37 Commits

Autor SHA1 Mensagem Data
Daniel Sloof 30b0fc0026 headers_list should return array() with no headers
headers_list should return an empty array when there are no
 headers. There were already tests involving this in ext_network.php, but it's
 being skipped (at least in the github repository).

Closes #1218

Reviewed By: @alexmalyshev

Differential Revision: D1030259

Pulled By: @scannell
2013-10-30 11:06:15 -07:00
Brett Simmers 4f78c7de03 Clear out request-local globals at the beginning of each request
The rpc server keeps the ExecutionContext alive across requests to
reduce startup costs. Unfortunately, we weren't clearing $_SESSION, $_GET,
etc... at the beginning of the request. This was making us think that most of
the http headers in most requests were duplicates, and emit a warning where the
option is enabled. It's also generally bad practice to leak this stuff between
different requests.

Reviewed By: @markw65

Differential Revision: D1010456
2013-10-30 11:06:04 -07:00
Paul Tarjan d6a8578e34 try to fix yii again
It turns out the path is unique to my machine. Try glob.

Reviewed By: @JoelMarcey

Differential Revision: D1031707
2013-10-30 11:05:53 -07:00
Paul Tarjan 085f510c23 don't call autoload handler with an empty class
Zend doesn't do it and we shouldn't either. It was causing an assert in a debug build.

Reviewed By: @markw65

Differential Revision: D1030881
2013-10-30 11:05:37 -07:00
mwilliams 1e1eac2a0e Fix fallback when optimized translation fails
analyze needs to read live state, which is only
valid if this is the first tracelet in the region. For
subsequent tracelets, fall back to the interpreter.

Reviewed By: @ottoni

Differential Revision: D1028657
2013-10-30 11:04:53 -07:00
Jordan DeLong 565465d580 Fix slow/intercept tests to pass DynamicInvokeFunctions to compiler
Modify one of the tests so it fails with the wrong options
and pass the right ones, add a similar test for static member
functions.  It appears DynamicInvokeFunction is ignored for member
functions (but member functions are inspected for a "dyn_" prefix??),
so I added norepo for the ones that do intercept on member functions.

Reviewed By: @swtaarrs

Differential Revision: D1029398
2013-10-30 11:03:05 -07:00
Sean Cannella 38be2694ae Fix linking issue on OS X 10.9 with libc++
ld on OS X 10.9 doesn't seem to be able to locate the ctype.h
functions (ex. isdigit) when they are used as function pointers, so wrap
them in lambdas.

Reviewed By: @markw65

Differential Revision: D1030137
2013-10-30 11:02:53 -07:00
Paul Tarjan d87b7c84fb stop yii from see-sawing
yii leaves this file around which is a duplicate of its test. So the autoloader loads it twice. Kill it between runs.

Reviewed By: @JoelMarcey

Differential Revision: D1030682
2013-10-30 11:02:30 -07:00
Herman Venter a8b31881f6 Fix the variable command so that it does not fail totally when one variable is too large.
The variable command, along with its clients the global command and the = command, obtained variable names and values from the server by asking for an map of variable name to variable values in a single request. If one or more of these variables have really large values, the serialization of the map exceeds the serialization limit and the entire command fails. This makes it difficult pin-point which variable causes the trouble and breaks the client commands in unexpected ways.

This diff changes the protocol of the variable command so that it first gets an array of variable names only and then separately gets the value of each variable. If such a separate get fails because of a serialization limit, the variable's value is printed as "...omitted".

Reviewed By: @mikemag

Differential Revision: D1021035
2013-10-30 11:00:11 -07:00
mwilliams bd49a4ac26 Fix retranslateOpt bug
If we've already optimized, we want to do a regular
translation, not an optimized one

Reviewed By: @ottoni

Differential Revision: D1026773
2013-10-30 10:59:14 -07:00
Joel Marcey c33c344f99 fix stream_select error
I am a clown.

Reviewed By: @ptarjan

Differential Revision: D1027352
2013-10-30 10:56:27 -07:00
aravind ec3d41f15f IncRef Sinking fix
An IncRef that is marked as a candidate for sinking should
be removed from the sinking list only if the corresponding DecRefNZ
is live.

Reviewed By: @ottoni

Differential Revision: D1026155
2013-10-30 10:54:54 -07:00
Alex Malyshev afc63c1ab6 Remove incorrect assert
We assert in DOMNode::{appendChild,insertBefore} that the node that
has been passed in is an orphaned node, however it's only orphaned if
it has no parent or its parent is also orphaned.

Fixes the last fatal in yii

Reviewed By: @ptarjan

Differential Revision: D1026211
2013-10-30 10:54:42 -07:00
Paul Tarjan b10c2021e2 set m_documentRoot even if there is no hdf
This variable is entirely independent of the hdf, so it should be set even it there isn't one.

This came up when someone (me) was running `hhvm -m server` from the symphony directory trying to show it off, but PATH_INFO doesn't work unless the m_documentRoot is set. It just assumes that all files exist if there is no document root.

This shouldn't affect anything in FB since there is always a `.hdf`.

Reviewed By: @markw65

Differential Revision: D1025781
2013-10-30 10:54:25 -07:00
mwilliams d04d9ec022 Fix jitted symbols in gdb 7.6
gdb traps calls to a function named __jit_debug_register_code,
and updates its internal symbol tables.

Apparently gdb-7.2 was prepared to demangle the name,
while gdb-7.6 is not.

Reviewed By: aravind

Differential Revision: D1026295
2013-10-30 10:54:10 -07:00
Sean Cannella 5a4db6875a StoreImmPatcher incorrectly handles 64-bit imms
StoreImmPatcher is currently subtracting the wrong offset (not
taking into account the extra instruction emitted) when setting m_addr.

Closes #1210

Reviewed By: @markw65

Differential Revision: D1025861
2013-10-30 10:53:44 -07:00
Bert Maher 251b5d78b4 Fix /stop command issued when hhvm can't bind port
When HHVM can't bind to a port it tries to shut down the
currently running instance using /stop on the admin port, but
RuntimeOption::ServerIP was blank (do we actually set this anywhere?)
and we weren't passing the admin password.

Reviewed By: @markw65

Differential Revision: D944849
2013-10-24 11:53:28 -07:00
Kristaps Kaupe d2ca7292fb Native.h macro typo
Fix macro typo

Reviewed By: @JoelMarcey

Differential Revision: D1023850

Pulled By: @scannell
2013-10-24 11:53:12 -07:00
Franck STAUFFER ebb9f3cadd row_count properly set on INSERT/UPDATES
Fixes bug due to variable shadowing

Closes #364

Reviewed By: @JoelMarcey

Differential Revision: D1021780

Pulled By: @scannell
2013-10-23 13:24:37 -07:00
Paul Tarjan b9d8d0ff47 fix ASAN bug in JSON parser
Wow, our json parser has diverged so much from zend. This is basicaly what theirs does. More importantly, this is correct.

Sadly I don't think is the memory corruption bug.

Reviewed By: @scannell

Differential Revision: D1021678
2013-10-23 13:24:08 -07:00
Herman Venter 73f16bc03b Fix list command so that it finds the right start line and it can find systemlib.php
The list command was using the the string "line2", cunningly disguised as the static string variable 'line1' to look for the line where a func/class/method starts. Also, the file name it got for systemlib.php was expected to always be exactly "systemlib.php" but it turns out this is no longer the case, or at least not always.

Reviewed By: @mikemag

Differential Revision: D1018535
2013-10-22 12:17:20 -07:00
Matthias Eck 540cac6ec2 Fixed step to skip generated functions
Changed cmd_step to check at onBeginInterrupt if the file line is empty i.e. returns as ":0"
In this case continue stepping

Reviewed By: @mikemag

Differential Revision: D1017420
2013-10-22 12:16:59 -07:00
Sara Golemon c20fcce91b Add missing define
Branch has some commits piled onto a non-fix diff on master.
They only really need this one line to work.
2013-10-21 21:37:38 -07:00
Yuval Hager 922a61dad5 Fix Buffer Overrun messages for tiff files
While processing tiff tags, the end pointer was not updated
after a realloc. Also, while processing IFD tag, end and begin pointers
were switched.

Closes #1154
Closes #1193

Reviewed By: @ptarjan

Differential Revision: D1019738

Pulled By: @scannell
2013-10-21 15:38:06 -07:00
Sean Cannella a568ad1a07 Import php-src pull #479
Fix clowny error in zend-strtod.cpp on ARM platforms that passed through the PHP internals mailing list

Reviewed By: @JoelMarcey

Differential Revision: D1019758
2013-10-21 15:37:29 -07:00
Sean Cannella 5815d21518 Fix ICU compliation when not using 51.x
'brew update' to a newer icu4c on OS X exposed that we aren't
being consistent in how we include it resulting in linker errors due to
confusion regarding what the icu namespace is.

Reviewed By: @sgolemon

Differential Revision: D1019529
2013-10-21 15:36:00 -07:00
Anton Grbin 757c1414f5 ArrayInit constructor ssize_t -> size_t
In ArrayInit constructor, n is defined as ssize_t, but negative values
are not handled in any way. We should point that out to callers by
making n of type size_t.

Reviewed By: @edwinsmith

Differential Revision: D1017631
2013-10-21 15:35:42 -07:00
Jordan DeLong a1745fb58b Fix a bug in AGet{L,C} and simplifyLdCls
If AGetL throws due to autoload failure (e.g. parse time
fatal), we crash in the unwinder.

Reviewed By: @bertmaher

Differential Revision: D1018048
2013-10-20 23:22:15 -07:00
aravind 20f0306dd3 Fixes for PGO mode
This fixes a couple of asserts I hit running www in DEBUG mode with
-vEval.JitPGO=1 -vEval.JitRegionSelector=hottrace
-vEval.JitPGOHotOnly=0.

Reviewed By: @ottoni

Differential Revision: D1016284
2013-10-19 00:37:51 -07:00
Alex Malyshev 8121dbb0d3 Fix three eval() bugs
* @ eval() was not being silenced correctly
* If the string passed to eval() hits a parse error, then the runtime
  is not supposed to fatal. We currently do.
* Errors in eval() code did not print a valid file name, they now
  print it as "$FILENAME($LINE1) : eval()'d code on line $LINE2"

Closes #945

Reviewed By: @jdelong

Differential Revision: D1006603
2013-10-19 00:37:41 -07:00
seanc 1177492d76 Fix CMake warning
Summary: Latest CMake on OS X with brew surfaced this warning and that
this check was not doing what it was originally intended to do.
2013-10-19 00:37:21 -07:00
Jordan DeLong 23cd8e033e Fix a bug in TypeConstraint::isSoft
This function returned true if the type had isHHType(), which
it will always if EnableHipHopSyntax=1.  The flag was 0x16 instead of
0x10, and isSoft() just does return m_flags & Soft.

Reviewed By: @dariorussi

Differential Revision: D1014812
2013-10-17 23:44:08 -07:00
Alex Malyshev 6050afa844 Emit an error message when our PHP systemlib doesn't compile
Fixes the terrible "Undefined interface: arrayaccess" error message

Reviewed By: @jdelong

Differential Revision: D1014257
2013-10-17 23:43:56 -07:00
mwilliams 98a2c6ede2 Fix TranslatorX64::m_mode
We need to ensure that m_mode is reset after each
translation attempt.

There was already code in TranslatorX64::translate to reset
it, but after setting it in TranslatorX64::retranslateOpt,
its not certain that we'll get there.

Reviewed By: @swtaarrs

Differential Revision: D1012330
2013-10-17 23:43:43 -07:00
James Miller e766a8a4ac Make the embedded systemlib a dependency of the binary 2013-10-17 23:43:23 -07:00
James Miller 5b7366968a Fix broken make install behaviour
CMake uses rpath to make it easier to run built executables from the build
tree without installing prerequisite libraries first. This means that when
installing, CMake will re-link the binary in order to change the rpath so
it works properly in an install. Unfortunately, it's not smart enough to know
to re-embed the systemlib section, so the installed `hhvm` binary does not
have a systemlib section and doesn't work.

This commit adds a cmake function `HHVM_INSTALL` that effectively bypasses the
standard install command to ensure that the binary is not relinked. To help
with rpaths, this also checks for the existance of the `chrpath` tool. If it
exists, it uses it to either remove or replace the rpath entry in the file,
otherwise it just leaves the rpath entry alone.

This allows `make install` to work again.
2013-10-17 23:42:56 -07:00
Sara Golemon 2d963c4ffb 2.2.0 release 2013-10-16 11:17:06 -07:00
14342 arquivos alterados com 201065 adições e 872719 exclusões
+19 -4
Ver Arquivo
@@ -1,5 +1,10 @@
*.[oad]
*.hhbc
/bin*-g
/bin*-O
/bin/*.so
/bin/hphp_options
/bin/systemlib.php
.mkdir
hphp.log
@@ -32,8 +37,16 @@ hphp.log
/hphp/hhvm/gen
/hphp/hhvm/hhvm
*.ext_hhvm.cpp
*.ext_hhvm.h
/hphp/runtime/ext/*.ext_hhvm.cpp
/hphp/runtime/ext/*.ext_hhvm.h
/hphp/runtime/ext/*/*.ext_hhvm.cpp
/hphp/runtime/ext/*/*.ext_hhvm.h
/hphp/runtime/ext_zend_compat/*/*.ext_hhvm.cpp
/hphp/runtime/ext_zend_compat/*/*.ext_hhvm.h
/hphp/runtime/ext_zend_compat/*/*/*.ext_hhvm.cpp
/hphp/runtime/ext_zend_compat/*/*/*.ext_hhvm.h
/hphp/runtime/base/builtin-functions.cpp.ext_hhvm.cpp
/hphp/runtime/base/builtin-functions.cpp.ext_hhvm.h
/hphp/runtime/ext_hhvm/ext_hhvm_infotabs.cpp
/hphp/runtime/ext_hhvm/ext_hhvm_infotabs.h
@@ -42,6 +55,10 @@ hphp.log
/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
@@ -51,8 +68,6 @@ install_manifest.txt
/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
+8 -20
Ver Arquivo
@@ -4,35 +4,23 @@ compiler:
- gcc
before_script:
- time TRAVIS=1 ./configure_ubuntu_12.04.sh
- TRAVIS=1 ./configure_ubuntu_12.04.sh
# for some tests
- time sudo locale-gen de_DE && sudo locale-gen zh_CN.utf8 && sudo locale-gen fr_FR
- time HPHP_HOME=`pwd` make -j 6
# mysql configuration for unit-tests
- mysql -e 'CREATE DATABASE IF NOT EXISTS hhvm;'
- export PDO_MYSQL_TEST_DSN="mysql:host=127.0.0.1;dbname=hhvm"
- export PDO_MYSQL_TEST_USER="travis"
- export PDO_MYSQL_TEST_PASS=""
- sudo locale-gen de_DE && sudo locale-gen zh_CN.utf8 && sudo locale-gen fr_FR
- HPHP_HOME=`pwd` make -j 6
# Test suites take longer to run in RepoAuthoritative mode (-r) than normal so
# split out the -r from normal runs and further split the -r runs by suite to
# avoid the possibility of slower machines exceeding the 50 minute test timeout
env:
- TEST_RUN_MODE="-m jit quick"
- TEST_RUN_MODE="-m jit slow"
- TEST_RUN_MODE="-m jit zend"
- TEST_RUN_MODE="-m jit -r quick"
- TEST_RUN_MODE="-m jit -r slow"
- TEST_RUN_MODE="-m jit all"
- TEST_RUN_MODE="-m interp all"
- TEST_RUN_MODE="-m jit -r quick slow"
- TEST_RUN_MODE="-m interp -r quick slow"
- TEST_RUN_MODE="-m jit -r zend"
- TEST_RUN_MODE="-m interp quick"
- TEST_RUN_MODE="-m interp slow"
- TEST_RUN_MODE="-m interp zend"
- TEST_RUN_MODE="-m interp -r quick"
- TEST_RUN_MODE="-m interp -r slow"
- TEST_RUN_MODE="-m interp -r zend"
script: time hphp/hhvm/hhvm hphp/test/run $TEST_RUN_MODE
script: hphp/hhvm/hhvm hphp/test/run $TEST_RUN_MODE
notifications:
email: false
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()
-16
Ver Arquivo
@@ -1,16 +0,0 @@
find_package(PkgConfig)
pkg_check_modules(PC_FREETYPE QUIET freetype2)
find_path(FREETYPE_INCLUDE_DIRS NAMES freetype/config/ftheader.h
HINTS ${PC_FREETYPE_INCLUDEDIR} ${PC_FREETYPE_INCLUDE_DIRS}
PATH_SUFFIXES freetype2)
find_library(FREETYPE_LIBRARIES NAMES freetype)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Freetype DEFAULT_MSG
FREETYPE_LIBRARIES
FREETYPE_INCLUDE_DIRS)
mark_as_advanced(FREETYPE_INCLUDE_DIRS FREETYPE_LIBRARIES)
+121
Ver Arquivo
@@ -0,0 +1,121 @@
# - Find GD
# Find the native GD includes and library
# This module defines
# GD_INCLUDE_DIR, where to find gd.h, etc.
# GD_LIBRARIES, the libraries needed to use GD.
# GD_FOUND, If false, do not try to use GD.
# also defined, but not for general use are
# GD_LIBRARY, where to find the GD library.
# GD_SUPPORTS_PNG, GD_SUPPORTS_JPEG, GD_SUPPORTS_GIF, test
# support for image formats in GD.
FIND_PATH(GD_INCLUDE_DIR gd.h
/usr/local/include
/usr/include
)
if(WIN32 AND NOT CYGWIN)
SET(GD_NAMES ${GD_NAMES} bgd)
else(WIN32)
SET(GD_NAMES ${GD_NAMES} gd)
endif(WIN32 AND NOT CYGWIN)
FIND_LIBRARY(GD_LIBRARY
NAMES ${GD_NAMES}
PATHS /usr/lib64 /usr/lib /usr/local/lib
)
IF (GD_LIBRARY AND GD_INCLUDE_DIR)
SET(GD_LIBRARIES ${GD_LIBRARY})
SET(GD_FOUND "YES")
ELSE (GD_LIBRARY AND GD_INCLUDE_DIR)
SET(GD_FOUND "NO")
ENDIF (GD_LIBRARY AND GD_INCLUDE_DIR)
IF (GD_FOUND)
IF (WIN32 AND NOT CYGWIN)
SET(GD_SUPPORTS_PNG ON)
SET(GD_SUPPORTS_JPEG ON)
SET(GD_SUPPORTS_GIF ON)
get_filename_component(GD_LIBRARY_DIR ${GD_LIBRARY} PATH)
ELSE (WIN32 AND NOT CYGWIN)
INCLUDE(CheckLibraryExists)
GET_FILENAME_COMPONENT(GD_LIB_PATH ${GD_LIBRARY} PATH)
GET_FILENAME_COMPONENT(GD_LIB ${GD_LIBRARY} NAME)
CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImagePng" "${GD_LIB_PATH}" GD_SUPPORTS_PNG)
IF (GD_SUPPORTS_PNG)
find_package(PNG)
IF (PNG_FOUND)
SET(GD_LIBRARIES ${GD_LIBRARIES} ${PNG_LIBRARIES})
SET(GD_INCLUDE_DIR ${GD_INCLUDE_DIR} ${PNG_INCLUDE_DIR})
ELSE (PNG_FOUND)
SET(GD_SUPPORTS_PNG "NO")
ENDIF (PNG_FOUND)
ENDIF (GD_SUPPORTS_PNG)
CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImageJpeg" "${GD_LIB_PATH}" GD_SUPPORTS_JPEG)
IF (GD_SUPPORTS_JPEG)
find_package(JPEG)
IF (JPEG_FOUND)
SET(GD_LIBRARIES ${GD_LIBRARIES} ${JPEG_LIBRARIES})
SET(GD_INCLUDE_DIR ${GD_INCLUDE_DIR} ${JPEG_INCLUDE_DIR})
ELSE (JPEG_FOUND)
SET(GD_SUPPORTS_JPEG "NO")
ENDIF (JPEG_FOUND)
ENDIF (GD_SUPPORTS_JPEG)
CHECK_LIBRARY_EXISTS("${GD_LIBRARY}" "gdImageGif" "${GD_LIB_PATH}" GD_SUPPORTS_GIF)
# Trim the list of include directories
SET(GDINCTRIM)
FOREACH(GD_DIR ${GD_INCLUDE_DIR})
SET(GD_TMP_FOUND OFF)
FOREACH(GD_TRIMMED ${GDINCTRIM})
IF ("${GD_DIR}" STREQUAL "${GD_TRIMMED}")
SET(GD_TMP_FOUND ON)
ENDIF ("${GD_DIR}" STREQUAL "${GD_TRIMMED}")
ENDFOREACH(GD_TRIMMED ${GDINCTRIM})
IF (NOT GD_TMP_FOUND)
SET(GDINCTRIM "${GDINCTRIM}" "${GD_DIR}")
ENDIF (NOT GD_TMP_FOUND)
ENDFOREACH(GD_DIR ${GD_INCLUDE_DIR})
SET(GD_INCLUDE_DIR ${GDINCTRIM})
SET(GD_LIBRARY_DIR)
# Generate trimmed list of library directories and list of libraries
FOREACH(GD_LIB ${GD_LIBRARIES})
GET_FILENAME_COMPONENT(GD_NEXTLIBDIR ${GD_LIB} PATH)
SET(GD_TMP_FOUND OFF)
FOREACH(GD_LIBDIR ${GD_LIBRARY_DIR})
IF ("${GD_NEXTLIBDIR}" STREQUAL "${GD_LIBDIR}")
SET(GD_TMP_FOUND ON)
ENDIF ("${GD_NEXTLIBDIR}" STREQUAL "${GD_LIBDIR}")
ENDFOREACH(GD_LIBDIR ${GD_LIBRARIES})
IF (NOT GD_TMP_FOUND)
SET(GD_LIBRARY_DIR "${GD_LIBRARY_DIR}" "${GD_NEXTLIBDIR}")
ENDIF (NOT GD_TMP_FOUND)
ENDFOREACH(GD_LIB ${GD_LIBRARIES})
ENDIF (WIN32 AND NOT CYGWIN)
ENDIF (GD_FOUND)
IF (GD_FOUND)
IF (NOT GD_FIND_QUIETLY)
MESSAGE(STATUS "Found GD: ${GD_LIBRARY}")
ENDIF (NOT GD_FIND_QUIETLY)
ELSE (GD_FOUND)
IF (GD_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find GD library")
ENDIF (GD_FIND_REQUIRED)
ENDIF (GD_FOUND)
MARK_AS_ADVANCED(
GD_LIBRARY
GD_LIBRARIES
GD_INCLUDE_DIR
GD_LIBRARY_DIR
GD_SUPPORTS_PNG
GD_SUPPORTS_JPEG
GD_SUPPORTS_GIF
)
+1 -9
Ver Arquivo
@@ -18,7 +18,7 @@ endif (LIBDWARF_LIBRARIES AND LIBDWARF_INCLUDE_DIRS)
find_path (DWARF_INCLUDE_DIR
NAMES
libdwarf.h dwarf.h
dwarf.h
PATHS
/usr/include
/usr/include/libdwarf
@@ -50,13 +50,5 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibDwarf DEFAULT_MSG
LIBDWARF_LIBRARIES
LIBDWARF_INCLUDE_DIRS)
if (LIBDWARF_LIBRARIES AND LIBDWARF_INCLUDE_DIRS)
set(CMAKE_REQUIRED_INCLUDES ${LIBDWARF_INCLUDE_DIRS})
set(CMAKE_REQUIRED_LIBRARIES ${LIBDWARF_LIBRARIES})
include(CheckSymbolExists)
CHECK_SYMBOL_EXISTS(dwarf_encode_leb128 "libdwarf.h" LIBDWARF_HAVE_ENCODE_LEB128)
endif()
mark_as_advanced(LIBDW_INCLUDE_DIR DWARF_INCLUDE_DIR)
mark_as_advanced(LIBDWARF_INCLUDE_DIRS LIBDWARF_LIBRARIES)
mark_as_advanced(LIBDWARF_HAVE_ENCODE_LEB128)
-14
Ver Arquivo
@@ -1,14 +0,0 @@
if (LIBJPEG_LIBRARIES AND LIBJPEG_INCLUDE_DIRS)
set (LibJpeg_FIND_QUIETLY TRUE)
endif (LIBJPEG_LIBRARIES AND LIBJPEG_INCLUDE_DIRS)
find_path(LIBJPEG_INCLUDE_DIRS NAMES jpeglib.h)
find_library(LIBJPEG_LIBRARIES NAMES jpeg)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibJpeg DEFAULT_MSG
LIBJPEG_LIBRARIES
LIBJPEG_INCLUDE_DIRS)
mark_as_advanced(LIBJPEG_INCLUDE_DIRS LIBJPEG_LIBRARIES)
-14
Ver Arquivo
@@ -1,14 +0,0 @@
if (LIBPNG_LIBRARIES AND LIBPNG_INCLUDE_DIRS)
set (LibPng_FIND_QUIETLY TRUE)
endif (LIBPNG_LIBRARIES AND LIBPNG_INCLUDE_DIRS)
find_path(LIBPNG_INCLUDE_DIRS NAMES png.h)
find_library(LIBPNG_LIBRARIES NAMES png)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibPng DEFAULT_MSG
LIBPNG_LIBRARIES
LIBPNG_INCLUDE_DIRS)
mark_as_advanced(LIBPNG_INCLUDE_DIRS LIBPNG_LIBRARIES)
-12
Ver Arquivo
@@ -1,12 +0,0 @@
if (LIBODBC_LIBRARIES AND LIBODBC_INCLUDE_DIRS)
set (LibUODBC_FIND_QUIETLY TRUE)
endif (LIBODBC_LIBRARIES AND LIBODBC_INCLUDE_DIRS)
find_path (LIBODBC_INCLUDE_DIRS NAMES sqlext.h)
find_library (LIBODBC_LIBRARIES NAMES odbc)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibUODBC DEFAULT_MSG
LIBODBC_LIBRARIES
LIBODBC_INCLUDE_DIRS)
mark_as_advanced(LIBODBC_INCLUDE_DIRS LIBODBC_LIBRARIES)
-14
Ver Arquivo
@@ -1,14 +0,0 @@
if (LIBVPX_LIBRARIES AND LIBVPX_INCLUDE_DIRS)
set (LibVpx_FIND_QUIETLY TRUE)
endif (LIBVPX_LIBRARIES AND LIBVPX_INCLUDE_DIRS)
find_path(LIBVPX_INCLUDE_DIRS NAMES vpx_codec.h)
find_library(LIBVPX_LIBRARIES NAMES vpx)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibVpx DEFAULT_MSG
LIBVPX_LIBRARIES
LIBVPX_INCLUDE_DIRS)
mark_as_advanced(LIBVPX_INCLUDE_DIRS LIBVPX_LIBRARIES)
-13
Ver Arquivo
@@ -1,13 +0,0 @@
if (LibYaml_LIBRARIES AND LibYaml_INCLUDE_DIRS)
set (LibYaml_FIND_QUIETLY TRUE)
endif (LibYaml_LIBRARIES AND LibYaml_INCLUDE_DIRS)
find_path (LibYaml_INCLUDE_DIRS NAMES yaml.h)
find_library (LibYaml_LIBRARIES NAMES yaml)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibYaml DEFAULT_MSG
LibYaml_LIBRARIES
LibYaml_INCLUDE_DIRS)
mark_as_advanced(LibYaml_INCLUDE_DIRS LibYaml_LIBRARIES)
-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()
+17 -12
Ver Arquivo
@@ -1,5 +1,14 @@
if(CMAKE_COMPILER_IS_GNUCC)
INCLUDE(CheckCSourceCompiles)
CHECK_C_SOURCE_COMPILES("#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION < 40600
#error Need GCC 4.6.0+
#endif
int main() { return 0; }" HAVE_GCC_46)
if(NOT HAVE_GCC_46)
message(FATAL_ERROR "Need at least GCC 4.6")
endif()
CHECK_C_SOURCE_COMPILES("#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION < 40700
@@ -7,10 +16,6 @@ if(CMAKE_COMPILER_IS_GNUCC)
#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+
@@ -32,18 +37,18 @@ 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")
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(GNUCC_48_OPT "")
set(GNUCC_UNINIT_OPT "")
if(HAVE_GCC_47)
set(GNUCC_UNINIT_OPT "-Wno-maybe-uninitialized")
endif()
set(GNUCC_LOCAL_TYPEDEF_OPT "")
if(HAVE_GCC_48)
set(GNUCC_48_OPT "-Wno-unused-local-typedefs -fno-canonical-system-headers -Wno-deprecated-declarations")
set(GNUCC_LOCAL_TYPEDEF_OPT "-Wno-unused-local-typedefs")
endif()
set(CMAKE_C_FLAGS "-w")
set(CMAKE_CXX_FLAGS "-fno-gcse -fno-omit-frame-pointer -ftemplate-depth-180 -Wall -Woverloaded-virtual -Wno-deprecated -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names -Wno-error=array-bounds -Wno-error=switch -std=gnu++11 -Werror=format-security -Wno-unused-result -Wno-sign-compare -Wno-attributes -Wno-maybe-uninitialized -mcrc32 ${GNUCC_48_OPT}")
endif()
if(${CMAKE_CXX_COMPILER} MATCHES ".*clang.*")
set(CMAKE_CXX_FLAGS "-fno-gcse -fno-omit-frame-pointer -ftemplate-depth-180 -Wall -Woverloaded-virtual -Wno-deprecated -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names -Wno-error=array-bounds -Wno-error=switch -std=gnu++11 -Werror=format-security -Wno-unused-result -Wno-sign-compare -Wno-attributes -Wno-maybe-uninitialized -Wno-mismatched-tags -Wno-unknown-warning-option -Wno-return-type-c-linkage -Qunused-arguments")
set(CMAKE_CXX_FLAGS "-fno-gcse -fno-omit-frame-pointer -ftemplate-depth-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 -Wno-attributes ${GNUCC_UNINIT_OPT} ${GNUCC_LOCAL_TYPEDEF_OPT}")
endif()
if(CMAKE_COMPILER_IS_GNUCC)
+19 -76
Ver Arquivo
@@ -31,11 +31,6 @@ endif()
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)
@@ -90,46 +85,22 @@ 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")
endif()
find_package(GD REQUIRED)
# libXed
find_package(LibXed)
if (LibXed_INCLUDE_DIR AND LibXed_LIBRARY)
include_directories(${LibXed_INCLUDE_DIR})
add_definitions("-DHAVE_LIBXED")
add_definitions(-DHAVE_LIBXED)
endif()
# CURL checks
@@ -165,7 +136,6 @@ 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")
# ICU
find_package(ICU REQUIRED)
@@ -319,9 +289,6 @@ include_directories(${CCLIENT_INCLUDE_PATH})
find_package(LibDwarf REQUIRED)
include_directories(${LIBDWARF_INCLUDE_DIRS})
if (LIBDWARF_HAVE_ENCODE_LEB128)
add_definitions("-DHAVE_LIBDWARF_20130729")
endif()
find_package(LibElf REQUIRED)
include_directories(${LIBELF_INCLUDE_DIRS})
@@ -335,26 +302,17 @@ 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)
@@ -488,21 +446,7 @@ endif()
target_link_libraries(${target} ${ONIGURUMA_LIBRARIES})
target_link_libraries(${target} ${Mcrypt_LIB})
target_link_libraries(${target} ${GD_LIBRARY})
if (FREETYPE_LIBRARIES)
target_link_libraries(${target} ${FREETYPE_LIBRARIES})
endif()
if (LIBJPEG_LIBRARIES)
target_link_libraries(${target} ${LIBJPEG_LIBRARIES})
endif()
if (LIBPNG_LIBRARIES)
target_link_libraries(${target} ${LIBPNG_LIBRARIES})
endif()
if (LIBVPX_LIBRARIES)
target_link_libraries(${target} ${LIBVPX_LIBRARIES})
endif()
if (LIBUODBC_LIBRARIES)
target_link_libraries(${target} ${LIBUODBC_LIBRARIES})
endif()
target_link_libraries(${target} ${LDAP_LIBRARIES})
target_link_libraries(${target} ${LBER_LIBRARIES})
@@ -518,7 +462,6 @@ endif()
target_link_libraries(${target} lz4)
target_link_libraries(${target} double-conversion)
target_link_libraries(${target} folly)
target_link_libraries(${target} zip_static)
target_link_libraries(${target} afdt)
target_link_libraries(${target} mbfl)
@@ -532,7 +475,7 @@ endif()
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()
+5 -40
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)
@@ -89,34 +68,20 @@ macro(MYSQL_SOCKET_SEARCH)
endif()
endmacro()
function(embed_systemlib TARGET DEST SOURCE SECTNAME)
function(embed_systemlib TARGET DEST SOURCE)
if (APPLE)
target_link_libraries(${TARGET} -Wl,-sectcreate,__text,${SECTNAME},${SOURCE})
target_link_libraries(${TARGET} -Wl,-sectcreate,__text,systemlib,${SOURCE})
else()
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND "objcopy"
ARGS "--add-section" "${SECTNAME}=${SOURCE}" ${DEST}
COMMENT "Embedding ${SOURCE} in ${TARGET} as ${SECTNAME}")
ARGS "--add-section" "systemlib=${SOURCE}" ${DEST}
COMMENT "Embedding systemlib.php in ${TARGET}")
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)
@@ -143,5 +108,5 @@ function(HHVM_EXTENSION EXTNAME)
endfunction()
function(HHVM_SYSTEMLIB EXTNAME SOURCE_FILE)
embed_systemlib(${EXTNAME} "${EXTNAME}.so" ${SOURCE_FILE} systemlib)
embed_systemlib(${EXTNAME} "${EXTNAME}.so" ${SOURCE_FILE})
endfunction()
+4 -26
Ver Arquivo
@@ -1,18 +1,9 @@
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)
if (APPLE)
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)
set(HHVM_ANCHOR_SYMS -Wl,-uregister_libevent_server)
endif()
set(HHVM_LINK_LIBRARIES
@@ -23,15 +14,9 @@ set(HHVM_LINK_LIBRARIES
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()
@@ -62,7 +47,8 @@ include(HPHPCompiler)
include(HPHPFunctions)
include(HPHPFindLibs)
add_definitions(-D_REENTRANT=1 -D_PTHREADS=1 -D__STDC_FORMAT_MACROS -DFOLLY_HAVE_WEAK_SYMBOLS=1)
add_definitions(-D_REENTRANT=1 -D_PTHREADS=1 -D__STDC_FORMAT_MACROS)
add_definitions(-DHHVM_LIB_PATH_DEFAULT="${HPHP_HOME}/bin")
if (LINUX)
add_definitions(-D_GNU_SOURCE)
@@ -119,14 +105,6 @@ if(APPLE)
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)
-3
Ver Arquivo
@@ -13,6 +13,3 @@ option(USE_JEMALLOC "Use jemalloc" ON)
option(USE_TCMALLOC "Use tcmalloc (if jemalloc is not used)" ON)
option(USE_GOOGLE_HEAP_PROFILER "Use Google heap profiler" OFF)
option(USE_GOOGLE_CPU_PROFILER "Use Google cpu profiler" OFF)
option(DISABLE_HARDWARE_COUNTERS "Disable hardware counters (for XenU systems)" OFF)
+21 -11
Ver Arquivo
@@ -1,18 +1,18 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.7 FATAL_ERROR)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5 FATAL_ERROR)
PROJECT(hphp C CXX ASM)
IF(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
message(FATAL_ERROR "HHVM requires a 64bit OS")
IF("$ENV{HPHP_HOME}" STREQUAL "")
message(FATAL_ERROR "You should set the HPHP_HOME environmental")
ENDIF()
set(HPHP_HOME "$ENV{HPHP_HOME}")
if (NOT HPHP_HOME)
set(HPHP_HOME "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
message("Using HPHP_HOME == ${HPHP_HOME}")
file(TO_CMAKE_PATH "$ENV{HPHP_HOME}" HPHP_HOME)
IF(NOT EXISTS "${HPHP_HOME}/CMake/HPHPSetup.cmake")
message(FATAL_ERROR "Invalid HPHP_HOME. Set it to the root of your hhvm tree, or run `cmake .` from there.")
IF(NOT IS_DIRECTORY ${HPHP_HOME})
message(FATAL_ERROR "The value of HPHP_HOME does not exist")
ENDIF()
IF(NOT EXISTS "${HPHP_HOME}/LICENSE.PHP")
message(FATAL_ERROR "The value of HPHP_HOME in incorrect")
ENDIF()
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})
@@ -20,5 +20,15 @@ SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH})
include("${CMAKE_CURRENT_SOURCE_DIR}/CMake/HPHPFunctions.cmake")
include(CheckFunctionExists)
add_subdirectory(hphp)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/hphp)
IF(CMAKE_SIZEOF_VOID_P EQUAL 4)
message(FATAL_ERROR "32-bit support is currently unsupported, check back with a later version of HipHop")
ENDIF()
if ("$ENV{USE_HHVM}" STREQUAL "1")
message("Building for HHVM")
endif()
if ("$ENV{USE_HPHPC}" STREQUAL "1")
message(FATAL_ERROR "Building HPHPc is no longer supported")
endif()
+13 -13
Ver Arquivo
@@ -1,46 +1,46 @@
# HHVM [![Build Status](https://travis-ci.org/facebook/hhvm.png?branch=master)](https://travis-ci.org/facebook/hhvm)
# HipHop VM for PHP [![Build Status](https://travis-ci.org/facebook/hiphop-php.png?branch=master)](https://travis-ci.org/facebook/hiphop-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 VM (HHVM) 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. HipHop VM (and before it HPHPc) has realized > 5x increase in throughput for Facebook compared with Zend PHP 5.2.
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.
HipHop is most commonly run as a standalone server, replacing both Apache and modphp.
## FAQ
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.
Our [FAQ](https://github.com/facebook/hiphop-php/wiki/FAQ) has answers to many common questions about HHVM, from [general questions](https://github.com/facebook/hiphop-php/wiki/FAQ#general) to questions geared towards those that want to [use](https://github.com/facebook/hiphop-php/wiki/FAQ#users) or [contribute](https://github.com/facebook/hiphop-php/wiki/FAQ#contributors) to HHVM.
## Installing
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).
You can install a [prebuilt package](https://github.com/facebook/hiphop-php/wiki#installing-pre-built-packages-for-hhvm) or [compile from source](https://github.com/facebook/hiphop-php/wiki#building-hhvm).
## Running
You can run standalone programs just by passing them to hhvm: `hhvm my_script.php`.
HHVM bundles in a webserver. So if you want to run on port 80 in the current directory:
HipHop bundles in a webserver. So if you want to run on port 80 in the current directory:
```
sudo hhvm -m server
```
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`.
For anything more complicated, you'll want to make a [config.hdf](https://github.com/facebook/hiphop-php/wiki/Runtime-options#server) and run `sudo hhvm -m server -c config.hdf`.
## Contributing
We'd love to have your help in making HHVM better.
We'd love to have your help in making HipHop better.
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.
Before changes can be accepted a [Contributor License 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.
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).
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](https://github.com/facebook/hiphop-php/pulls). Join us on [#hhvm on freenode](http://webchat.freenode.net/?channels=hhvm).
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/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.
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. 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.
## License
HHVM is licensed under the PHP and Zend licenses except as otherwise noted.
HipHop VM 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.
See [Reporting Crashes](https://github.com/facebook/hiphop-php/wiki/Reporting-Crashes) for helpful tips on how to report crashes in an actionable manner.
+1
Ver Arquivo
@@ -0,0 +1 @@
This file just exists to keep the bin/ directory in git.
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
+8 -30
Ver Arquivo
@@ -1,6 +1,6 @@
#########################################
#
# Install all the dependencies for HipHop
# Install all the dependancies for HipHop
#
#########################################
@@ -20,15 +20,12 @@ if [ "x${TRAVIS}" != "x" ]; then
fi
export CMAKE_PREFIX_PATH=`/bin/pwd`/..
export HPHP_HOME=`/bin/pwd`
# install python-software-properties before trying to add a PPA
sudo apt-get -y update
sudo apt-get install -y python-software-properties
# install apt-fast to speed up later dependency installation
# install apt-fast to speedup later dependency installation
sudo add-apt-repository -y ppa:apt-fast/stable
sudo apt-get -y update
sudo apt-get -y install apt-fast
sudo apt-get update
sudo apt-get install apt-fast
# install the actual dependencies
sudo apt-fast -y update
@@ -36,8 +33,8 @@ 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 \
libboost-program-options1.48-dev libboost-filesystem1.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 &
@@ -46,9 +43,6 @@ 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
@@ -66,22 +60,6 @@ else
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
@@ -123,4 +101,4 @@ cmake .
echo "-------------------------------------------------------------------------"
echo "Done. Now run:"
echo " CMAKE_PREFIX_PATH=\`pwd\`/.. make"
echo " CMAKE_PREFIX_PATH=\`pwd\`/.. HPHP_HOME=\`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
+50 -13
Ver Arquivo
@@ -16,12 +16,44 @@
#
include(HPHPSetup)
include(FollySetup)
include(ExtZendCompat)
add_definitions("-DHHVM")
# HHVM Build
SET(USE_HHVM TRUE)
SET(ENV{HHVM} 1)
ADD_DEFINITIONS("-DHHVM -DHHVM_BINARY=1 -DHHVM_PATH=\\\"${HPHP_HOME}/hphp/hhvm/hhvm\\\"")
add_subdirectory(tools/bootstrap)
set(RECURSIVE_SOURCE_SUBDIRS runtime/base runtime/debugger runtime/eval runtime/ext runtime/server runtime/vm)
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})
auto_sources(files "*.S" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
list(APPEND ASM_SOURCES ${files})
endforeach(dir ${RECURSIVE_SOURCE_SUBDIRS})
if(NOT LINUX)
add_definitions(-DNO_HARDWARE_COUNTERS)
list(REMOVE_ITEM CXX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/runtime/vm/debug/elfwriter.cpp)
endif()
# Not working with off-the-shelf libevent
list(REMOVE_ITEM CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/runtime/server/server-name-indication.cpp")
# remove ext_hhvm, and anything in a test folder
foreach (file ${CXX_SOURCES})
if (${file} MATCHES "ext_hhvm")
list(REMOVE_ITEM CXX_SOURCES ${file})
endif()
if (${file} MATCHES "/test/")
list(REMOVE_ITEM CXX_SOURCES ${file})
endif()
endforeach(file ${CXX_SOURCES})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
add_subdirectory(third_party/libafdt)
add_subdirectory(third_party/libmbfl)
@@ -30,11 +62,19 @@ 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_LIBRARY(hphp_runtime_static STATIC
${CXX_SOURCES} ${C_SOURCES} ${ASM_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_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>")
hphp_link(hphp_runtime_static)
add_dependencies(hphp_runtime_static hphp_parser)
add_subdirectory("tools/bootstrap")
add_subdirectory(vixl)
add_subdirectory(neo)
@@ -42,13 +82,10 @@ add_subdirectory(parser)
add_subdirectory(zend)
add_subdirectory(util)
add_subdirectory(hhbbc)
add_subdirectory(compiler)
add_subdirectory(runtime)
add_subdirectory(runtime/ext_hhvm)
add_subdirectory(system)
add_subdirectory(hhvm)
add_subdirectory(system)
if (NOT "$ENV{HPHP_NOTEST}" STREQUAL "1")
add_subdirectory(test)
+7 -102
Ver Arquivo
@@ -1,104 +1,9 @@
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
- <cool stuff goes here>
"Sausage" 14-Oct-2013
- Direct invocation of callable arrays: $f = [$cls_or_obj, 'method']; $f()
- Fixed issue that caused memory_get_usage to report double the actual usage.
- Direct invocation of callable arrays: $f = [$cls_or_instance, 'method']; $f()
- ASAN clean
- Support dynamically loadable extensions
- Support loading mini-systemlibs from extensions
@@ -120,7 +25,7 @@ Next release
- Support arbitrary expressions inside empty()
"Bobotie" 16-Sep-2013
- HNI (HipHop Native Interface) for calling C++ functions from PHP
- HNI (HipHop Native Interface) for calling C++ functions from Php
- Fix PropertyAccessorMap::isset
- Expose more POSIX constants
- Fixed behavior of stream_get_contents when default args are used.
@@ -134,14 +39,14 @@ Next release
- Import ftp extension
"Kimchi" 2-Sep-2013
- Fix order of custom attributes and visibility in ctor arg promotion
- Fix order of custom attributes and visibility in ctor arg promotion
- Implement CachingIterator
- Implement RecursiveCachingIterator
- Generalized heuristic for choosing when to inline in the jit
- Introduced a Zend compatibility layer to compile extensions
- Imported calendar extension
- Use gcc-4.8.1 by default
- Improve hhvm command line parsing logic
- Improve hhvm commandline parsing logic
- Fix register_shutdown in session_set_save_handler to match PHP 5.4
- Add "native" functions for use in Systemlib
- PHP extension source-compatitblility layer
@@ -199,7 +104,7 @@ Next release
"Wasabi Peas" 08-Jul-2013
- always_assert when we run out of TC space
- Initial changes to get HHVM compiling on OSX
- Consolidate ObjectData and Instance
- Consolodate ObjectData and Instance
- Prototype heap tracing framework & Heap profiler
- Better JIT code generation for Mod and Div
- Fixes to enable compilation with clang
+14 -16
Ver Arquivo
@@ -66,7 +66,7 @@
#include "hphp/compiler/analysis/live_dict.h"
#include "hphp/compiler/analysis/ref_dict.h"
#include "hphp/runtime/vm/runtime.h"
#include "hphp/runtime/base/builtin-functions.h"
#include "hphp/parser/hphp.tab.hpp"
#include "hphp/parser/location.h"
@@ -1927,7 +1927,6 @@ StatementPtr AliasManager::canonicalizeRecur(StatementPtr s, int &ret) {
switch (stype) {
case Statement::KindOfUseTraitStatement:
case Statement::KindOfTraitRequireStatement:
case Statement::KindOfTraitPrecStatement:
case Statement::KindOfTraitAliasStatement:
return StatementPtr();
@@ -1969,7 +1968,7 @@ StatementPtr AliasManager::canonicalizeRecur(StatementPtr s, int &ret) {
}
case Statement::KindOfIfBranchStatement:
always_assert(false);
always_assert(0);
break;
case Statement::KindOfForStatement: {
@@ -2109,6 +2108,7 @@ int AliasManager::collectAliasInfoRecur(ConstructPtr cs, bool unused) {
}
cs->clearVisited();
cs->clearChildOfYield();
StatementPtr s = dpc(Statement, cs);
if (s) {
@@ -2361,6 +2361,9 @@ int AliasManager::collectAliasInfoRecur(ConstructPtr cs, bool unused) {
case Expression::KindOfSimpleFunctionCall:
{
SimpleFunctionCallPtr sfc(spc(SimpleFunctionCall, e));
if (sfc->getName() == "hphp_create_continuation") {
m_inlineAsExpr = false;
}
sfc->updateVtFlags();
}
case Expression::KindOfDynamicFunctionCall:
@@ -2396,6 +2399,9 @@ int AliasManager::collectAliasInfoRecur(ConstructPtr cs, bool unused) {
// expressions. TODO: revisit this later
m_inlineAsExpr = false;
break;
case Expression::KindOfYieldExpression:
spc(YieldExpression, e)->getValueExpression()->setChildOfYield();
break;
case Expression::KindOfUnaryOpExpression:
if (Option::EnableEval > Option::NoEval && spc(UnaryOpExpression, e)->
getOp() == T_EVAL) {
@@ -2531,10 +2537,8 @@ public:
}
private:
#define CONSTRUCT_EXP(from) \
#define CONSTRUCT_PARAMS(from) \
(from)->getScope(), (from)->getLocation()
#define CONSTRUCT_STMT(from) \
(from)->getScope(), (from)->getLabelScope(), (from)->getLocation()
AnalysisResultConstPtr m_ar;
bool m_changed;
@@ -2607,7 +2611,7 @@ private:
ExpressionListPtr el(
new ExpressionList(
CONSTRUCT_EXP(target),
CONSTRUCT_PARAMS(target),
ExpressionList::ListKindComma));
if (target->isUnused()) {
el->setUnused(true);
@@ -2951,7 +2955,7 @@ private:
slistPtr->insertElement(
ExpStatementPtr(
new ExpStatement(
CONSTRUCT_STMT(slistPtr), assertion)),
CONSTRUCT_PARAMS(slistPtr), assertion)),
idx);
}
break;
@@ -3032,12 +3036,12 @@ private:
} else {
ExpStatementPtr newExpStmt(
new ExpStatement(
CONSTRUCT_STMT(branch),
CONSTRUCT_PARAMS(branch),
after));
IfBranchStatementPtr newBranch(
new IfBranchStatement(
CONSTRUCT_STMT(branch),
CONSTRUCT_PARAMS(branch),
ExpressionPtr(), newExpStmt));
branches->addElement(newBranch);
@@ -3304,12 +3308,6 @@ private:
static bool isNewResult(ExpressionPtr e) {
if (!e) return false;
if (e->is(Expression::KindOfNewObjectExpression)) return true;
if (e->is(Expression::KindOfBinaryOpExpression)) {
auto b = spc(BinaryOpExpression, e);
if (b->getOp() == T_COLLECTION) {
return true;
}
}
if (e->is(Expression::KindOfAssignmentExpression)) {
return isNewResult(spc(AssignmentExpression, e)->getValue());
}
+66 -74
Ver Arquivo
@@ -32,7 +32,6 @@
#include "hphp/compiler/statement/loop_statement.h"
#include "hphp/compiler/statement/class_variable.h"
#include "hphp/compiler/statement/use_trait_statement.h"
#include "hphp/compiler/statement/trait_require_statement.h"
#include "hphp/compiler/analysis/symbol_table.h"
#include "hphp/compiler/package.h"
#include "hphp/compiler/parser/parser.h"
@@ -489,7 +488,8 @@ void AnalysisResult::link(FileScopePtr user, FileScopePtr provider) {
bool AnalysisResult::addClassDependency(FileScopePtr usingFile,
const std::string &className) {
if (m_systemClasses.find(className) != m_systemClasses.end())
if (BuiltinSymbols::s_classes.find(className) !=
BuiltinSymbols::s_classes.end())
return true;
StringToClassScopePtrVecMap::const_iterator iter =
@@ -507,7 +507,8 @@ bool AnalysisResult::addClassDependency(FileScopePtr usingFile,
bool AnalysisResult::addFunctionDependency(FileScopePtr usingFile,
const std::string &functionName) {
if (m_functions.find(functionName) != m_functions.end())
if (BuiltinSymbols::s_functions.find(functionName) !=
BuiltinSymbols::s_functions.end())
return true;
StringToFunctionScopePtrMap::const_iterator iter =
m_functionDecs.find(functionName);
@@ -569,16 +570,12 @@ bool AnalysisResult::isSystemConstant(const std::string &constName) const {
///////////////////////////////////////////////////////////////////////////////
// Program
void AnalysisResult::addSystemFunction(FunctionScopeRawPtr fs) {
FunctionScopePtr& entry = m_functions[fs->getName()];
assert(!entry);
entry = fs;
}
void AnalysisResult::addSystemClass(ClassScopeRawPtr cs) {
ClassScopePtr& entry = m_systemClasses[cs->getName()];
assert(!entry);
entry = cs;
void AnalysisResult::loadBuiltins() {
AnalysisResultPtr ar = shared_from_this();
BuiltinSymbols::LoadFunctions(ar, m_functions);
BuiltinSymbols::LoadClasses(ar, m_systemClasses);
BuiltinSymbols::LoadVariables(ar, m_variables);
BuiltinSymbols::LoadConstants(ar, m_constants);
}
void AnalysisResult::checkClassDerivations() {
@@ -590,11 +587,7 @@ void AnalysisResult::checkClassDerivations() {
hphp_string_iset seen;
cls->checkDerivation(ar, seen);
if (Option::WholeProgram) {
try {
cls->importUsedTraits(ar);
} catch (const AnalysisTimeFatalException& e) {
cls->setFatal(e);
}
cls->importUsedTraits(ar);
}
}
}
@@ -612,26 +605,22 @@ void AnalysisResult::resolveNSFallbackFuncs() {
}
void AnalysisResult::collectFunctionsAndClasses(FileScopePtr fs) {
for (const auto& iter : fs->getFunctions()) {
FunctionScopePtr func = iter.second;
const StringToFunctionScopePtrMap &funcs = fs->getFunctions();
for (StringToFunctionScopePtrMap::const_iterator iter = funcs.begin();
iter != funcs.end(); ++iter) {
FunctionScopePtr func = iter->second;
if (!func->inPseudoMain()) {
FunctionScopePtr &funcDec = m_functionDecs[iter.first];
FunctionScopePtr &funcDec = m_functionDecs[iter->first];
if (funcDec) {
if (funcDec->isSystem()) {
assert(funcDec->allowOverride());
funcDec = func;
} else if (func->isSystem()) {
assert(func->allowOverride());
} else {
FunctionScopePtrVec &funcVec = m_functionReDecs[iter.first];
int sz = funcVec.size();
if (!sz) {
funcDec->setRedeclaring(sz++);
funcVec.push_back(funcDec);
}
func->setRedeclaring(sz++);
funcVec.push_back(func);
FunctionScopePtrVec &funcVec = m_functionReDecs[iter->first];
int sz = funcVec.size();
if (!sz) {
funcDec->setRedeclaring(sz++);
funcVec.push_back(funcDec);
}
func->setRedeclaring(sz++);
funcVec.push_back(func);
} else {
funcDec = func;
}
@@ -639,12 +628,13 @@ void AnalysisResult::collectFunctionsAndClasses(FileScopePtr fs) {
}
if (const StringToFunctionScopePtrVecMap *redec = fs->getRedecFunctions()) {
for (const auto &iter : *redec) {
FunctionScopePtrVec::const_iterator i = iter.second.begin();
FunctionScopePtrVec::const_iterator e = iter.second.end();
FunctionScopePtr &funcDec = m_functionDecs[iter.first];
for (StringToFunctionScopePtrVecMap::const_iterator iter = redec->begin();
iter != redec->end(); ++iter) {
FunctionScopePtrVec::const_iterator i = iter->second.begin();
FunctionScopePtrVec::const_iterator e = iter->second.end();
FunctionScopePtr &funcDec = m_functionDecs[iter->first];
assert(funcDec); // because the first one was in funcs above
FunctionScopePtrVec &funcVec = m_functionReDecs[iter.first];
FunctionScopePtrVec &funcVec = m_functionReDecs[iter->first];
int sz = funcVec.size();
if (!sz) {
funcDec->setRedeclaring(sz++);
@@ -657,9 +647,11 @@ void AnalysisResult::collectFunctionsAndClasses(FileScopePtr fs) {
}
}
for (const auto& iter : fs->getClasses()) {
ClassScopePtrVec &clsVec = m_classDecs[iter.first];
clsVec.insert(clsVec.end(), iter.second.begin(), iter.second.end());
const StringToClassScopePtrVecMap &classes = fs->getClasses();
for (StringToClassScopePtrVecMap::const_iterator iter = classes.begin();
iter != classes.end(); ++iter) {
ClassScopePtrVec &clsVec = m_classDecs[iter->first];
clsVec.insert(clsVec.end(), iter->second.begin(), iter->second.end());
}
m_classAliases.insert(fs->getClassAliases().begin(),
@@ -975,14 +967,11 @@ struct OptVisitor {
AnalysisResultPtr m_ar;
unsigned m_nscope;
JobQueueDispatcher<OptWorker<When>> *m_dispatcher;
JobQueueDispatcher<BlockScope *, OptWorker<When> > *m_dispatcher;
};
template <typename When>
class OptWorker : public JobQueueWorker<BlockScope*,
void*,
true,
true> {
class OptWorker : public JobQueueWorker<BlockScope *, true, true> {
public:
OptWorker() {}
@@ -1001,8 +990,8 @@ public:
acc->second += 1;
#endif /* HPHP_INSTRUMENT_PROCESS_PARALLEL */
try {
auto visitor =
(DepthFirstVisitor<When, OptVisitor>*) m_context;
DepthFirstVisitor<When, OptVisitor > *visitor =
(DepthFirstVisitor<When, OptVisitor >*)m_opaque;
{
Lock ldep(BlockScope::s_depsMutex);
Lock lstate(BlockScope::s_jobStateMutex);
@@ -1191,7 +1180,7 @@ void OptWorker<Pre>::onThreadExit() {
} \
if (threadCount <= 0) threadCount = 1; \
this->m_data.m_dispatcher = \
new JobQueueDispatcher<worker>( \
new JobQueueDispatcher<BlockScope *, worker >( \
threadCount, true, 0, false, this); \
} while (0)
@@ -1236,7 +1225,7 @@ template <typename When>
void
AnalysisResult::preWaitCallback(bool first,
const BlockScopeRawPtrQueue &scopes,
void *context) {
void *opaque) {
// default is no-op
}
@@ -1245,7 +1234,7 @@ bool
AnalysisResult::postWaitCallback(bool first,
bool again,
const BlockScopeRawPtrQueue &scopes,
void *context) {
void *opaque) {
// default is no-op
return again;
}
@@ -1310,7 +1299,7 @@ struct BIPairCmp {
template <typename When>
void
AnalysisResult::processScopesParallel(const char *id,
void *context /* = NULL */) {
void *opaque /* = NULL */) {
BlockScopeRawPtrQueue scopes;
getScopesSet(scopes);
@@ -1347,7 +1336,7 @@ AnalysisResult::processScopesParallel(const char *id,
BlockScopeRawPtrQueue enqueued;
again = dfv.visitParallel(scopes, first, enqueued);
preWaitCallback<When>(first, scopes, context);
preWaitCallback<When>(first, scopes, opaque);
#ifdef HPHP_INSTRUMENT_PROCESS_PARALLEL
{
@@ -1401,7 +1390,7 @@ AnalysisResult::processScopesParallel(const char *id,
std::cout << "Number of waiting scopes: " << numWaiting << std::endl;
#endif /* HPHP_INSTRUMENT_PROCESS_PARALLEL */
again = postWaitCallback<When>(first, again, scopes, context);
again = postWaitCallback<When>(first, again, scopes, opaque);
first = false;
} while (again);
dfv.data().stop();
@@ -1573,8 +1562,7 @@ DepthFirstVisitor<InferTypes, OptVisitor>::visitScope(BlockScopeRawPtr scope) {
template<>
bool AnalysisResult::postWaitCallback<InferTypes>(
bool first, bool again,
const BlockScopeRawPtrQueue &scopes, void *context) {
bool first, bool again, const BlockScopeRawPtrQueue &scopes, void *opaque) {
#ifdef HPHP_INSTRUMENT_TYPE_INF
std::cout << "Number of rescheduled: " <<
@@ -1616,10 +1604,12 @@ void AnalysisResult::inferTypes() {
BlockScopeRawPtrQueue scopes;
getScopesSet(scopes);
for (auto scope : scopes) {
scope->setInTypeInference(true);
scope->clearUpdated();
assert(scope->getNumDepsToWaitFor() == 0);
for (BlockScopeRawPtrQueue::iterator
it = scopes.begin(), end = scopes.end();
it != end; ++it) {
(*it)->setInTypeInference(true);
(*it)->clearUpdated();
assert((*it)->getNumDepsToWaitFor() == 0);
}
#ifdef HPHP_INSTRUMENT_TYPE_INF
@@ -1630,11 +1620,13 @@ void AnalysisResult::inferTypes() {
processScopesParallel<InferTypes>("InferTypes");
for (auto scope : scopes) {
scope->setInTypeInference(false);
scope->clearUpdated();
assert(scope->getMark() == BlockScope::MarkProcessed);
assert(scope->getNumDepsToWaitFor() == 0);
for (BlockScopeRawPtrQueue::iterator
it = scopes.begin(), end = scopes.end();
it != end; ++it) {
(*it)->setInTypeInference(false);
(*it)->clearUpdated();
assert((*it)->getMark() == BlockScope::MarkProcessed);
assert((*it)->getNumDepsToWaitFor() == 0);
}
}
@@ -1676,12 +1668,12 @@ StatementPtr DepthFirstVisitor<Post, OptVisitor>::visit(StatementPtr stmt) {
return stmt->postOptimize(this->m_data.m_ar);
}
class FinalWorker : public JobQueueWorker<MethodStatementPtr, AnalysisResult*> {
class FinalWorker : public JobQueueWorker<MethodStatementPtr> {
public:
virtual void doJob(MethodStatementPtr m) {
try {
AliasManager am(1);
am.finalSetup(m_context->shared_from_this(), m);
am.finalSetup(((AnalysisResult*)m_opaque)->shared_from_this(), m);
} catch (Exception &e) {
Logger::Error("%s", e.getMessage().c_str());
}
@@ -1690,11 +1682,11 @@ public:
template<>
void AnalysisResult::preWaitCallback<Post>(
bool first, const BlockScopeRawPtrQueue &scopes, void *context) {
assert(!Option::ControlFlow || context != nullptr);
bool first, const BlockScopeRawPtrQueue &scopes, void *opaque) {
assert(!Option::ControlFlow || opaque != nullptr);
if (first && Option::ControlFlow) {
auto *dispatcher
= (JobQueueDispatcher<FinalWorker> *) context;
JobQueueDispatcher<FinalWorker::JobType, FinalWorker> *dispatcher
= (JobQueueDispatcher<FinalWorker::JobType, FinalWorker> *) opaque;
for (BlockScopeRawPtrQueue::const_iterator it = scopes.begin(),
end = scopes.end(); it != end; ++it) {
BlockScopeRawPtr scope = *it;
@@ -1718,7 +1710,7 @@ void AnalysisResult::postOptimize() {
}
if (threadCount <= 0) threadCount = 1;
JobQueueDispatcher<FinalWorker> dispatcher(
JobQueueDispatcher<FinalWorker::JobType, FinalWorker> dispatcher(
threadCount, true, 0, false, this);
processScopesParallel<Post>("PostOptimize", &dispatcher);
+2 -4
Ver Arquivo
@@ -24,7 +24,6 @@
#include "hphp/compiler/analysis/symbol_table.h"
#include "hphp/compiler/analysis/function_container.h"
#include "hphp/compiler/package.h"
#include "hphp/compiler/hphp.h"
#include "hphp/util/string-bag.h"
#include "hphp/util/thread-local.h"
@@ -37,7 +36,7 @@ namespace HPHP {
DECLARE_BOOST_TYPES(ClassScope);
DECLARE_EXTENDED_BOOST_TYPES(FileScope);
DECLARE_BOOST_TYPES(FileScope);
DECLARE_BOOST_TYPES(FunctionScope);
DECLARE_BOOST_TYPES(Location);
DECLARE_BOOST_TYPES(AnalysisResult);
@@ -151,8 +150,7 @@ public:
void addNSFallbackFunc(ConstructPtr c, FileScopePtr fs);
void addSystemFunction(FunctionScopeRawPtr fs);
void addSystemClass(ClassScopeRawPtr cs);
void loadBuiltins();
void analyzeProgram(bool system = false);
void analyzeIncludes();
void analyzeProgramFinal();
+3 -1
Ver Arquivo
@@ -155,7 +155,9 @@ bool BlockScope::hasUser(BlockScopeRawPtr user, int useKinds) const {
}
void BlockScope::addUse(BlockScopeRawPtr user, int useKinds) {
if ((is(ClassScope) || is(FunctionScope)) && getStmt()) {
if (is(ClassScope) ? static_cast<HPHP::ClassScope*>(this)->isUserClass() :
is(FunctionScope) &&
static_cast<HPHP::FunctionScope*>(this)->isUserFunction()) {
if (user.get() == this) {
m_selfUser |= useKinds;
-391
Ver Arquivo
@@ -1,391 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/capture_extractor.h"
#include "hphp/compiler/expression/join_clause.h"
#include "hphp/compiler/expression/scalar_expression.h"
#include "hphp/parser/hphp.tab.hpp"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
/**
* Rewrites the construct rooted in cp so that it is in a form
* that a query processor can evaluate while referencing only
* state that is contained in the query processor or supplied
* to the query processor in the form of arguments to the query.
* For instance, a reference to a local variable in the scope
* containing the query expression will be rewritten into a
* reference to a (synthetic) parameter of the query expression.
* This is similar to the way lambda expressions capture variables
* from their enclosing environment.
* Note that rewriting implies allocating new objects.
* The original construct is not mutated in any way.
* If the original construct is already in the right form, it is
* returned as is.
*/
ExpressionPtr CaptureExtractor::rewrite(ExpressionPtr ep) {
assert(ep != nullptr);
switch (ep->getKindOf()) {
case Expression::KindOfQueryExpression: {
return rewriteQuery(static_pointer_cast<QueryExpression>(ep));
}
case Expression::KindOfSelectClause: {
// leave select clauses alone, another visitor deals with them.
return ep;
}
case Expression::KindOfFromClause:
case Expression::KindOfLetClause:
case Expression::KindOfIntoClause:
case Expression::KindOfWhereClause: {
return rewriteSimpleClause(static_pointer_cast<SimpleQueryClause>(ep));
}
case Expression::KindOfGroupClause:
case Expression::KindOfJoinClause:
case Expression::KindOfOrderbyClause:
case Expression::KindOfOrdering: {
// leave these alone. they are query specific and not parameterizable.
return ep;
}
case Expression::KindOfObjectPropertyExpression: {
return rewriteObjectProperty(
static_pointer_cast<ObjectPropertyExpression>(ep));
}
case Expression::KindOfSimpleFunctionCall: {
return rewriteCall(static_pointer_cast<SimpleFunctionCall>(ep));
}
case Expression::KindOfScalarExpression: {
// Leave scalars alone. If the query processor can't handle them
// rewriting won't help.
return ep;
}
case Expression::KindOfUnaryOpExpression: {
return rewriteUnary(static_pointer_cast<UnaryOpExpression>(ep));
}
case Expression::KindOfBinaryOpExpression: {
return rewriteBinary(static_pointer_cast<BinaryOpExpression>(ep));
}
case Expression::KindOfSimpleVariable: {
return rewriteSimpleVariable(static_pointer_cast<SimpleVariable>(ep));
}
case Expression::KindOfExpressionList: {
return rewriteExpressionList(static_pointer_cast<ExpressionList>(ep));
}
default: {
// If we get here, the expression is not a candidate for evaluation
// by the query processor, so just turn it into a query parameter.
return newQueryParamRef(ep);
}
}
}
/**
* Appends the given expression to end of the m_capturedExpressions list
* and creates a new expression with the same scope and source location
* that represents a reference to a query parameter. Query parameters do
* not have a source code equivalent, but inform the query processor that
* this expression represents the ith argument value, where i is zero based
* and forms the last character of the special string @query_param_i.
*/
SimpleVariablePtr CaptureExtractor::newQueryParamRef(ExpressionPtr ae) {
assert(ae != nullptr);
char count = '0' + m_capturedExpressions.size();
std::string pname = "@query_param_";
pname.push_back(count);
SimpleVariablePtr param(
new SimpleVariable(ae->getScope(), ae->getLocation(), pname)
);
m_capturedExpressions.push_back(ae);
return param;
}
/**
* If one or more of the arguments of the function call depend on query only
* state (query local but not a query parameter reference), then rewrite
* all of the arguments to be query local and return the rewritten
* function call (the query processor has to either figure out a way to call
* the function or must cause a runtime error when faced with the call).
* Otherwise, rewrite the call as a query parameter reference.
*/
ExpressionPtr CaptureExtractor::rewriteCall(SimpleFunctionCallPtr sfc) {
assert(sfc != nullptr);
if (sfc->hadBackslash() ||
(sfc->getClass() != nullptr && !sfc->getClassName().empty())) {
return newQueryParamRef(sfc);
}
auto args = sfc->getParams();
auto pc = args == nullptr ? 0 : args->getCount();
bool isQueryCall = false;
for (int i = 0; i < pc; i++) {
auto arg = (*args)[i];
assert(arg != nullptr);
isQueryCall |= this->dependsOnQueryOnlyState(arg);
}
if (!isQueryCall) return newQueryParamRef(sfc);
ExpressionListPtr newArgs(
new ExpressionList(args->getScope(), args->getLocation())
);
bool noRewrites = true;
for (int i = 0; i < pc; i++) {
auto arg = (*args)[i];
auto newArg = rewrite(arg);
if (arg != newArg) noRewrites = false;
newArgs->addElement(newArg);
}
if (noRewrites) return sfc;
SimpleFunctionCallPtr result(
new SimpleFunctionCall(sfc->getScope(), sfc->getLocation(),
sfc->getName(), false, newArgs, ExpressionPtr())
);
return result;
}
/**
* Traverses the expression tree rooted at e and returns true if
* any node in the tree is a simple variable that references a
* name in m_boundVars.
*/
bool CaptureExtractor::dependsOnQueryOnlyState(ExpressionPtr e) {
assert(e != nullptr);
if (e->getKindOf() == Expression::KindOfSimpleVariable) {
auto sv = static_pointer_cast<SimpleVariable>(e);
auto varName = sv->getName();
for (auto &boundVar : m_boundVars) {
if (varName == boundVar) return true;
}
return false;
}
auto numKids = e->getKidCount();
for (int i = 0; i < numKids; i++) {
auto ei = e->getNthExpr(i);
if (ei == nullptr) return false; //Default param
if (dependsOnQueryOnlyState(ei)) return true;
}
return false;
}
/**
* If a simple variable refers to a name bound inside the query
* then leave it alone. If not, rewrite it to be reference to
* a query parameter.
*/
SimpleVariablePtr CaptureExtractor::rewriteSimpleVariable(
SimpleVariablePtr sv) {
assert(sv != nullptr);
auto varName = sv->getName();
for (auto &boundVar : m_boundVars) {
if (varName == boundVar) return sv;
}
return newQueryParamRef(sv);
}
/**
* Query expressions introduce a local scope with names introduced
* by some of the clauses of the query expression. This needs
* special handling so that we can track variables local to the query.
*/
QueryExpressionPtr CaptureExtractor::rewriteQuery(QueryExpressionPtr qe) {
assert(qe != nullptr);
auto clauses = qe->getClauses();
auto newClauses = rewriteExpressionList(clauses);
if (clauses == newClauses) return qe;
QueryExpressionPtr result(
new QueryExpression(qe->getScope(), qe->getLocation(), newClauses)
);
return result;
}
/**
* Rewrites any expression query clauses in this list of clauses, taking care
* to track variables local to the query.
*/
ExpressionListPtr CaptureExtractor::rewriteExpressionList(ExpressionListPtr l) {
int np = 0;
int nc = l->getCount();
ExpressionListPtr newList(
new ExpressionList(l->getScope(), l->getLocation())
);
bool noRewrites = true;
for (int i = 0; i < nc; i++) {
auto e = (*l)[i];
assert(e != nullptr);
auto kind = e->getKindOf();
switch (kind) {
case Expression::KindOfIntoClause: {
// The into expression is in the scope of the into clause
SimpleQueryClausePtr qcp(static_pointer_cast<SimpleQueryClause>(e));
m_boundVars.push_back(qcp->getIdentifier());
np++;
break;
}
case Expression::KindOfJoinClause: {
JoinClausePtr jcp(static_pointer_cast<JoinClause>(e));
m_boundVars.push_back(jcp->getVar());
np++;
break;
}
default:
break;
}
auto ne = rewrite(e);
if (ne != e) noRewrites = false;
newList->addElement(ne);
// deal with clauses that introduce names for subsequent clauses
switch (kind) {
case Expression::KindOfFromClause:
case Expression::KindOfLetClause: {
SimpleQueryClausePtr qcp(static_pointer_cast<SimpleQueryClause>(e));
m_boundVars.push_back(qcp->getIdentifier());
np++;
break;
}
case Expression::KindOfJoinClause: {
JoinClausePtr jcp(static_pointer_cast<JoinClause>(e));
auto groupId = jcp->getGroup();
if (!groupId.empty()) {
m_boundVars.push_back(groupId);
np++;
}
break;
}
default:
break;
}
}
while (np-- > 0) m_boundVars.pop_back();
if (noRewrites) return l;
return newList;
}
/*
* If the expression of a simple query clause is query local, then
* return the clause as is. Otherwise return a clone of the clause
* with the expression rewritten to reference a query parameter.
*/
SimpleQueryClausePtr CaptureExtractor::rewriteSimpleClause(
SimpleQueryClausePtr sc) {
assert (sc != nullptr);
auto expr = sc->getExpression();
auto newExpr = rewrite(expr);
if (expr == newExpr) return sc;
auto rsc = static_pointer_cast<SimpleQueryClause>(sc->clone());
rsc->setExpression(newExpr);
return rsc;
}
/*
* If the object expression is query local, that is, if it is a simple variable
* referring to a name declared in a query clause, or itself a query local
* object expression, then if keep this expression as is. If not, then
* rewrite this expression into a query parameter reference.
*/
ExpressionPtr CaptureExtractor::rewriteObjectProperty(
ObjectPropertyExpressionPtr ope) {
assert(ope != nullptr);
auto obj = ope->getObject();
if (this->dependsOnQueryOnlyState(obj)) {
auto prop = ope->getProperty();
if (prop->getKindOf() == Expression::KindOfScalarExpression) {
auto scalar = static_pointer_cast<ScalarExpression>(prop);
const string &propName = scalar->getLiteralString();
if (!propName.empty()) {
return ope;
}
}
}
return newQueryParamRef(ope);
}
/**
* If the unary operation is not PHP specific, but something a query
* processor can handle (+ - ! ~), then rewrite the operand to something
* the query processor can evaluate (such as a query parameter reference)
* and rewrite the entire expression to use the rewritten operand.
* If the rewritten operand is the same as the original operand, just
* return the expression as is.
*/
ExpressionPtr CaptureExtractor::rewriteUnary(UnaryOpExpressionPtr ue) {
assert (ue != nullptr);
if (!ue->getFront()) return nullptr;
switch (ue->getOp()) {
case '+':
case '-':
case '!':
case '~':
break; // Could be something the query processor can handle
default:
return newQueryParamRef(ue);
}
auto expr = ue->getExpression();
auto newExpr = rewrite(expr);
if (expr == newExpr) return ue;
UnaryOpExpressionPtr result(
new UnaryOpExpression(ue->getScope(), ue->getLocation(),
newExpr, ue->getOp(), true)
);
return result;
}
/**
* If the binary operation is not PHP specific, but something a query
* processor can handle (+ - * and so on), then rewrite the operands to
* something the query processor can evaluate (such as a query parameter
* references) and rewrite the entire expression to use the rewritten operands.
* If the rewritten operands are the same as the original operands, just
* return the expression as is.
*/
ExpressionPtr CaptureExtractor::rewriteBinary(BinaryOpExpressionPtr be) {
assert(be != nullptr);
switch (be->getOp()) {
case '+':
case '-':
case '*':
case '/':
case '%':
case '&':
case '|':
case '^':
case T_IS_IDENTICAL:
case T_IS_EQUAL:
case '>':
case '<':
case T_IS_GREATER_OR_EQUAL:
case T_IS_SMALLER_OR_EQUAL:
case T_IS_NOT_IDENTICAL:
case T_IS_NOT_EQUAL:
case T_BOOLEAN_OR:
case T_BOOLEAN_AND:
case T_LOGICAL_OR:
case T_LOGICAL_AND:
case '.':
break; // Could be something the query processor can handle
default:
return newQueryParamRef(be);
}
auto expr1 = be->getExp1();
auto expr2 = be->getExp2();
auto newExpr1 = rewrite(expr1);
auto newExpr2 = rewrite(expr2);
if (expr1 == newExpr1 && expr2 == newExpr2) return be;
BinaryOpExpressionPtr result(
new BinaryOpExpression(be->getScope(), be->getLocation(),
newExpr1, newExpr2, be->getOp())
);
return result;
}
}
-66
Ver Arquivo
@@ -1,66 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_CAPTURE_EXTRACTOR_H_
#define incl_HPHP_CAPTURE_EXTRACTOR_H_
#include "hphp/compiler/expression/binary_op_expression.h"
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/object_property_expression.h"
#include "hphp/compiler/expression/query_expression.h"
#include "hphp/compiler/expression/simple_function_call.h"
#include "hphp/compiler/expression/simple_query_clause.h"
#include "hphp/compiler/expression/simple_variable.h"
#include "hphp/compiler/expression/unary_op_expression.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
/** A rewriter for query expressions that capture variables that lie
* outside of the scope of the query expression. Subexpressions that
* contain such references are turned into references to query parameter
* variables. The original expressions are collected into the list
* returned by getCapturedEpressions. Their runtime values are obtained
* before the query is evaluated and are passed as arguments to the query
* processor.
*/
class CaptureExtractor {
public:
ExpressionPtr rewrite(ExpressionPtr ep);
std::vector<ExpressionPtr> getCapturedExpressions() {
return m_capturedExpressions;
}
private:
bool dependsOnQueryOnlyState(ExpressionPtr e);
SimpleVariablePtr newQueryParamRef(ExpressionPtr ae);
ExpressionPtr rewriteBinary(BinaryOpExpressionPtr be);
ExpressionPtr rewriteCall(SimpleFunctionCallPtr sfc);
ExpressionListPtr rewriteExpressionList(ExpressionListPtr l);
ExpressionPtr rewriteObjectProperty(ObjectPropertyExpressionPtr ope);
QueryExpressionPtr rewriteQuery(QueryExpressionPtr qe);
SimpleQueryClausePtr rewriteSimpleClause(SimpleQueryClausePtr sc);
SimpleVariablePtr rewriteSimpleVariable(SimpleVariablePtr sv);
ExpressionPtr rewriteUnary(UnaryOpExpressionPtr ue);
std::vector<ExpressionPtr> m_capturedExpressions;
std::vector<std::string> m_boundVars;
};
}
#endif // incl_HPHP_CAPTURE_EXTRACTOR_H_
+21 -129
Ver Arquivo
@@ -39,7 +39,6 @@
#include "hphp/compiler/statement/class_variable.h"
#include "hphp/compiler/statement/class_constant.h"
#include "hphp/compiler/statement/use_trait_statement.h"
#include "hphp/compiler/statement/trait_require_statement.h"
#include "hphp/compiler/statement/trait_prec_statement.h"
#include "hphp/compiler/statement/trait_alias_statement.h"
#include "hphp/runtime/base/zend-string.h"
@@ -474,17 +473,6 @@ void ClassScope::addImportTraitMethod(const TraitMethod &traitMethod,
m_importMethToTraitMap[methName].push_back(traitMethod);
}
void ClassScope::addTraitRequirement(const string &requiredName,
bool isExtends) {
assert(isTrait());
if (isExtends) {
m_traitRequiredExtends.insert(requiredName);
} else {
m_traitRequiredImplements.insert(requiredName);
}
}
void
ClassScope::setImportTraitMethodModifiers(const string &methName,
ClassScopePtr traitCls,
@@ -545,7 +533,6 @@ ClassScope::findTraitMethod(AnalysisResultPtr ar,
void ClassScope::findTraitMethodsToImport(AnalysisResultPtr ar,
ClassScopePtr trait) {
assert(Option::WholeProgram);
ClassStatementPtr tStmt =
dynamic_pointer_cast<ClassStatement>(trait->getStmt());
StatementListPtr tStmts = tStmt->getStmts();
@@ -562,45 +549,7 @@ void ClassScope::findTraitMethodsToImport(AnalysisResultPtr ar,
}
}
void ClassScope::importTraitRequirements(AnalysisResultPtr ar,
ClassScopePtr trait) {
if (isTrait()) {
for (auto const& req : trait->getTraitRequiredExtends()) {
addTraitRequirement(req, true);
}
for (auto const& req : trait->getTraitRequiredImplements()) {
addTraitRequirement(req, false);
}
} else {
for (auto const& req : trait->getTraitRequiredExtends()) {
if (!derivesFrom(ar, req, true, false)) {
getStmt()->analysisTimeFatal(
Compiler::InvalidDerivation,
Strings::TRAIT_REQ_EXTENDS,
m_originalName.c_str(),
req.c_str(),
trait->getOriginalName().c_str(),
"use"
);
}
}
for (auto const& req : trait->getTraitRequiredImplements()) {
if (!derivesFrom(ar, req, true, false)) {
getStmt()->analysisTimeFatal(
Compiler::InvalidDerivation,
Strings::TRAIT_REQ_IMPLEMENTS,
m_originalName.c_str(),
req.c_str(),
trait->getOriginalName().c_str(),
"use"
);
}
}
}
}
void ClassScope::applyTraitPrecRule(TraitPrecStatementPtr stmt) {
assert(Option::WholeProgram);
const string methodName = Util::toLower(stmt->getMethodName());
const string selectedTraitName = Util::toLower(stmt->getTraitName());
std::set<string> otherTraitNames;
@@ -631,20 +580,12 @@ void ClassScope::applyTraitPrecRule(TraitPrecStatementPtr stmt) {
// Report error if didn't find the selected trait
if (!foundSelectedTrait) {
stmt->analysisTimeFatal(
Compiler::UnknownTrait,
Strings::TRAITS_UNKNOWN_TRAIT,
selectedTraitName.c_str()
);
Compiler::Error(Compiler::UnknownTrait, stmt);
}
// Sanity checking: otherTraitNames should be empty now
if (otherTraitNames.size()) {
stmt->analysisTimeFatal(
Compiler::UnknownTrait,
Strings::TRAITS_UNKNOWN_TRAIT,
selectedTraitName.c_str()
);
Compiler::Error(Compiler::UnknownTrait, stmt);
}
}
@@ -655,7 +596,6 @@ bool ClassScope::hasMethod(const string &methodName) const {
ClassScopePtr
ClassScope::findSingleTraitWithMethod(AnalysisResultPtr ar,
const string &methodName) const {
assert(Option::WholeProgram);
ClassScopePtr trait = ClassScopePtr();
for (unsigned i = 0; i < m_usedTraitNames.size(); i++) {
@@ -673,7 +613,6 @@ ClassScope::findSingleTraitWithMethod(AnalysisResultPtr ar,
}
void ClassScope::addTraitAlias(TraitAliasStatementPtr aliasStmt) {
assert(Option::WholeProgram);
const string &traitName = aliasStmt->getTraitName();
const string &origMethName = aliasStmt->getMethodName();
const string &newMethName = aliasStmt->getNewMethodName();
@@ -684,7 +623,6 @@ void ClassScope::addTraitAlias(TraitAliasStatementPtr aliasStmt) {
void ClassScope::applyTraitAliasRule(AnalysisResultPtr ar,
TraitAliasStatementPtr stmt) {
assert(Option::WholeProgram);
const string traitName = Util::toLower(stmt->getTraitName());
const string origMethName = Util::toLower(stmt->getMethodName());
const string newMethName = Util::toLower(stmt->getNewMethodName());
@@ -697,11 +635,8 @@ void ClassScope::applyTraitAliasRule(AnalysisResultPtr ar,
traitCls = ar->findClass(traitName);
}
if (!traitCls || !(traitCls->isTrait())) {
stmt->analysisTimeFatal(
Compiler::UnknownTrait,
Strings::TRAITS_UNKNOWN_TRAIT,
traitName.empty() ? origMethName.c_str() : traitName.c_str()
);
Compiler::Error(Compiler::UnknownTrait, stmt);
return;
}
// Keep record of alias rule
@@ -712,10 +647,8 @@ void ClassScope::applyTraitAliasRule(AnalysisResultPtr ar,
MethodStatementPtr methStmt = findTraitMethod(ar, traitCls, origMethName,
visitedTraits);
if (!methStmt) {
stmt->analysisTimeFatal(
Compiler::UnknownTraitMethod,
Strings::TRAITS_UNKNOWN_TRAIT_METHOD, origMethName.c_str()
);
Compiler::Error(Compiler::UnknownTraitMethod, stmt);
return;
}
if (origMethName == newMethName) {
@@ -730,7 +663,6 @@ void ClassScope::applyTraitAliasRule(AnalysisResultPtr ar,
}
void ClassScope::applyTraitRules(AnalysisResultPtr ar) {
assert(Option::WholeProgram);
ClassStatementPtr classStmt = dynamic_pointer_cast<ClassStatement>(getStmt());
assert(classStmt);
StatementListPtr stmts = classStmt->getStmts();
@@ -763,7 +695,6 @@ void ClassScope::applyTraitRules(AnalysisResultPtr ar) {
// 1) implemented by other traits
// 2) duplicate
void ClassScope::removeSpareTraitAbstractMethods(AnalysisResultPtr ar) {
assert(Option::WholeProgram);
for (MethodToTraitListMap::iterator iter = m_importMethToTraitMap.begin();
iter != m_importMethToTraitMap.end(); iter++) {
@@ -801,17 +732,9 @@ void ClassScope::removeSpareTraitAbstractMethods(AnalysisResultPtr ar) {
}
void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
// Trait flattening is supposed to happen only when we have awareness of
// the whole program.
assert(Option::WholeProgram);
if (m_traitStatus == FLATTENED) return;
if (m_traitStatus == BEING_FLATTENED) {
getStmt()->analysisTimeFatal(
Compiler::CyclicDependentTraits,
"Cyclic dependency between traits involving %s",
getOriginalName().c_str()
);
Compiler::Error(Compiler::CyclicDependentTraits, getStmt());
return;
}
if (m_usedTraitNames.size() == 0) {
@@ -828,53 +751,18 @@ void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
}
}
if (isTrait()) {
for (auto const& req : getTraitRequiredExtends()) {
ClassScopePtr rCls = ar->findClass(req);
if (!rCls || rCls->isFinal() || rCls->isInterface()) {
getStmt()->analysisTimeFatal(
Compiler::InvalidDerivation,
Strings::TRAIT_BAD_REQ_EXTENDS,
m_originalName.c_str(),
req.c_str(),
req.c_str()
);
}
}
for (auto const& req : getTraitRequiredImplements()) {
ClassScopePtr rCls = ar->findClass(req);
if (!rCls || !(rCls->isInterface())) {
getStmt()->analysisTimeFatal(
Compiler::InvalidDerivation,
Strings::TRAIT_BAD_REQ_IMPLEMENTS,
m_originalName.c_str(),
req.c_str(),
req.c_str()
);
}
}
}
// Find trait methods to be imported
for (unsigned i = 0; i < m_usedTraitNames.size(); i++) {
ClassScopePtr tCls = ar->findClass(m_usedTraitNames[i]);
if (!tCls || !(tCls->isTrait())) {
setAttribute(UsesUnknownTrait); // XXX: is this useful ... for anything?
getStmt()->analysisTimeFatal(
Compiler::UnknownTrait,
Strings::TRAITS_UNKNOWN_TRAIT,
m_usedTraitNames[i].c_str()
);
setAttribute(UsesUnknownTrait);
Compiler::Error(Compiler::UnknownTrait, getStmt());
continue;
}
// First, make sure the used trait is flattened
tCls->importUsedTraits(ar);
findTraitMethodsToImport(ar, tCls);
// Import any interfaces implemented
tCls->getInterfaces(ar, m_bases, false);
importTraitRequirements(ar, tCls);
}
// Apply rules
@@ -894,7 +782,7 @@ void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
}
std::map<string, MethodStatementPtr> importedTraitMethods;
std::vector<std::pair<string,const TraitMethod*>> importedTraitsWithOrigName;
std::vector<std::pair<string,const TraitMethod*> > importedTraitsWithOrigName;
// Actually import the methods
for (MethodToTraitListMap::const_iterator
@@ -908,11 +796,7 @@ void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
}
// Consistency checking: each name must only refer to one imported method
if (iter->second.size() > 1) {
getStmt()->analysisTimeFatal(
Compiler::MethodInMultipleTraits,
Strings::METHOD_IN_MULTIPLE_TRAITS,
iter->first.c_str()
);
Compiler::Error(Compiler::MethodInMultipleTraits, getStmt());
} else {
TraitMethodList::const_iterator traitMethIter = iter->second.begin();
if ((traitMethIter->m_modifiers ? traitMethIter->m_modifiers :
@@ -923,6 +807,13 @@ void ClassScope::importUsedTraits(AnalysisResultPtr ar) {
continue;
}
}
if (traitMethIter->m_modifiers &&
traitMethIter->m_modifiers->isStatic()) {
Compiler::Error(Compiler::InvalidAccessModifier,
traitMethIter->m_modifiers);
continue;
}
string sourceName = traitMethIter->m_ruleStmt ?
Util::toLower(((TraitAliasStatement*)traitMethIter->m_ruleStmt.get())->
getMethodName()) : iter->first;
@@ -1243,7 +1134,8 @@ void ClassScope::getInterfaces(AnalysisResultConstPtr ar,
if (cls && cls->isRedeclaring()) {
cls = self->findExactClass(cls);
}
names.push_back(cls ? cls->getDocName() : *it);
if (cls) names.push_back(cls->getDocName());
else names.push_back(*it);
if (cls && recursive) {
cls->getInterfaces(ar, names, true);
}
+3 -34
Ver Arquivo
@@ -24,9 +24,8 @@
#include "hphp/compiler/statement/trait_prec_statement.h"
#include "hphp/compiler/statement/trait_alias_statement.h"
#include "hphp/compiler/expression/user_attribute.h"
#include "hphp/compiler/json.h"
#include "hphp/util/functional.h"
#include "hphp/util/hash-map-typedefs.h"
#include "hphp/util/json.h"
#include "hphp/util/case-insensitive.h"
#include "hphp/compiler/option.h"
namespace HPHP {
@@ -174,7 +173,6 @@ public:
* Get/set attributes.
*/
void setSystem();
bool isSystem() const { return m_attribute & System; }
void setAttribute(Attribute attr) { m_attribute |= attr;}
void clearAttribute(Attribute attr) { m_attribute &= ~attr;}
bool getAttribute(Attribute attr) const {
@@ -303,29 +301,17 @@ public:
}
}
const boost::container::flat_set<std::string>& getTraitRequiredExtends()
const {
return m_traitRequiredExtends;
}
const boost::container::flat_set<std::string>& getTraitRequiredImplements()
const {
return m_traitRequiredImplements;
}
const std::vector<std::string> &getUsedTraitNames() const {
return m_usedTraitNames;
}
const std::vector<std::pair<std::string, std::string>>& getTraitAliases()
const std::vector<std::pair<std::string, std::string> > &getTraitAliases()
const {
return m_traitAliases;
}
void addTraitAlias(TraitAliasStatementPtr aliasStmt);
void addTraitRequirement(const std::string &requiredName, bool isExtends);
void importUsedTraits(AnalysisResultPtr ar);
/**
@@ -383,16 +369,6 @@ public:
bool canSkipCreateMethod(AnalysisResultConstPtr ar) const;
bool checkHasPropTable(AnalysisResultConstPtr ar);
const StringData* getFatalMessage() const {
return m_fatal_error_msg;
}
void setFatal(const AnalysisTimeFatalException& fatal) {
assert(m_fatal_error_msg == nullptr);
m_fatal_error_msg = makeStaticString(fatal.getMessage());
assert(m_fatal_error_msg != nullptr);
}
private:
// need to maintain declaration order for ClassInfo map
FunctionScopePtrVec m_functionsVec;
@@ -402,8 +378,6 @@ private:
UserAttributeMap m_userAttributes;
std::vector<std::string> m_usedTraitNames;
boost::container::flat_set<std::string> m_traitRequiredExtends;
boost::container::flat_set<std::string> m_traitRequiredImplements;
// m_traitAliases is used to support ReflectionClass::getTraitAliases
std::vector<std::pair<std::string, std::string> > m_traitAliases;
@@ -453,9 +427,6 @@ private:
// bases 32 through n are all known.
unsigned m_knownBases;
// holds the fact that accessing this class declaration is a fatal error
const StringData* m_fatal_error_msg = nullptr;
void addImportTraitMethod(const TraitMethod &traitMethod,
const std::string &methName);
void informClosuresAboutScopeClone(ConstructPtr root,
@@ -476,8 +447,6 @@ private:
void findTraitMethodsToImport(AnalysisResultPtr ar, ClassScopePtr trait);
void importTraitRequirements(AnalysisResultPtr ar, ClassScopePtr trait);
MethodStatementPtr findTraitMethod(AnalysisResultPtr ar,
ClassScopePtr trait,
const std::string &methodName,
+1 -1
Ver Arquivo
@@ -18,7 +18,7 @@
#define incl_HPHP_COMPILER_ERROR_H_
#include "hphp/compiler/analysis/type.h"
#include "hphp/compiler/json.h"
#include "hphp/util/json.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
-1
Ver Arquivo
@@ -245,7 +245,6 @@ int ControlFlowBuilder::before(ConstructRawPtr cp) {
Statement::KindOf stype = s->getKindOf();
switch (stype) {
case Statement::KindOfUseTraitStatement:
case Statement::KindOfTraitRequireStatement:
case Statement::KindOfTraitPrecStatement:
case Statement::KindOfTraitAliasStatement:
not_reached();
+1 -1
Ver Arquivo
@@ -37,6 +37,7 @@ CODE_ERROR_ENTRY(InvalidAttribute)
CODE_ERROR_ENTRY(UnknownTrait)
CODE_ERROR_ENTRY(MethodInMultipleTraits)
CODE_ERROR_ENTRY(UnknownTraitMethod)
CODE_ERROR_ENTRY(InvalidAccessModifier)
CODE_ERROR_ENTRY(CyclicDependentTraits)
CODE_ERROR_ENTRY(InvalidTraitStatement)
CODE_ERROR_ENTRY(RedeclaredTrait)
@@ -44,4 +45,3 @@ CODE_ERROR_ENTRY(InvalidInstantiation)
CODE_ERROR_ENTRY(InvalidYield)
CODE_ERROR_ENTRY(InvalidAwait)
CODE_ERROR_ENTRY(BadDefaultValueType)
CODE_ERROR_ENTRY(InvalidMethodDefinition)
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+60 -264
Ver Arquivo
@@ -20,7 +20,6 @@
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/statement/statement.h"
#include "hphp/compiler/statement/use_trait_statement.h"
#include "hphp/compiler/statement/trait_require_statement.h"
#include "hphp/compiler/statement/trait_prec_statement.h"
#include "hphp/compiler/statement/trait_alias_statement.h"
#include "hphp/compiler/statement/typedef_statement.h"
@@ -29,9 +28,6 @@
#include "hphp/runtime/vm/unit.h"
#include "hphp/util/hash.h"
#include <deque>
#include <utility>
namespace HPHP {
DECLARE_BOOST_TYPES(ClosureExpression);
@@ -99,7 +95,6 @@ public:
IterKind kind;
Id id;
};
#define O(name, imm, pop, push, flags) \
void name(imm);
#define NA
@@ -111,7 +106,7 @@ public:
typ1 a1, typ2 a2, typ3 a3
#define FOUR(typ1, typ2, typ3, typ4) \
typ1 a1, typ2 a2, typ3 a3, typ4 a4
#define MA std::vector<unsigned char>
#define MA std::vector<uchar>
#define BLA std::vector<Label*>&
#define SLA std::vector<StrOff>&
#define ILA std::vector<IterPair>&
@@ -123,8 +118,7 @@ public:
#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
@@ -145,7 +139,6 @@ public:
#undef AA
#undef BA
#undef OA
#undef VSA
private:
ConstructPtr m_node;
UnitEmitter& m_ue;
@@ -323,137 +316,14 @@ 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();
@@ -462,10 +332,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);
typedef std::vector<int> IndexChain;
void visitListAssignmentLHS(Emitter& e, ExpressionPtr exp,
IndexChain& indexChain,
std::vector<IndexChain*>& chainList);
@@ -480,7 +349,7 @@ 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 popEvalStackLMany();
void popEvalStackMany(int len, char symFlavor);
void popEvalStackCVMany(int len);
void pushEvalStack(char symFlavor);
@@ -501,15 +370,6 @@ public:
|| 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:
@@ -579,11 +439,36 @@ private:
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)
: m_itId(itId), m_itRef(itRef), m_brkTarg(brkTarg), m_cntTarg(cntTarg)
{}
Id m_itId;
bool m_itRef;
Label& m_brkTarg; // Jump here for "break;" (after doing IterFree)
Label& m_cntTarg; // Jump here for "continue;"
};
class ControlTargetPusher {
public:
ControlTargetPusher(EmitterVisitor* e, Id itId, bool itRef, Label& brkTarg,
Label& cntTarg) : m_e(e) {
e->m_controlTargets.push_front(ControlTargets(itId, itRef, brkTarg,
cntTarg));
}
~ControlTargetPusher() {
m_e->m_controlTargets.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;
@@ -597,22 +482,18 @@ private:
class FaultRegion {
public:
FaultRegion(Offset start,
Offset end,
Label* func,
Id iterId,
IterKind kind)
FaultRegion(Offset start, Offset end, Id iterId, IterKind kind)
: m_start(start)
, m_end(end)
, m_func(func)
, m_iterId(iterId)
, m_iterKind(kind) {}
, m_iterKind(kind)
{}
Offset m_start;
Offset m_end;
Label* m_func;
Id m_iterId;
IterKind m_iterKind;
Label m_func; // note: a pointer to this is handed out to the Funclet
};
class FPIRegion {
@@ -660,33 +541,23 @@ private:
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;
std::deque<ControlTargets> m_controlTargets;
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::set<std::string,stdltistr> m_hoistables;
LocationPtr m_tempLoc;
std::map<StringData*, Label, string_data_lt> m_gotoLabels;
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;
MetaInfoBuilder m_metaInfo;
public:
bool checkIfStackEmpty(const char* forInstruction) const;
void unexpectedStackSym(char sym, const char* where) const;
int scanStackForLocation(int iLast);
void buildVectorImm(std::vector<unsigned char>& vectorImm,
void buildVectorImm(std::vector<uchar>& vectorImm,
int iFirst, int iLast, bool allowW,
Emitter& e);
enum class PassByRefKind {
@@ -698,20 +569,26 @@ 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 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);
@@ -732,6 +609,7 @@ public:
void emitStringSwitch(Emitter& e, SwitchStatementPtr s,
std::vector<Label>& caseLabels, Label& done,
const SwitchState& state);
void emitIterBreak(Emitter& e, uint64_t n, Label& targ);
void markElem(Emitter& e);
void markNewElem(Emitter& e);
@@ -797,90 +675,34 @@ 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);
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,
void emitForeachListAssignment(Emitter& e, ListAssignmentPtr la,
int vLocalId);
void emitForeach(Emitter& e, ForEachStatementPtr fe);
void emitRestoreErrorReporting(Emitter& e, Id oldLevelLoc);
void emitMakeUnitFatal(Emitter& e,
const char* msg,
FatalOp k = FatalOp::Runtime);
FatalKind k = FatalKind::Runtime,
bool skipFrame = false);
// 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,
void newFaultRegion(Offset start, Offset end, Thunklet* t,
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 newFPIRegion(Offset start, Offset end, Offset fpOff);
void copyOverCatchAndFaultRegions(FuncEmitter* fe);
void copyOverExnHandlers(FuncEmitter* fe);
void copyOverFPIRegions(FuncEmitter* fe);
void saveMaxStackCells(FuncEmitter* fe);
void finishFunc(Emitter& e, FuncEmitter* fe);
@@ -892,37 +714,11 @@ public:
void emitClassTraitAliasRule(PreClassEmitter* pce,
TraitAliasStatementPtr rule);
void emitClassUseTrait(PreClassEmitter* pce, UseTraitStatementPtr useStmt);
// Helper function for creating entries.
RegionPtr createRegion(StatementPtr s, Region::Kind kind);
// Enter/leave the passed in entry. Note that entries sometimes need be
// to be constructed before they are entered, or need to be accessed
// after they are left. This especially applies to constructs such
// as loops and try blocks.
void enterRegion(RegionPtr);
void leaveRegion(RegionPtr);
// Functions used for handling state IDs allocation.
// FIXME (#3275259): This should be moved into global / func
// body / fault funclet entries in order to optimize state
// allocation. See the task description for more details.
void registerControlTarget(ControlTarget* t);
void unregisterControlTarget(ControlTarget* t);
void registerReturn(StatementPtr s, Region* entry, char sym);
void registerYieldAwait(ExpressionPtr e);
ControlTargetPtr registerBreak(StatementPtr s, Region* entry, int depth,
bool alloc);
ControlTargetPtr registerContinue(StatementPtr s, Region* entry, int depth,
bool alloc);
ControlTargetPtr registerGoto(StatementPtr s, Region* entry,
StringData* name, bool alloc);
};
void emitAllHHBC(AnalysisResultPtr ar);
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,
+89 -93
Ver Arquivo
@@ -13,13 +13,9 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/file_scope.h"
#include <sys/stat.h>
#include "folly/ScopeGuard.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/analysis/lambda_names.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/compiler/analysis/class_scope.h"
#include "hphp/compiler/statement/statement_list.h"
@@ -27,10 +23,11 @@
#include "hphp/compiler/option.h"
#include "hphp/compiler/analysis/constant_table.h"
#include "hphp/compiler/analysis/function_scope.h"
#include <sys/stat.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/util/base.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/compiler/statement/function_statement.h"
#include "hphp/compiler/analysis/variable_table.h"
@@ -39,14 +36,15 @@
#include "hphp/compiler/expression/user_attribute.h"
#include "hphp/runtime/base/complex-types.h"
namespace HPHP {
using namespace HPHP;
///////////////////////////////////////////////////////////////////////////////
FileScope::FileScope(const string &fileName, int fileSize, const MD5 &md5)
: BlockScope("", "", StatementPtr(), BlockScope::FileScope),
m_size(fileSize), m_md5(md5), m_includeState(0), m_system(false),
m_fileName(fileName), m_redeclaredFunctions(0) {
m_size(fileSize), m_md5(md5), m_module(false), m_privateInclude(false),
m_externInclude(false),
m_includeState(0), m_fileName(fileName), m_redeclaredFunctions(0) {
pushAttribute(); // for global scope
}
@@ -68,11 +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;
@@ -105,7 +98,6 @@ void makeFatalMeth(FileScope& file,
int line,
Meth meth) {
LocationPtr loc(new Location());
LabelScopePtr labelScope(new LabelScope());
loc->file = file.getName().c_str();
loc->first(line, 0);
loc->last(line, 0);
@@ -116,8 +108,8 @@ void makeFatalMeth(FileScope& file,
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));
ExpStatementPtr exp(new ExpStatement(scope, loc, e));
StatementListPtr stmts(new StatementList(scope, loc));
stmts->addElement(exp);
FunctionScopePtr fs = file.setTree(ar, stmts);
@@ -262,10 +254,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 +321,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,11 +409,8 @@ const string &FileScope::pseudoMainName() {
FunctionScopePtr FileScope::createPseudoMain(AnalysisResultConstPtr ar) {
StatementListPtr st = m_tree;
LabelScopePtr labelScope(new LabelScope());
FunctionStatementPtr f
(new FunctionStatement(BlockScopePtr(),
labelScope,
LocationPtr(),
(new FunctionStatement(BlockScopePtr(), LocationPtr(),
ModifierExpressionPtr(),
false, pseudoMainName(),
ExpressionListPtr(), TypeAnnotationPtr(),
@@ -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,3 @@ void FileScope::serialize(JSON::DocTarget::OutputStream &out) const {
ms.done();
}
}
+11 -15
Ver Arquivo
@@ -17,16 +17,14 @@
#ifndef incl_HPHP_FILE_SCOPE_H_
#define incl_HPHP_FILE_SCOPE_H_
#include <string>
#include <map>
#include <boost/algorithm/string.hpp>
#include "hphp/compiler/analysis/block_scope.h"
#include "hphp/compiler/analysis/function_container.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/code_generator.h"
#include <boost/graph/adjacency_list.hpp>
#include "hphp/compiler/json.h"
#include "hphp/util/json.h"
#include "hphp/util/md5.h"
namespace HPHP {
@@ -64,7 +62,6 @@ public:
IsFoldable = 0x1000,// function can be constant folded
NeedsActRec = 0x2000,// builtin function needs ActRec
AllowOverride = 0x4000,// allow override of systemlib or builtin
NeedsFinallyLocals = 0x8000,
};
typedef boost::adjacency_list<boost::setS, boost::vecS> Graph;
@@ -80,7 +77,6 @@ public:
const std::string &getName() const { return m_fileName;}
const MD5& getMd5() const { return m_md5; }
void setMd5(const MD5& md5) { m_md5 = md5; }
StatementListPtr getStmt() const { return m_tree;}
const StringToClassScopePtrVecMap &getClasses() const {
return m_classes;
@@ -145,12 +141,8 @@ public:
const std::string &decname);
void addClassAlias(const std::string& target, const std::string& alias) {
m_classAliasMap.insert(
std::make_pair(
boost::to_lower_copy(target),
boost::to_lower_copy(alias)
)
);
m_classAliasMap.insert(std::make_pair(Util::toLower(target),
Util::toLower(alias)));
}
std::multimap<std::string,std::string> const& getClassAliases() const {
@@ -158,7 +150,7 @@ public:
}
void addTypeAliasName(const std::string& name) {
m_typeAliasNames.insert(boost::to_lower_copy(name));
m_typeAliasNames.insert(Util::toLower(name));
}
std::set<std::string> const& getTypeAliasNames() const {
@@ -173,8 +165,10 @@ public:
m_vertex = vertex;
}
void setSystem();
bool isSystem() const { return m_system; }
void setModule() { m_module = true; }
void setPrivateInclude() { m_privateInclude = true; }
bool isPrivateInclude() const { return m_privateInclude && !m_externInclude; }
void setExternInclude() { m_externInclude = true; }
void analyzeProgram(AnalysisResultPtr ar);
void analyzeIncludes(AnalysisResultPtr ar);
@@ -204,8 +198,10 @@ public:
private:
int m_size;
MD5 m_md5;
unsigned m_module : 1;
unsigned m_privateInclude : 1;
unsigned m_externInclude : 1;
unsigned m_includeState : 2;
unsigned m_system : 1;
std::vector<int> m_attributes;
std::string m_fileName;
+1 -1
Ver Arquivo
@@ -24,7 +24,7 @@ namespace HPHP {
class CodeGenerator;
DECLARE_BOOST_TYPES(AnalysisResult);
DECLARE_EXTENDED_BOOST_TYPES(FunctionScope);
DECLARE_BOOST_TYPES(FunctionScope);
DECLARE_BOOST_TYPES(ClassScope);
DECLARE_BOOST_TYPES(FunctionContainer);
+6 -15
Ver Arquivo
@@ -292,8 +292,7 @@ bool FunctionScope::hasUserAttr(const char *attr) const {
}
bool FunctionScope::isZendParamMode() const {
return m_attributeClassInfo &
(ClassInfo::ZendParamModeNull | ClassInfo::ZendParamModeFalse);
return m_attributeClassInfo & ClassInfo::ZendParamMode;
}
bool FunctionScope::isPublic() const {
@@ -355,11 +354,6 @@ bool FunctionScope::needsActRec() const {
return res;
}
bool FunctionScope::needsFinallyLocals() const {
bool res = (m_attribute & FileScope::NeedsFinallyLocals);
return res;
}
bool FunctionScope::mayContainThis() {
return inPseudoMain() || getContainingClass() ||
(isClosure() && !m_modifiers->isStatic());
@@ -848,14 +842,11 @@ bool FunctionScope::popReturnType() {
m_prevReturn.reset();
return false;
}
Logger::Verbose("Corrected %s's return type %s -> %s",
getFullName().c_str(),
m_prevReturn->toString().c_str(),
m_returnType->toString().c_str());
} else {
Logger::Verbose("Set %s's return type %s",
getFullName().c_str(),
m_returnType->toString().c_str());
if (!isFirstPass()) {
Logger::Verbose("Corrected function return type %s -> %s",
m_prevReturn->toString().c_str(),
m_returnType->toString().c_str());
}
}
} else if (!m_prevReturn) {
return false;
+2 -6
Ver Arquivo
@@ -20,9 +20,8 @@
#include "hphp/compiler/expression/user_attribute.h"
#include "hphp/compiler/analysis/block_scope.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/json.h"
#include "hphp/util/hash-map-typedefs.h"
#include "hphp/util/json.h"
#include "hphp/parser/parser.h"
namespace HPHP {
@@ -96,7 +95,6 @@ public:
* What kind of function this is.
*/
bool isUserFunction() const { return !m_system && !isNative(); }
bool isSystem() const { return m_system; }
bool isDynamic() const { return m_dynamic; }
bool isPublic() const;
bool isProtected() const;
@@ -228,8 +226,6 @@ public:
bool allowOverride() const;
void setAllowOverride();
bool needsFinallyLocals() const;
/**
* Whether this function is a runtime helper function
*/
@@ -389,7 +385,7 @@ public:
ReadWriteMutex &getInlineMutex() { return m_inlineMutex; }
DECLARE_EXTENDED_BOOST_TYPES(FunctionInfo);
DECLARE_BOOST_TYPES(FunctionInfo);
static void RecordFunctionInfo(std::string fname, FunctionScopePtr func);
-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
+1 -2
Ver Arquivo
@@ -623,8 +623,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);
}
}
+5 -5
Ver Arquivo
@@ -24,7 +24,7 @@ namespace HPHP { namespace Compiler {
static void collapseJmp(Offset* offsetPtr, Op* instr, Op* start) {
if (offsetPtr) {
Op* dest = instr + *offsetPtr;
while (isUnconditionalJmp(*dest) && dest != instr) {
while (*dest == OpJmp && dest != instr) {
dest = start + instrJumpTarget(start, dest - start);
}
*offsetPtr = dest - instr;
@@ -91,10 +91,10 @@ Peephole::Peephole(UnitEmitter &ue, MetaInfoBuilder& metaInfo)
// fallthrough
incDecOp:
if (static_cast<IncDecOp>(imm->u_OA) == IncDecOp::PostInc) {
imm->u_OA = static_cast<unsigned char>(IncDecOp::PreInc);
} else if (static_cast<IncDecOp>(imm->u_OA) == IncDecOp::PostDec) {
imm->u_OA = static_cast<unsigned char>(IncDecOp::PreDec);
if (imm->u_OA == PostInc) {
imm->u_OA = PreInc;
} else if (imm->u_OA == PostDec) {
imm->u_OA = PreDec;
}
break;
default:
+2 -3
Ver Arquivo
@@ -18,10 +18,9 @@
#define incl_HPHP_SYMBOL_TABLE_H_
#include "hphp/compiler/hphp.h"
#include "hphp/compiler/json.h"
#include "hphp/util/json.h"
#include "hphp/util/util.h"
#include "hphp/util/lock.h"
#include "hphp/util/hash-map-typedefs.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -30,7 +29,7 @@ class BlockScope;
class CodeGenerator;
class Variant;
DECLARE_BOOST_TYPES(Construct);
DECLARE_EXTENDED_BOOST_TYPES(Type);
DECLARE_BOOST_TYPES(Type);
DECLARE_BOOST_TYPES(AnalysisResult);
DECLARE_BOOST_TYPES(SymbolTable);
DECLARE_BOOST_TYPES(FunctionScope);
-3
Ver Arquivo
@@ -21,7 +21,6 @@
#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 <boost/format.hpp>
using namespace HPHP;
@@ -71,8 +70,6 @@ void Type::InitTypeHintMap() {
s_HHTypeHintTypes["double"] = Type::Double;
s_HHTypeHintTypes["float"] = Type::Double;
s_HHTypeHintTypes["string"] = Type::String;
// Type::Numeric doesn't include numeric strings; this is intentional
s_HHTypeHintTypes["num"] = Type::Numeric;
s_HHTypeHintTypes["resource"] = Type::Resource;
s_HHTypeHintTypes["callable"] = Type::Variant;
}
+2 -2
Ver Arquivo
@@ -18,8 +18,8 @@
#define incl_HPHP_TYPE_H_
#include "hphp/compiler/hphp.h"
#include "hphp/compiler/json.h"
#include "hphp/util/functional.h"
#include "hphp/util/json.h"
#include "hphp/util/case-insensitive.h"
#include "hphp/runtime/base/types.h"
+1 -3
Ver Arquivo
@@ -428,9 +428,7 @@ TypePtr VariableTable::add(Symbol *sym, TypePtr type,
type = setType(ar, sym, type, true);
if (sym->isParameter()) {
auto p = dynamic_pointer_cast<ParameterExpression>(construct);
if (p) {
sym->setDeclaration(construct);
}
if (p) sym->setDeclaration(construct);
} else {
sym->setDeclaration(construct);
}
+1 -2
Ver Arquivo
@@ -20,7 +20,6 @@
#include "hphp/compiler/analysis/symbol_table.h"
#include "hphp/compiler/statement/statement.h"
#include "hphp/compiler/analysis/class_scope.h"
#include "hphp/util/hash-map-typedefs.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -297,7 +296,7 @@ public:
* GlobalVariables class to make ThreadLocal<GlobalVaribles> work.
* This data structure is only needed by global scope.
*/
DECLARE_EXTENDED_BOOST_TYPES(StaticGlobalInfo);
DECLARE_BOOST_TYPES(StaticGlobalInfo);
struct StaticGlobalInfo {
Symbol *sym;
VariableTable *variables; // where this variable was from
+124 -38
Ver Arquivo
@@ -50,7 +50,8 @@ using namespace HPHP;
bool BuiltinSymbols::Loaded = false;
StringBag BuiltinSymbols::s_strings;
AnalysisResultPtr BuiltinSymbols::s_systemAr;
StringToFunctionScopePtrMap BuiltinSymbols::s_functions;
const char *const BuiltinSymbols::GlobalNames[] = {
"HTTP_RAW_POST_DATA",
@@ -85,7 +86,12 @@ const char *BuiltinSymbols::SystemClasses[] = {
nullptr
};
StringToClassScopePtrMap BuiltinSymbols::s_classes;
VariableTablePtr BuiltinSymbols::s_variables;
ConstantTablePtr BuiltinSymbols::s_constants;
StringToTypePtrMap BuiltinSymbols::s_superGlobals;
AnalysisResultPtr BuiltinSymbols::s_systemAr;
void *BuiltinSymbols::s_handle_main = nullptr;
///////////////////////////////////////////////////////////////////////////////
@@ -212,6 +218,7 @@ FunctionScopePtr BuiltinSymbols::ImportFunctionScopePtr(AnalysisResultPtr ar,
}
void BuiltinSymbols::ImportExtFunctions(AnalysisResultPtr ar,
StringToFunctionScopePtrMap &map,
ClassInfo *cls) {
const ClassInfo::MethodVec &methods = cls->getMethodsVec();
for (auto it = methods.begin(); it != methods.end(); ++it) {
@@ -221,13 +228,14 @@ void BuiltinSymbols::ImportExtFunctions(AnalysisResultPtr ar,
}
FunctionScopePtr f = ImportFunctionScopePtr(ar, cls, *it);
ar->addSystemFunction(f);
assert(!map[f->getName()]);
map[f->getName()] = f;
}
}
void BuiltinSymbols::ImportExtMethods(AnalysisResultPtr ar,
FunctionScopePtrVec &vec,
ClassInfo *cls) {
void BuiltinSymbols::ImportExtFunctions(AnalysisResultPtr ar,
FunctionScopePtrVec &vec,
ClassInfo *cls) {
const ClassInfo::MethodVec &methods = cls->getMethodsVec();
for (auto it = methods.begin(); it != methods.end(); ++it) {
FunctionScopePtr f = ImportFunctionScopePtr(ar, cls, *it);
@@ -279,7 +287,7 @@ void BuiltinSymbols::ImportExtConstants(AnalysisResultPtr ar,
ClassScopePtr BuiltinSymbols::ImportClassScopePtr(AnalysisResultPtr ar,
ClassInfo *cls) {
FunctionScopePtrVec methods;
ImportExtMethods(ar, methods, cls);
ImportExtFunctions(ar, methods, cls);
ClassInfo::InterfaceVec ifaces = cls->getInterfacesVec();
String parent = cls->getParentClass();
@@ -317,7 +325,8 @@ void BuiltinSymbols::ImportExtClasses(AnalysisResultPtr ar) {
}
ClassScopePtr cl = ImportClassScopePtr(ar, it->second);
ar->addSystemClass(cl);
assert(!s_classes[cl->getName()]);
s_classes[cl->getName()] = cl;
}
}
@@ -329,11 +338,13 @@ bool BuiltinSymbols::Load(AnalysisResultPtr ar) {
ClassInfo::Load();
// load extension functions first, so system/php may call them
ImportExtFunctions(ar, ClassInfo::GetSystem());
ImportExtFunctions(ar, s_functions, ClassInfo::GetSystem());
AnalysisResultPtr ar2 = AnalysisResultPtr(new AnalysisResult());
s_variables = VariableTablePtr(new VariableTable(*ar2.get()));
s_constants = ConstantTablePtr(new ConstantTable(*ar2.get()));
ConstantTablePtr cns = ar->getConstants();
// load extension constants, classes and dynamics
ImportExtConstants(ar, cns, ClassInfo::GetSystem());
ImportExtConstants(ar, s_constants, ClassInfo::GetSystem());
ImportExtClasses(ar);
Array constants = ClassInfo::GetSystemConstants();
@@ -342,11 +353,11 @@ bool BuiltinSymbols::Load(AnalysisResultPtr ar) {
CVarRef key = it.first();
if (!key.isString()) continue;
std::string name = key.toCStrRef().data();
if (cns->getSymbol(name)) continue;
if (s_constants->getSymbol(name)) continue;
if (name == "true" || name == "false" || name == "null") continue;
CVarRef value = it.secondRef();
if (!value.isInitialized() || value.isObject()) continue;
ExpressionPtr e = Expression::MakeScalarExpression(ar, ar, loc, value);
ExpressionPtr e = Expression::MakeScalarExpression(ar2, ar2, loc, value);
TypePtr t =
value.isNull() ? Type::Null :
value.isBoolean() ? Type::Boolean :
@@ -354,47 +365,122 @@ bool BuiltinSymbols::Load(AnalysisResultPtr ar) {
value.isDouble() ? Type::Double :
value.isArray() ? Type::Array : Type::Variant;
cns->add(key.toCStrRef().data(), t, e, ar, e);
s_constants->add(key.toCStrRef().data(), t, e, ar2, e);
}
s_variables = ar2->getVariables();
for (int i = 0, n = NumGlobalNames(); i < n; ++i) {
ar->getVariables()->add(GlobalNames[i], Type::Variant, false, ar,
ConstructPtr(), ModifierExpressionPtr());
s_variables->add(GlobalNames[i], Type::Variant, false, ar,
ConstructPtr(), ModifierExpressionPtr());
}
cns->setDynamic(ar, "PHP_BINARY", true);
cns->setDynamic(ar, "PHP_BINDIR", true);
cns->setDynamic(ar, "PHP_OS", true);
cns->setDynamic(ar, "PHP_SAPI", true);
cns->setDynamic(ar, "SID", true);
s_constants->setDynamic(ar, "PHP_BINARY", true);
s_constants->setDynamic(ar, "PHP_BINDIR", true);
s_constants->setDynamic(ar, "PHP_OS", true);
s_constants->setDynamic(ar, "PHP_SAPI", true);
s_constants->setDynamic(ar, "SID", true);
// Systemlib files were all parsed by hphp_process_init
// parse all PHP files under system/php
s_systemAr = ar = AnalysisResultPtr(new AnalysisResult());
ar->loadBuiltins();
string slib = get_systemlib();
Scanner scanner(slib.c_str(), slib.size(),
Option::GetScannerType(), "systemlib.php");
Compiler::Parser parser(scanner, "systemlib.php", ar);
if (!parser.parse()) {
Logger::Error("Unable to parse systemlib.php: %s",
parser.getMessage().c_str());
assert(false);
}
ar->analyzeProgram(true);
ar->inferTypes();
const StringToFileScopePtrMap &files = ar->getAllFiles();
for (const auto& file : files) {
file.second->setSystem();
const auto& classes = file.second->getClasses();
for (const auto& clsVec : classes) {
assert(clsVec.second.size() == 1);
auto cls = clsVec.second[0];
cls->setSystem();
ar->addSystemClass(cls);
for (const auto& func : cls->getFunctions()) {
FunctionScope::RecordFunctionInfo(func.first, func.second);
}
for (StringToFileScopePtrMap::const_iterator iterFile = files.begin();
iterFile != files.end(); iterFile++) {
const StringToClassScopePtrVecMap &classes =
iterFile->second->getClasses();
for (StringToClassScopePtrVecMap::const_iterator iter = classes.begin();
iter != classes.end(); ++iter) {
assert(iter->second.size() == 1);
iter->second[0]->setSystem();
assert(!s_classes[iter->first]);
s_classes[iter->first] = iter->second[0];
}
const auto& functions = file.second->getFunctions();
for (const auto& func : functions) {
func.second->setSystem();
ar->addSystemFunction(func.second);
FunctionScope::RecordFunctionInfo(func.first, func.second);
const StringToFunctionScopePtrMap &functions =
iterFile->second->getFunctions();
for (StringToFunctionScopePtrMap::const_iterator iter = functions.begin();
iter != functions.end(); ++iter) {
iter->second->setSystem();
s_functions[iter->first] = iter->second;
}
}
return true;
}
AnalysisResultPtr BuiltinSymbols::LoadGlobalSymbols(const char *fileName) {
AnalysisResultPtr ar(new AnalysisResult());
string phpBaseName = "/system/globals/";
phpBaseName += fileName;
string phpFileName = Option::GetSystemRoot() + phpBaseName;
const char *baseName = s_strings.add(phpBaseName.c_str());
fileName = s_strings.add(phpFileName.c_str());
try {
Scanner scanner(fileName, Option::GetScannerType());
Compiler::Parser parser(scanner, baseName, ar);
if (!parser.parse()) {
assert(false);
Logger::Error("Unable to parse file %s: %s", fileName,
parser.getMessage().c_str());
}
} catch (FileOpenException &e) {
Logger::Error("%s", e.getMessage().c_str());
}
ar->analyzeProgram(true);
ar->inferTypes();
return ar;
}
void BuiltinSymbols::LoadFunctions(AnalysisResultPtr ar,
StringToFunctionScopePtrMap &functions) {
assert(Loaded);
functions.insert(s_functions.begin(), s_functions.end());
}
void BuiltinSymbols::LoadClasses(AnalysisResultPtr ar,
StringToClassScopePtrMap &classes) {
assert(Loaded);
classes.insert(s_classes.begin(), s_classes.end());
}
void BuiltinSymbols::LoadVariables(AnalysisResultPtr ar,
VariableTablePtr variables) {
assert(Loaded);
if (s_variables) {
variables->import(s_variables);
}
}
void BuiltinSymbols::LoadConstants(AnalysisResultPtr ar,
ConstantTablePtr constants) {
assert(Loaded);
if (s_constants) {
constants->import(s_constants);
}
}
ConstantTablePtr BuiltinSymbols::LoadSystemConstants() {
AnalysisResultPtr ar = LoadGlobalSymbols("constants.php");
const auto &fileScopes = ar->getAllFilesVector();
if (!fileScopes.empty()) {
return fileScopes[0]->getConstants();
}
throw std::runtime_error("LoadSystemConstants failed");
}
void BuiltinSymbols::LoadSuperGlobals() {
if (s_superGlobals.empty()) {
s_superGlobals["_SERVER"] = Type::Variant;
+22 -7
Ver Arquivo
@@ -24,17 +24,16 @@
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_EXTENDED_BOOST_TYPES(Type);
DECLARE_BOOST_TYPES(Type);
DECLARE_BOOST_TYPES(AnalysisResult);
DECLARE_EXTENDED_BOOST_TYPES(FunctionScope);
DECLARE_EXTENDED_BOOST_TYPES(ClassScope);
DECLARE_BOOST_TYPES(FunctionScope);
DECLARE_BOOST_TYPES(ClassScope);
DECLARE_BOOST_TYPES(VariableTable);
DECLARE_BOOST_TYPES(ConstantTable);
class BuiltinSymbols {
public:
static bool Loaded;
static AnalysisResultPtr s_systemAr;
static bool Load(AnalysisResultPtr ar);
@@ -47,6 +46,11 @@ public:
static void LoadConstants(AnalysisResultPtr ar,
ConstantTablePtr constants);
/*
* Load system/globals/constants.php.
*/
static ConstantTablePtr LoadSystemConstants();
/**
* Testing whether a variable is a PHP superglobal.
*/
@@ -56,24 +60,35 @@ public:
static bool IsDeclaredDynamic(const std::string& name);
static void LoadSuperGlobals();
static StringToFunctionScopePtrMap s_functions;
static StringToClassScopePtrMap s_classes;
static VariableTablePtr s_variables;
static ConstantTablePtr s_constants;
static AnalysisResultPtr s_systemAr;
static const char *const GlobalNames[];
static int NumGlobalNames();
private:
static StringBag s_strings;
static const char *SystemClasses[];
static AnalysisResultPtr LoadGlobalSymbols(const char *fileName);
static StringToTypePtrMap s_superGlobals;
static std::set<std::string> s_declaredDynamic;
static void *s_handle_main;
static FunctionScopePtr ImportFunctionScopePtr(AnalysisResultPtr ar,
ClassInfo *cls,
ClassInfo::MethodInfo *method);
static void ImportExtFunctions(AnalysisResultPtr ar,
StringToFunctionScopePtrMap &map,
ClassInfo *cls);
static void ImportExtFunctions(AnalysisResultPtr ar,
FunctionScopePtrVec &vec,
ClassInfo *cls);
static void ImportExtMethods(AnalysisResultPtr ar,
FunctionScopePtrVec &vec,
ClassInfo *cls);
static void ImportExtProperties(AnalysisResultPtr ar,
VariableTablePtr dest,
ClassInfo *cls);
+2 -171
Ver Arquivo
@@ -14,16 +14,15 @@
+----------------------------------------------------------------------+
*/
#include <stdarg.h>
#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 <boost/format.hpp>
@@ -425,171 +424,3 @@ int CodeGenerator::ClassScopeCompare::cmp(const ClassScopeRawPtr &p1,
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();
}
+1 -31
Ver Arquivo
@@ -24,16 +24,12 @@ 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 {
@@ -270,37 +265,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];
-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_
+6 -16
Ver Arquivo
@@ -25,7 +25,7 @@
#include "hphp/compiler/option.h"
#include "hphp/compiler/parser/parser.h"
#include "hphp/compiler/builtin_symbols.h"
#include "hphp/compiler/json.h"
#include "hphp/util/json.h"
#include "hphp/util/logger.h"
#include "hphp/util/db-conn.h"
#include "hphp/util/exception.h"
@@ -344,8 +344,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,7 +358,7 @@ 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";
#define HPHP_VERSION(v) cout << HPHP_COMPILER_STR #v << "\n";
#include "../version" // nolint
cout << "Compiler: " << kCompilerId << "\n";
@@ -484,8 +484,6 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
Option::ParseTimeOpts = false;
}
initialize_hhbbc_options();
return 0;
}
@@ -542,12 +540,6 @@ int process(const CompilerOptions &po) {
bool isPickledPHP = (po.target == "php" && po.format == "pickled");
if (!isPickledPHP) {
bool wp = Option::WholeProgram;
Option::WholeProgram = false;
BuiltinSymbols::s_systemAr = ar;
hphp_process_init();
BuiltinSymbols::s_systemAr.reset();
Option::WholeProgram = wp;
if (po.target == "hhbc" && !Option::WholeProgram) {
// We're trying to produce the same bytecode as runtime parsing.
// There's nothing to do.
@@ -555,7 +547,9 @@ int process(const CompilerOptions &po) {
if (!BuiltinSymbols::Load(ar)) {
return false;
}
ar->loadBuiltins();
}
hphp_process_init();
}
{
@@ -602,7 +596,6 @@ int process(const CompilerOptions &po) {
return 1;
}
if (Option::WholeProgram || po.target == "analyze") {
Timer timer(Timer::WallTime, "analyzeProgram");
ar->analyzeProgram();
}
}
@@ -807,7 +800,6 @@ void hhbcTargetInit(const CompilerOptions &po, AnalysisResultPtr ar) {
if (po.format.find("exe") != string::npos) {
RuntimeOption::RepoCentralPath += ".hhbc";
}
unlink(RuntimeOption::RepoCentralPath.c_str());
RuntimeOption::RepoLocalMode = "--";
RuntimeOption::RepoDebugInfo = Option::RepoDebugInfo;
RuntimeOption::RepoJournal = "memory";
@@ -923,8 +915,6 @@ int runTarget(const CompilerOptions &po) {
cmd += buf;
cmd += " -vRepo.Authoritative=true";
if (getenv("HPHP_DUMP_BYTECODE")) cmd += " -vEval.DumpBytecode=1";
if (getenv("HPHP_INTERP")) cmd += " -vEval.Jit=0";
cmd += " -vRepo.Local.Mode=r- -vRepo.Local.Path=";
}
cmd += po.outputDir + '/' + po.program;
+1 -15
Ver Arquivo
@@ -469,23 +469,9 @@ void Construct::parseTimeFatal(Compiler::ErrorType err, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
string msg;
string_vsnprintf(msg, fmt, ap);
Util::string_vsnprintf(msg, fmt, ap);
va_end(ap);
if (err != Compiler::NoError) Compiler::Error(err, shared_from_this());
throw ParseTimeFatalException(m_loc->file, m_loc->line0, "%s", msg.c_str());
}
void Construct::analysisTimeFatal(Compiler::ErrorType err,
const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
string msg;
string_vsnprintf(msg, fmt, ap);
va_end(ap);
assert(err != Compiler::NoError);
Compiler::Error(err, shared_from_this());
throw AnalysisTimeFatalException(m_loc->file, m_loc->line0,
"%s [analysis]", msg.c_str());
}
+7 -10
Ver Arquivo
@@ -17,7 +17,7 @@
#ifndef incl_HPHP_CONSTRUCT_H_
#define incl_HPHP_CONSTRUCT_H_
#include "hphp/compiler/json.h"
#include "hphp/util/json.h"
#include "hphp/compiler/code_generator.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/analysis/block_scope.h"
@@ -166,6 +166,10 @@ public:
void clearKilled() { m_flags.killed = false; }
bool isKilled() const { return m_flags.killed; }
void setChildOfYield() { m_flags.childOfYield = true; }
void clearChildOfYield() { m_flags.childOfYield = false; }
bool isChildOfYield() const { return m_flags.childOfYield; }
BlockScopeRawPtr getScope() const { return m_blockScope; }
void setBlockScope(BlockScopeRawPtr scope) { m_blockScope = scope; }
FileScopeRawPtr getFileScope() const {
@@ -180,8 +184,6 @@ public:
void resetScope(BlockScopeRawPtr scope, bool resetOrigScope=false);
void parseTimeFatal(Compiler::ErrorType error, const char *fmt, ...)
ATTRIBUTE_PRINTF(3,4);
void analysisTimeFatal(Compiler::ErrorType error, const char *fmt, ...)
ATTRIBUTE_PRINTF(3,4);
virtual int getLocalEffects() const { return UnknownEffect;}
int getChildrenEffects() const;
int getContainedEffects() const;
@@ -197,8 +199,7 @@ public:
}
template<typename T>
std::shared_ptr<T> Clone(std::shared_ptr<T> constr,
BlockScopePtr scope) {
std::shared_ptr<T> Clone(std::shared_ptr<T> constr, BlockScopePtr scope) {
if (constr) {
constr = constr->clone();
constr->resetScope(scope);
@@ -246,11 +247,6 @@ 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.
*/
@@ -303,6 +299,7 @@ private:
unsigned killed : 1;
unsigned refCounted : 2; // high bit indicates whether its valid
unsigned inited : 2; // high bit indicates whether its valid
unsigned childOfYield : 1; // parent node is yield
} m_flags;
};
protected:
@@ -19,7 +19,6 @@
#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"
@@ -389,42 +388,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
@@ -17,7 +17,6 @@
#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"
using namespace HPHP;
@@ -123,25 +122,6 @@ 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
@@ -26,7 +26,6 @@
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/expression/unary_op_expression.h"
#include "hphp/parser/hphp.tab.hpp"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/analysis/class_scope.h"
#include "hphp/compiler/analysis/function_scope.h"
@@ -307,21 +306,6 @@ TypePtr AssignmentExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return inferAssignmentTypes(ar, type, coerce, m_variable, m_value);
}
///////////////////////////////////////////////////////////////////////////////
void AssignmentExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("BinaryOpExpression", 4);
cg.printPropertyHeader("expression1");
m_variable->outputCodeModel(cg);
cg.printPropertyHeader("expression2");
cg.printExpression(m_value, m_ref);
cg.printPropertyHeader("operation");
cg.printValue(PHP_ASSIGNMENT);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -16,7 +16,6 @@
#include "hphp/compiler/expression/await_expression.h"
#include "hphp/compiler/analysis/function_scope.h"
#include "hphp/compiler/code_model_enums.h"
using namespace HPHP;
@@ -83,18 +82,6 @@ TypePtr AwaitExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return Type::Variant;
}
///////////////////////////////////////////////////////////////////////////////
void AwaitExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("UnaryOpExpression", 3);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("operation");
cg.printValue(PHP_AWAIT_OP);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -21,7 +21,6 @@
#include "hphp/parser/hphp.tab.hpp"
#include "hphp/compiler/expression/scalar_expression.h"
#include "hphp/compiler/expression/constant_expression.h"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/runtime/base/complex-types.h"
#include "hphp/runtime/base/type-conversions.h"
#include "hphp/runtime/base/builtin-functions.h"
@@ -33,7 +32,6 @@
#include "hphp/compiler/expression/simple_variable.h"
#include "hphp/compiler/statement/loop_statement.h"
#include "hphp/runtime/base/tv-arith.h"
#include "hphp/runtime/vm/runtime.h"
using namespace HPHP;
@@ -67,7 +65,7 @@ BinaryOpExpression::BinaryOpExpression
break;
case T_COLLECTION: {
std::string s = m_exp1->getLiteralString();
Collection::Type cType = Collection::InvalidType;
int cType = 0;
if (strcasecmp(s.c_str(), "vector") == 0) {
cType = Collection::VectorType;
} else if (strcasecmp(s.c_str(), "map") == 0) {
@@ -78,12 +76,6 @@ BinaryOpExpression::BinaryOpExpression
cType = Collection::SetType;
} else if (strcasecmp(s.c_str(), "pair") == 0) {
cType = Collection::PairType;
} else if (strcasecmp(s.c_str(), "frozenvector") == 0) {
cType = Collection::FrozenVectorType;
} else if (strcasecmp(s.c_str(), "frozenmap") == 0) {
cType = Collection::FrozenMapType;
} else if (strcasecmp(s.c_str(), "frozenset") == 0) {
cType = Collection::FrozenSetType;
}
ExpressionListPtr el = static_pointer_cast<ExpressionList>(m_exp2);
el->setCollectionType(cType);
@@ -484,9 +476,6 @@ ExpressionPtr BinaryOpExpression::foldConst(AnalysisResultConstPtr ar) {
ExpressionPtr aExp = m_exp1;
ExpressionPtr bExp = binOpExp->m_exp1;
ExpressionPtr cExp = binOpExp->m_exp2;
if (aExp->isArray() || bExp->isArray() || cExp->isArray()) {
break;
}
m_exp1 = binOpExp = Clone(binOpExp);
m_exp2 = cExp;
binOpExp->m_exp1 = aExp;
@@ -547,9 +536,6 @@ ExpressionPtr BinaryOpExpression::foldConst(AnalysisResultConstPtr ar) {
*result.asCell() = cellBitXor(*v1.asCell(), *v2.asCell());
break;
case '.':
if (v1.isArray() || v2.isArray()) {
return ExpressionPtr();
}
result = concat(v1.toString(), v2.toString());
break;
case T_IS_IDENTICAL:
@@ -816,7 +802,7 @@ TypePtr BinaryOpExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
case T_COLLECTION:
et1 = Type::Any;
et2 = Type::Any;
rt = Type::CreateObjectType(m_exp1->getLiteralString());
rt = Type::Object;
break;
default:
assert(false);
@@ -925,76 +911,6 @@ TypePtr BinaryOpExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return rt;
}
///////////////////////////////////////////////////////////////////////////////
void BinaryOpExpression::outputCodeModel(CodeGenerator &cg) {
if (m_op == T_COLLECTION) {
cg.printObjectHeader("CollectionInitializerExpression", 3);
cg.printPropertyHeader("collection");
m_exp1->outputCodeModel(cg);
cg.printPropertyHeader("arguments");
cg.printExpressionVector(static_pointer_cast<ExpressionList>(m_exp2));
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
return;
}
cg.printObjectHeader("BinaryOpExpression", 4);
cg.printPropertyHeader("expression1");
m_exp1->outputCodeModel(cg);
cg.printPropertyHeader("expression2");
m_exp2->outputCodeModel(cg);
cg.printPropertyHeader("operation");
int op = 0;
switch (m_op) {
case T_PLUS_EQUAL: op = PHP_PLUS_ASSIGN; break;
case T_MINUS_EQUAL: op = PHP_MINUS_ASSIGN; break;
case T_MUL_EQUAL: op = PHP_MULTIPLY_ASSIGN; break;
case T_DIV_EQUAL: op = PHP_DIVIDE_ASSIGN; break;
case T_CONCAT_EQUAL: op = PHP_CONCAT_ASSIGN; break;
case T_MOD_EQUAL: op = PHP_MODULUS_ASSIGN; break;
case T_AND_EQUAL: op = PHP_AND_ASSIGN; break;
case T_OR_EQUAL: op = PHP_OR_ASSIGN; break;
case T_XOR_EQUAL: op = PHP_XOR_ASSIGN; break;
case T_SL_EQUAL: op = PHP_SHIFT_LEFT_ASSIGN; break;
case T_SR_EQUAL: op = PHP_SHIFT_RIGHT_ASSIGN; break;
case T_BOOLEAN_OR: op = PHP_BOOLEAN_OR; break;
case T_BOOLEAN_AND: op = PHP_BOOLEAN_AND; break;
case T_LOGICAL_OR: op = PHP_LOGICAL_OR; break;
case T_LOGICAL_AND: op = PHP_LOGICAL_AND; break;
case T_LOGICAL_XOR: op = PHP_LOGICAL_XOR; break;
case '|': op = PHP_OR; break;
case '&': op = PHP_AND; break;
case '^': op = PHP_XOR; break;
case '.': op = PHP_CONCAT; break;
case '+': op = PHP_PLUS; break;
case '-': op = PHP_MINUS; break;
case '*': op = PHP_MULTIPLY; break;
case '/': op = PHP_DIVIDE; break;
case '%': op = PHP_MODULUS; break;
case T_SL: op = PHP_SHIFT_LEFT; break;
case T_SR: op = PHP_SHIFT_RIGHT; break;
case T_IS_IDENTICAL: op = PHP_IS_IDENTICAL; break;
case T_IS_NOT_IDENTICAL: op = PHP_IS_NOT_IDENTICAL; break;
case T_IS_EQUAL: op = PHP_IS_EQUAL; break;
case T_IS_NOT_EQUAL: op = PHP_IS_NOT_EQUAL; break;
case '<': op = PHP_IS_SMALLER; break;
case T_IS_SMALLER_OR_EQUAL: op = PHP_IS_SMALLER_OR_EQUAL; break;
case '>': op = PHP_IS_GREATER; break;
case T_IS_GREATER_OR_EQUAL: op = PHP_IS_GREATER_OR_EQUAL; break;
case T_INSTANCEOF: op = PHP_INSTANCEOF; break;
default:
assert(false);
}
cg.printValue(op);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -1075,3 +991,4 @@ bool BinaryOpExpression::isOpEqual() {
}
return false;
}
@@ -221,18 +221,6 @@ bool ClassConstantExpression::canonCompare(ExpressionPtr e) const {
m_className == static_cast<ClassConstantExpression*>(e.get())->m_className;
}
///////////////////////////////////////////////////////////////////////////////
void ClassConstantExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ClassPropertyExpression", 3);
cg.printPropertyHeader("className");
StaticClassName::outputCodeModel(cg);
cg.printPropertyHeader("propertyName");
cg.printValue(m_varName);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -46,7 +46,6 @@ public:
bool isValid() const { return m_valid; }
bool isDynamic() const;
bool hasClass() const { return m_defScope != 0; }
bool isColonColonClass() const { return m_varName == "class"; }
private:
std::string m_varName;
BlockScope *m_defScope;
+102 -203
Ver Arquivo
@@ -13,11 +13,8 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/expression/closure_expression.h"
#include <boost/make_shared.hpp>
#include "folly/ScopeGuard.h"
#include "hphp/compiler/expression/parameter_expression.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/compiler/expression/simple_variable.h"
@@ -27,79 +24,68 @@
#include "hphp/compiler/analysis/function_scope.h"
#include "hphp/compiler/analysis/file_scope.h"
namespace HPHP {
//////////////////////////////////////////////////////////////////////
using namespace HPHP;
TypePtr ClosureExpression::s_ClosureType =
Type::CreateObjectType("closure"); // needs lower case
ClosureExpression::ClosureExpression(
EXPRESSION_CONSTRUCTOR_PARAMETERS,
ClosureType type,
FunctionStatementPtr func,
ExpressionListPtr vars)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ClosureExpression))
, m_type(type)
, m_func(func)
, m_captureState(m_type == ClosureType::Short ? CaptureState::Unknown
: CaptureState::Known)
{
switch (m_type) {
case ClosureType::Short:
break;
case ClosureType::Long:
if (vars) initializeFromUseList(vars);
break;
}
}
///////////////////////////////////////////////////////////////////////////////
// constructors/destructors
void ClosureExpression::initializeFromUseList(ExpressionListPtr vars) {
m_vars = ExpressionListPtr(
new ExpressionList(vars->getScope(), vars->getLocation()));
ClosureExpression::ClosureExpression
(EXPRESSION_CONSTRUCTOR_PARAMETERS, FunctionStatementPtr func,
ExpressionListPtr vars)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ClosureExpression)),
m_func(func) {
// Because PHP is insane you can have a use variable with the same
// name as a param name.
// In that case, params win (which is different than zend but much easier)
auto seenBefore = collectParamNames();
if (vars) {
m_vars = ExpressionListPtr
(new ExpressionList(vars->getScope(), vars->getLocation()));
// push the vars in reverse order, not retaining duplicates
std::set<string> seenBefore;
for (int i = vars->getCount() - 1; i >= 0; i--) {
ParameterExpressionPtr param(
dynamic_pointer_cast<ParameterExpression>((*vars)[i]));
assert(param);
if (param->getName() == "this") {
// "this" is automatically included.
// Once we get rid of all the callsites, make this an error
continue;
// Because PHP is insane you can have a use variable with the same
// name as a param name.
// In that case, params win (which is different than zend but much easier)
ExpressionListPtr bodyParams = m_func->getParams();
if (bodyParams) {
int nParams = bodyParams->getCount();
for (int i = 0; i < nParams; i++) {
ParameterExpressionPtr par(
static_pointer_cast<ParameterExpression>((*bodyParams)[i]));
seenBefore.insert(par->getName());
}
}
if (seenBefore.find(param->getName().c_str()) == seenBefore.end()) {
seenBefore.insert(param->getName().c_str());
m_vars->insertElement(param);
for (int i = vars->getCount() - 1; i >= 0; i--) {
ParameterExpressionPtr param(
dynamic_pointer_cast<ParameterExpression>((*vars)[i]));
assert(param);
if (seenBefore.find(param->getName().c_str()) == seenBefore.end()) {
seenBefore.insert(param->getName().c_str());
m_vars->insertElement(param);
}
}
if (m_vars) {
m_values = ExpressionListPtr
(new ExpressionList(m_vars->getScope(), m_vars->getLocation()));
for (int i = 0; i < m_vars->getCount(); i++) {
ParameterExpressionPtr param =
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
const string &name = param->getName();
SimpleVariablePtr var(new SimpleVariable(param->getScope(),
param->getLocation(),
name));
if (param->isRef()) {
var->setContext(RefValue);
}
m_values->addElement(var);
}
assert(m_vars->getCount() == m_values->getCount());
}
}
initializeValuesFromVars();
}
void ClosureExpression::initializeValuesFromVars() {
if (!m_vars) return;
m_values = ExpressionListPtr
(new ExpressionList(m_vars->getScope(), m_vars->getLocation()));
for (int i = 0; i < m_vars->getCount(); i++) {
ParameterExpressionPtr param =
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
const string &name = param->getName();
SimpleVariablePtr var(new SimpleVariable(param->getScope(),
param->getLocation(),
name));
if (param->isRef()) {
var->setContext(RefValue);
}
m_values->addElement(var);
}
assert(m_vars->getCount() == m_values->getCount());
}
ExpressionPtr ClosureExpression::clone() {
@@ -146,65 +132,62 @@ void ClosureExpression::setNthKid(int n, ConstructPtr cp) {
void ClosureExpression::analyzeProgram(AnalysisResultPtr ar) {
m_func->analyzeProgram(ar);
if (m_vars) {
m_values->analyzeProgram(ar);
if (m_vars) analyzeVars(ar);
if (ar->getPhase() == AnalysisResult::AnalyzeAll) {
getFunctionScope()->addUse(m_func->getFunctionScope(),
BlockScope::UseKindClosure);
m_func->getFunctionScope()->setClosureVars(m_vars);
FunctionScopeRawPtr container =
// closure function's variable table (not containing function's)
VariableTablePtr variables = m_func->getFunctionScope()->getVariables();
VariableTablePtr containing = getFunctionScope()->getVariables();
for (int i = 0; i < m_vars->getCount(); i++) {
ParameterExpressionPtr param =
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
const string &name = param->getName();
{
Symbol *containingSym = containing->addDeclaredSymbol(name, param);
containingSym->setPassClosureVar();
Symbol *sym = variables->addDeclaredSymbol(name, param);
sym->setClosureVar();
sym->setDeclaration(ConstructPtr());
if (param->isRef()) {
sym->setRefClosureVar();
sym->setUsed();
} else {
sym->clearRefClosureVar();
sym->clearUsed();
}
}
}
return;
}
if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
// closure function's variable table (not containing function's)
VariableTablePtr variables = m_func->getFunctionScope()->getVariables();
for (int i = 0; i < m_vars->getCount(); i++) {
ParameterExpressionPtr param =
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
const string &name = param->getName();
// so we can assign values to them, instead of seeing CVarRef
Symbol *sym = variables->getSymbol(name);
if (sym && sym->isParameter()) {
sym->setLvalParam();
}
}
}
}
FunctionScopeRawPtr container =
getFunctionScope()->getContainingNonClosureFunction();
if (container && container->isStatic()) {
m_func->getModifiers()->add(T_STATIC);
}
}
void ClosureExpression::analyzeVars(AnalysisResultPtr ar) {
m_values->analyzeProgram(ar);
if (ar->getPhase() == AnalysisResult::AnalyzeAll) {
getFunctionScope()->addUse(m_func->getFunctionScope(),
BlockScope::UseKindClosure);
m_func->getFunctionScope()->setClosureVars(m_vars);
// closure function's variable table (not containing function's)
VariableTablePtr variables = m_func->getFunctionScope()->getVariables();
VariableTablePtr containing = getFunctionScope()->getVariables();
for (int i = 0; i < m_vars->getCount(); i++) {
ParameterExpressionPtr param =
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
const string &name = param->getName();
{
Symbol *containingSym = containing->addDeclaredSymbol(name, param);
containingSym->setPassClosureVar();
Symbol *sym = variables->addDeclaredSymbol(name, param);
sym->setClosureVar();
sym->setDeclaration(ConstructPtr());
if (param->isRef()) {
sym->setRefClosureVar();
sym->setUsed();
} else {
sym->clearRefClosureVar();
sym->clearUsed();
}
}
}
return;
}
if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
// closure function's variable table (not containing function's)
VariableTablePtr variables = m_func->getFunctionScope()->getVariables();
for (int i = 0; i < m_vars->getCount(); i++) {
ParameterExpressionPtr param =
dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
const string &name = param->getName();
// so we can assign values to them, instead of seeing CVarRef
Symbol *sym = variables->getSymbol(name);
if (sym && sym->isParameter()) {
sym->setLvalParam();
}
}
}
}
TypePtr ClosureExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
@@ -268,72 +251,6 @@ TypePtr ClosureExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return s_ClosureType;
}
void ClosureExpression::setCaptureList(
AnalysisResultPtr ar,
const std::set<std::string>& captureNames) {
assert(m_captureState == CaptureState::Unknown);
m_captureState = CaptureState::Known;
bool usedThis = false;
SCOPE_EXIT {
/*
* TODO: closures in a non-class scope should be neither static
* nor non-static, but right now we don't really have this idea.
*
* This would allow not having to check for a $this or late bound
* class in the closure object or on the ActRec when returning
* from those closures.
*
* (We could also mark closures that don't use late static binding
* with this flag to avoid checks on closures in member functions
* when they use neither $this nor static::)
*/
if (!usedThis) m_func->getModifiers()->add(T_STATIC);
};
if (captureNames.empty()) return;
m_vars = ExpressionListPtr(
new ExpressionList(getOriginalScope(), getLocation()));
for (auto const& name : captureNames) {
if (name == "this") {
usedThis = true;
continue;
}
auto expr = ParameterExpressionPtr(new ParameterExpression(
BlockScopePtr(getOriginalScope()),
getLocation(),
TypeAnnotationPtr(),
true /* hhType */,
name,
false /* ref */,
0 /* token modifier thing */,
ExpressionPtr(),
ExpressionPtr()
));
m_vars->insertElement(expr);
}
initializeValuesFromVars();
analyzeVars(ar);
}
std::set<std::string> ClosureExpression::collectParamNames() const {
std::set<std::string> ret;
auto bodyParams = m_func->getParams();
if (!bodyParams) return ret;
int nParams = bodyParams->getCount();
for (int i = 0; i < nParams; i++) {
auto par = static_pointer_cast<ParameterExpression>((*bodyParams)[i]);
ret.insert(par->getName());
}
return ret;
}
bool ClosureExpression::hasStaticLocals() {
ConstructPtr cons(m_func);
return hasStaticLocalsImpl(cons);
@@ -362,22 +279,6 @@ bool ClosureExpression::hasStaticLocalsImpl(ConstructPtr root) {
return false;
}
///////////////////////////////////////////////////////////////////////////////
void ClosureExpression::outputCodeModel(CodeGenerator &cg) {
auto numProps = m_vars != nullptr && m_vars->getCount() > 0 ? 3 : 2;
cg.printObjectHeader("ClosureExpression", numProps);
cg.printPropertyHeader("ffunction");
m_func->outputCodeModel(cg);
if (m_vars != nullptr && m_vars->getCount() > 0) {
cg.printPropertyHeader("capturedVariables");
cg.printExpressionVector(m_vars);
}
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -390,5 +291,3 @@ void ClosureExpression::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
}
m_func->outputPHPBody(cg, ar);
}
}
+5 -34
Ver Arquivo
@@ -18,7 +18,6 @@
#define incl_HPHP_CLOSURE_EXPRESSION_H_
#include "hphp/compiler/expression/expression.h"
#include "hphp/parser/parser.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -30,20 +29,10 @@ DECLARE_BOOST_TYPES(ExpressionList);
class ClosureExpression : public Expression {
public:
ClosureExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ClosureType type,
FunctionStatementPtr func,
ExpressionListPtr vars);
FunctionStatementPtr func, ExpressionListPtr vars);
DECLARE_BASE_EXPRESSION_VIRTUAL_FUNCTIONS;
// Flag for whether we have already determined the capture list for
// this lambda.
enum class CaptureState {
Unknown,
Known,
};
CaptureState captureState() const { return m_captureState; }
virtual ConstructPtr getNthKid(int n) const;
virtual void setNthKid(int n, ConstructPtr cp);
virtual int getKidCount() const;
@@ -54,35 +43,17 @@ public:
StringData* getClosureClassName() { return m_closureClassName; }
void setClosureClassName(StringData* value) { m_closureClassName = value; }
bool hasStaticLocals();
ClosureType type() const { return m_type; }
std::set<std::string> collectParamNames() const;
/*
* Initialize the capture list for a closure that uses automatic
* captures.
*
* Pre: captureState() == CaptureState::Unknown.
*/
void setCaptureList(AnalysisResultPtr ar,
const std::set<std::string>&);
private:
static TypePtr s_ClosureType;
private:
void initializeFromUseList(ExpressionListPtr vars);
void initializeValuesFromVars();
void analyzeVars(AnalysisResultPtr);
bool hasStaticLocalsImpl(ConstructPtr root);
private:
ClosureType m_type;
FunctionStatementPtr m_func;
ExpressionListPtr m_vars;
ExpressionListPtr m_values;
StringData* m_closureClassName;
std::set<std::string> m_unboundNames;
CaptureState m_captureState;
static TypePtr s_ClosureType;
bool hasStaticLocalsImpl(ConstructPtr root);
};
///////////////////////////////////////////////////////////////////////////////
@@ -273,17 +273,6 @@ TypePtr ConstantExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return actualType;
}
///////////////////////////////////////////////////////////////////////////////
void ConstantExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("SimpleVariableExpression", 2);
cg.printPropertyHeader("variableName");
cg.printValue(m_origName);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -113,26 +113,6 @@ TypePtr DynamicFunctionCall::inferTypes(AnalysisResultPtr ar, TypePtr type,
return Type::Variant;
}
///////////////////////////////////////////////////////////////////////////////
void DynamicFunctionCall::outputCodeModel(CodeGenerator &cg) {
if (m_class || !m_className.empty()) {
cg.printObjectHeader("ClassMethodCallExpression", 4);
cg.printPropertyHeader("className");
StaticClassName::outputCodeModel(cg);
cg.printPropertyHeader("methodExpression");
} else {
cg.printObjectHeader("SimpleFunctionCallExpression", 3);
cg.printPropertyHeader("functionExpression");
}
m_nameExp->outputCodeModel(cg);
cg.printPropertyHeader("arguments");
cg.printExpressionVector(m_params);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(m_nameExp->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
void DynamicFunctionCall::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
@@ -19,7 +19,6 @@
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/analysis/variable_table.h"
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/code_model_enums.h"
using namespace HPHP;
@@ -88,19 +87,6 @@ TypePtr DynamicVariable::inferTypes(AnalysisResultPtr ar, TypePtr type,
return m_implementedType = Type::Variant;
}
///////////////////////////////////////////////////////////////////////////////
void DynamicVariable::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("UnaryOpExpression", 3);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("operation");
cg.printValue(PHP_DYNAMIC_VARIABLE_OP) ;
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -119,19 +119,6 @@ bool EncapsListExpression::canonCompare(ExpressionPtr e) const {
return m_type == el->m_type;
}
///////////////////////////////////////////////////////////////////////////////
void EncapsListExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("EncapsListExpression", 3);
cg.printPropertyHeader("delimiter");
cg.printValue(m_type);
cg.printPropertyHeader("expressions");
cg.printExpressionVector(m_exps);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+1
Ver Arquivo
@@ -71,6 +71,7 @@ ExpressionPtr Expression::replaceValue(ExpressionPtr rep) {
rep->clearContext(AssignmentRHS);
rep = el;
}
if (isChildOfYield()) rep->setChildOfYield();
if (rep->is(KindOfSimpleVariable) && !is(KindOfSimpleVariable)) {
static_pointer_cast<SimpleVariable>(rep)->setAlwaysStash();
}
+2 -20
Ver Arquivo
@@ -17,12 +17,9 @@
#ifndef incl_HPHP_EXPRESSION_H_
#define incl_HPHP_EXPRESSION_H_
#include "hphp/util/deprecated/declare-boost-types.h"
#include "hphp/util/hash-map-typedefs.h"
#include "hphp/compiler/construct.h"
#include "hphp/compiler/analysis/type.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/util/hash-map-typedefs.h"
#define EXPRESSION_CONSTRUCTOR_BASE_PARAMETERS \
BlockScopePtr scope, LocationPtr loc, Expression::KindOf kindOf
@@ -39,7 +36,6 @@
virtual ExpressionPtr clone(); \
virtual TypePtr inferTypes(AnalysisResultPtr ar, TypePtr type, \
bool coerce); \
virtual void outputCodeModel(CodeGenerator &cg); \
virtual void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
#define DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS \
DECLARE_BASE_EXPRESSION_VIRTUAL_FUNCTIONS; \
@@ -51,7 +47,7 @@ namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(Statement);
DECLARE_EXTENDED_BOOST_TYPES(Expression);
DECLARE_BOOST_TYPES(Expression);
class Variant;
#define DECLARE_EXPRESSION_TYPES(x) \
@@ -81,17 +77,7 @@ class Variant;
x(ClosureExpression, None), \
x(YieldExpression, None), \
x(AwaitExpression, None), \
x(UserAttribute, None), \
x(QueryExpression, None), \
x(FromClause, None), \
x(LetClause, None), \
x(WhereClause, None), \
x(SelectClause, None), \
x(IntoClause, None), \
x(JoinClause, None), \
x(GroupClause, None), \
x(OrderbyClause, None), \
x(Ordering, None)
x(UserAttribute, None)
class Expression : public Construct {
public:
@@ -363,10 +349,6 @@ public:
return isNoRemove() && m_assertedType;
}
virtual bool allowCellByRef() const {
return false;
}
static ExpressionPtr MakeConstant(AnalysisResultConstPtr ar,
BlockScopePtr scope,
LocationPtr loc,
+19 -19
Ver Arquivo
@@ -33,6 +33,7 @@ using namespace HPHP;
ExpressionList::ExpressionList(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ListKind kind)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ExpressionList)),
m_outputCount(-1),
m_arrayElements(false), m_collectionType(0), m_kind(kind) {
}
@@ -239,17 +240,28 @@ void ExpressionList::stripConcat() {
BinaryOpExpressionPtr b
(static_pointer_cast<BinaryOpExpression>(e));
if (b->getOp() == '.') {
if(!b->getExp1()->isArray() && !b->getExp2()->isArray()) {
e = b->getExp1();
el.insertElement(b->getExp2(), i + 1);
continue;
}
e = b->getExp1();
el.insertElement(b->getExp2(), i + 1);
continue;
}
}
i++;
}
}
void ExpressionList::setOutputCount(int count) {
assert(count >= 0 && count <= (int)m_exps.size());
m_outputCount = count;
}
int ExpressionList::getOutputCount() const {
return m_outputCount < 0 ? m_exps.size() : m_outputCount;
}
void ExpressionList::resetOutputCount() {
m_outputCount = -1;
}
void ExpressionList::markParam(int p, bool noRefWrapper) {
ExpressionPtr param = (*this)[p];
if (param->hasContext(Expression::InvokeArgument)) {
@@ -274,7 +286,7 @@ void ExpressionList::markParams(bool noRefWrapper) {
}
}
void ExpressionList::setCollectionType(Collection::Type cType) {
void ExpressionList::setCollectionType(int cType) {
m_arrayElements = true;
m_collectionType = cType;
}
@@ -466,19 +478,6 @@ bool ExpressionList::canonCompare(ExpressionPtr e) const {
m_kind == l->m_kind;
}
///////////////////////////////////////////////////////////////////////////////
void ExpressionList::outputCodeModel(CodeGenerator &cg) {
for (unsigned int i = 0; i < m_exps.size(); i++) {
ExpressionPtr exp = m_exps[i];
if (exp) {
cg.printExpression(exp, exp->hasContext(RefParameter));
} else {
cg.printNull();
}
}
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -514,3 +513,4 @@ unsigned int ExpressionList::checkLitstrKeys() const {
}
return keys.size();
}
+10 -1
Ver Arquivo
@@ -73,7 +73,15 @@ public:
void markParam(int p, bool noRefWrapper);
void markParams(bool noRefWrapper);
void setCollectionType(Collection::Type cType);
void setCollectionType(int cType);
/**
* When a function call has too many arguments, we only want to output
* max number of arguments, by limiting output count of subexpressions.
*/
void setOutputCount(int count);
int getOutputCount() const;
void resetOutputCount();
virtual bool canonCompare(ExpressionPtr e) const;
@@ -89,6 +97,7 @@ private:
unsigned int checkLitstrKeys() const;
ExpressionPtrVec m_exps;
int m_outputCount;
bool m_arrayElements;
int m_collectionType;
ListKind m_kind;
-111
Ver Arquivo
@@ -1,111 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/expression/group_clause.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/runtime/base/complex-types.h"
using namespace HPHP;
///////////////////////////////////////////////////////////////////////////////
// constructors/destructors
GroupClause::GroupClause
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr coll, ExpressionPtr key)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(GroupClause)),
m_coll(coll), m_key(key) {
}
ExpressionPtr GroupClause::clone() {
GroupClausePtr exp(new GroupClause(*this));
Expression::deepCopy(exp);
exp->m_coll = Clone(m_coll);
exp->m_key = Clone(m_key);
return exp;
}
///////////////////////////////////////////////////////////////////////////////
// parser functions
///////////////////////////////////////////////////////////////////////////////
// static analysis functions
void GroupClause::analyzeProgram(AnalysisResultPtr ar) {
m_coll->analyzeProgram(ar);
m_key->analyzeProgram(ar);
}
ConstructPtr GroupClause::getNthKid(int n) const {
switch (n) {
case 0:
return m_coll;
case 1:
return m_key;
default:
assert(false);
break;
}
return ConstructPtr();
}
int GroupClause::getKidCount() const {
return 2;
}
void GroupClause::setNthKid(int n, ConstructPtr cp) {
switch (n) {
case 0:
m_coll = dynamic_pointer_cast<Expression>(cp);
break;
case 1:
m_key = dynamic_pointer_cast<Expression>(cp);
break;
default:
break;
}
}
TypePtr GroupClause::inferTypes(AnalysisResultPtr ar, TypePtr type,
bool coerce) {
m_coll->inferAndCheck(ar, Type::Some, false);
m_key->inferAndCheck(ar, Type::Some, false);
return Type::Object;
}
///////////////////////////////////////////////////////////////////////////////
void GroupClause::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("GroupClause", 3);
cg.printPropertyHeader("collection");
m_coll->outputCodeModel(cg);
cg.printPropertyHeader("key");
m_key->outputCodeModel(cg);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
void GroupClause::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
cg_printf("group ");
m_coll->outputPHP(cg, ar);
cg_printf(" by ");
m_key->outputPHP(cg, ar);
}
-45
Ver Arquivo
@@ -1,45 +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_GROUP_CLAUSE_H_
#define incl_HPHP_GROUP_CLAUSE_H_
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/expression_list.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(GroupClause);
class GroupClause : public Expression {
public:
GroupClause(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr coll, ExpressionPtr key);
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
ExpressionPtr getColl() { return m_coll; }
ExpressionPtr getKey() { return m_key; }
private:
ExpressionPtr m_coll;
ExpressionPtr m_key;
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_GROUP_CLAUSE_H_
@@ -283,12 +283,6 @@ TypePtr IncludeExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return UnaryOpExpression::inferTypes(ar, type, coerce);
}
///////////////////////////////////////////////////////////////////////////////
void IncludeExpression::outputCodeModel(CodeGenerator &cg) {
UnaryOpExpression::outputCodeModel(cg);
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-138
Ver Arquivo
@@ -1,138 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/expression/join_clause.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/runtime/base/complex-types.h"
using namespace HPHP;
///////////////////////////////////////////////////////////////////////////////
// constructors/destructors
JoinClause::JoinClause
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
const std::string &var, ExpressionPtr coll, ExpressionPtr left,
ExpressionPtr right, const std::string &group)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(JoinClause)),
m_var(var), m_coll(coll), m_left(left),
m_right(right), m_group(group) {
}
ExpressionPtr JoinClause::clone() {
JoinClausePtr exp(new JoinClause(*this));
Expression::deepCopy(exp);
exp->m_var = m_var;
exp->m_coll = Clone(m_coll);
exp->m_left = Clone(m_left);
exp->m_right = Clone(m_right);
exp->m_group = m_group;
return exp;
}
///////////////////////////////////////////////////////////////////////////////
// parser functions
///////////////////////////////////////////////////////////////////////////////
// static analysis functions
void JoinClause::analyzeProgram(AnalysisResultPtr ar) {
m_coll->analyzeProgram(ar);
m_left->analyzeProgram(ar);
m_right->analyzeProgram(ar);
}
ConstructPtr JoinClause::getNthKid(int n) const {
switch (n) {
case 0:
return m_coll;
case 1:
return m_left;
case 2:
return m_right;
default:
assert(false);
break;
}
return ConstructPtr();
}
int JoinClause::getKidCount() const {
return 3;
}
void JoinClause::setNthKid(int n, ConstructPtr cp) {
switch (n) {
case 0:
m_coll = dynamic_pointer_cast<Expression>(cp);
break;
case 1:
m_left = dynamic_pointer_cast<Expression>(cp);
break;
case 2:
m_right = dynamic_pointer_cast<Expression>(cp);
break;
default:
break;
}
}
TypePtr JoinClause::inferTypes(AnalysisResultPtr ar, TypePtr type,
bool coerce) {
m_coll->inferAndCheck(ar, Type::Some, false);
m_left->inferAndCheck(ar, Type::Some, false);
m_right->inferAndCheck(ar, Type::Some, false);
return Type::Object;
}
///////////////////////////////////////////////////////////////////////////////
void JoinClause::outputCodeModel(CodeGenerator &cg) {
auto numProps = 5;
if (!m_group.empty()) numProps++;
cg.printObjectHeader("JoinClause", numProps);
cg.printPropertyHeader("variable");
cg.printValue(m_var);
cg.printPropertyHeader("collection");
m_coll->outputCodeModel(cg);
cg.printPropertyHeader("left");
m_left->outputCodeModel(cg);
cg.printPropertyHeader("right");
m_right->outputCodeModel(cg);
if (!m_group.empty()) {
cg.printPropertyHeader("group");
cg.printValue(m_group);
}
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
void JoinClause::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
cg_printf("join %s in ", m_var.c_str());
m_coll->outputPHP(cg, ar);
cg_printf(" on ");
m_left->outputPHP(cg, ar);
cg_printf(" equals ");
m_right->outputPHP(cg, ar);
if (!m_group.empty()) {
cg_printf(" into %s", m_group.c_str());
}
}
-52
Ver Arquivo
@@ -1,52 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_JOIN_CLAUSE_H_
#define incl_HPHP_JOIN_CLAUSE_H_
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/expression_list.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(JoinClause);
class JoinClause : public Expression {
public:
JoinClause(EXPRESSION_CONSTRUCTOR_PARAMETERS,
const std::string &var, ExpressionPtr coll, ExpressionPtr left,
ExpressionPtr right, const std::string &group);
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
std::string getVar() const { return m_var; }
ExpressionPtr getColl() { return m_coll; }
ExpressionPtr getLeft() { return m_left; }
ExpressionPtr getRight() { return m_right; }
std::string getGroup() { return m_group; }
private:
std::string m_var;
ExpressionPtr m_coll;
ExpressionPtr m_left;
ExpressionPtr m_right;
std::string m_group;
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_JOIN_CLAUSE_H_
+1 -27
Ver Arquivo
@@ -31,7 +31,7 @@ using namespace HPHP;
// constructors/destructors
/*
Determine whether the rhs behaves normally, or abnormally.
Determine whether the rhs behaves normall, or abnormally.
1) If the expression is the silence operator, recurse on the inner expression.
2) If the expression is a list assignment expression, recurse on the
@@ -77,7 +77,6 @@ static ListAssignment::RHSKind GetRHSKind(ExpressionPtr rhs) {
case Expression::KindOfIncludeExpression:
case Expression::KindOfYieldExpression:
case Expression::KindOfAwaitExpression:
case Expression::KindOfQueryExpression:
return ListAssignment::Regular;
case Expression::KindOfListAssignment:
@@ -119,15 +118,6 @@ static ListAssignment::RHSKind GetRHSKind(ExpressionPtr rhs) {
case Expression::KindOfParameterExpression:
case Expression::KindOfModifierExpression:
case Expression::KindOfUserAttribute:
case Expression::KindOfFromClause:
case Expression::KindOfLetClause:
case Expression::KindOfWhereClause:
case Expression::KindOfSelectClause:
case Expression::KindOfIntoClause:
case Expression::KindOfJoinClause:
case Expression::KindOfGroupClause:
case Expression::KindOfOrderbyClause:
case Expression::KindOfOrdering:
always_assert(false);
// non-arrays
@@ -283,22 +273,6 @@ TypePtr ListAssignment::inferTypes(AnalysisResultPtr ar, TypePtr type,
return m_array->inferAndCheck(ar, Type::Variant, false);
}
///////////////////////////////////////////////////////////////////////////////
void ListAssignment::outputCodeModel(CodeGenerator &cg) {
auto numProps = m_array != nullptr ? 3 : 2;
cg.printObjectHeader("ListAssignmentExpression", numProps);
cg.printPropertyHeader("variables");
cg.printExpressionVector(m_variables);
if (m_array != nullptr) {
cg.printPropertyHeader("expression");
m_array->outputCodeModel(cg);
}
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -118,20 +118,6 @@ bool ModifierExpression::validForClosure() const {
return true;
}
/**
* In the context of a trait alias rule, only method access and visibility
* modifiers are allowed
*/
bool ModifierExpression::validForTraitAliasRule() const {
for (auto const& mod: m_modifiers) {
if (mod != T_PUBLIC && mod != T_PRIVATE && mod != T_PROTECTED
&& mod != T_FINAL) {
return false;
}
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
// static analysis functions
@@ -145,29 +131,6 @@ TypePtr ModifierExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return TypePtr();
}
///////////////////////////////////////////////////////////////////////////////
void ModifierExpression::outputCodeModel(CodeGenerator &cg) {
cg.printf("V:9:\"HH\\Vector\":%d:{", (int)m_modifiers.size());
for (unsigned int i = 0; i < m_modifiers.size(); i++) {
cg.printObjectHeader("Modifier", 1);
cg.printPropertyHeader("name");
switch (m_modifiers[i]) {
case T_PUBLIC: cg.printValue("public"); break;
case T_PROTECTED: cg.printValue("protected"); break;
case T_PRIVATE: cg.printValue("private"); break;
case T_STATIC: cg.printValue("static"); break;
case T_ABSTRACT: cg.printValue("abstract"); break;
case T_FINAL: cg.printValue("final"); break;
case T_ASYNC: cg.printValue("async"); break;
default:
assert(false);
}
cg.printObjectFooter();
}
cg.printf("}");
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -56,7 +56,6 @@ public:
bool validForFunction() const;
bool validForClosure() const;
bool validForTraitAliasRule() const;
void setHasPrivacy(bool f) { m_hasPrivacy = f; }
@@ -122,6 +122,7 @@ TypePtr NewObjectExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
if (getScope()->isFirstPass()) {
Compiler::Error(Compiler::BadConstructorCall, self);
}
m_params->setOutputCount(0);
}
m_params->inferAndCheck(ar, Type::Some, false);
}
@@ -152,25 +153,6 @@ TypePtr NewObjectExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return Type::Object;
}
///////////////////////////////////////////////////////////////////////////////
void NewObjectExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("NewObjectExpression", m_params == nullptr ? 2 : 3);
if (m_nameExp->is(Expression::KindOfScalarExpression)) {
cg.printPropertyHeader("className");
} else {
cg.printPropertyHeader("classExpression");
}
m_nameExp->outputCodeModel(cg);
if (m_params != nullptr) {
cg.printPropertyHeader("arguments");
cg.printExpressionVector(m_params);
}
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -146,6 +146,7 @@ void ObjectMethodExpression::setInvokeParams(AnalysisResultPtr ar) {
for (int i = 0; i < m_params->getCount(); i++) {
(*m_params)[i]->inferAndCheck(ar, Type::Variant, false);
}
m_params->resetOutputCount();
}
ExpressionPtr ObjectMethodExpression::preOptimize(AnalysisResultConstPtr ar) {
@@ -277,28 +278,6 @@ TypePtr ObjectMethodExpression::inferAndCheck(AnalysisResultPtr ar,
return checkParamsAndReturn(ar, type, coerce, func, false);
}
///////////////////////////////////////////////////////////////////////////////
void ObjectMethodExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ObjectMethodCallExpression",
m_params == nullptr ? 3 : 4);
cg.printPropertyHeader("object");
m_object->outputCodeModel(cg);
if (m_nameExp->is(Expression::KindOfScalarExpression)) {
cg.printPropertyHeader("methodName");
} else {
cg.printPropertyHeader("methodExpression");
}
m_nameExp->outputCodeModel(cg);
if (m_params != nullptr) {
cg.printPropertyHeader("arguments");
cg.printExpressionVector(m_params);
}
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -332,23 +332,6 @@ ObjectPropertyExpression::postOptimize(AnalysisResultConstPtr ar) {
ExpressionPtr();
}
///////////////////////////////////////////////////////////////////////////////
void ObjectPropertyExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ObjectPropertyExpression", 3);
cg.printPropertyHeader("object");
m_object->outputCodeModel(cg);
if (m_property->is(Expression::KindOfScalarExpression)) {
cg.printPropertyHeader("propertyName");
} else {
cg.printPropertyHeader("propertyExpression");
}
m_property->outputCodeModel(cg);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-126
Ver Arquivo
@@ -1,126 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/expression/ordering.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/runtime/base/complex-types.h"
using namespace HPHP;
///////////////////////////////////////////////////////////////////////////////
// constructors/destructors
Ordering::Ordering
(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr key, TokenID direction)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(Ordering)),
m_key(key), m_direction(direction){
}
ExpressionPtr Ordering::clone() {
OrderingPtr exp(new Ordering(*this));
Expression::deepCopy(exp);
exp->m_key = Clone(m_key);
exp->m_direction = m_direction;
return exp;
}
///////////////////////////////////////////////////////////////////////////////
// parser functions
///////////////////////////////////////////////////////////////////////////////
// static analysis functions
void Ordering::analyzeProgram(AnalysisResultPtr ar) {
m_key->analyzeProgram(ar);
}
ConstructPtr Ordering::getNthKid(int n) const {
switch (n) {
case 0:
return m_key;
default:
assert(false);
break;
}
return ConstructPtr();
}
int Ordering::getKidCount() const {
return 1;
}
void Ordering::setNthKid(int n, ConstructPtr cp) {
switch (n) {
case 0:
m_key = dynamic_pointer_cast<Expression>(cp);
break;
default:
break;
}
}
TypePtr Ordering::inferTypes(AnalysisResultPtr ar, TypePtr type,
bool coerce) {
m_key->inferAndCheck(ar, Type::Some, false);
return Type::Object;
}
///////////////////////////////////////////////////////////////////////////////
void Ordering::outputCodeModel(CodeGenerator &cg) {
int direction;
switch (m_direction) {
case T_ASCENDING:
direction = 1;
break;
case T_DESCENDING:
direction = 2;
break;
default:
direction = 3;
break;
}
auto propCount = direction > 0 ? 3 : 2;
cg.printObjectHeader("Ordering", propCount);
cg.printPropertyHeader("key");
m_key->outputCodeModel(cg);
if (propCount == 3) {
cg.printPropertyHeader("direction");
cg.printValue(direction);
}
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
void Ordering::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
m_key->outputPHP(cg, ar);
switch (m_direction) {
case T_ASCENDING:
cg_printf(" ascending");
break;
case T_DESCENDING:
cg_printf(" decending");
break;
default:
break;
}
}
-47
Ver Arquivo
@@ -1,47 +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_ORDERING_H_
#define incl_HPHP_ORDERING_H_
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/parser/scanner.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(Ordering);
class Ordering : public Expression {
public:
Ordering(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr key, TokenID direction);
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
ExpressionPtr getKey() const { return m_key; }
TokenID getDirection() { return m_direction; }
private:
ExpressionPtr m_key;
TokenID m_direction;
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_ORDERING_H_
@@ -300,45 +300,6 @@ void ParameterExpression::compatibleDefault() {
}
}
///////////////////////////////////////////////////////////////////////////////
void ParameterExpression::outputCodeModel(CodeGenerator &cg) {
auto propCount = 2;
if (m_attributeList) propCount++;
if (m_modifier != 0) propCount++;
if (m_ref) propCount++;
if (m_defaultValue != nullptr) propCount++;
cg.printObjectHeader("ParameterDeclaration", propCount);
if (m_attributeList) {
cg.printPropertyHeader("isPassedByReference");
cg.printExpressionVector(m_attributeList);
}
if (m_modifier != 0) {
cg.printPropertyHeader("modifiers");
printf("V:9:\"HH\\Vector\":1:{");
switch (m_modifier) {
case T_PUBLIC: cg.printValue("public"); break;
case T_PROTECTED: cg.printValue("protected"); break;
case T_PRIVATE: cg.printValue("private"); break;
default: assert(false);
}
printf("}");
}
if (m_ref) {
cg.printPropertyHeader("isPassedByReference");
cg.printValue(true);
}
cg.printPropertyHeader("name");
cg.printValue(m_name);
if (m_defaultValue) {
cg.printPropertyHeader("expression");
m_defaultValue->outputCodeModel(cg);
}
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+1 -1
Ver Arquivo
@@ -19,7 +19,7 @@
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/constant_expression.h"
#include "hphp/compiler/json.h"
#include "hphp/util/json.h"
#include "hphp/parser/scanner.h"
namespace HPHP {
-22
Ver Arquivo
@@ -163,28 +163,6 @@ ExpressionPtr QOpExpression::unneededHelper() {
return static_pointer_cast<Expression>(shared_from_this());
}
///////////////////////////////////////////////////////////////////////////////
void QOpExpression::outputCodeModel(CodeGenerator &cg) {
if (m_expYes == nullptr) {
cg.printObjectHeader("ValueIfNullExpression", 3);
cg.printPropertyHeader("expression");
m_condition->outputCodeModel(cg);
cg.printPropertyHeader("valueIfNull");
} else {
cg.printObjectHeader("ConditionalExpression", 4);
cg.printPropertyHeader("condition");
m_condition->outputCodeModel(cg);
cg.printPropertyHeader("valueIfTrue");
m_expYes->outputCodeModel(cg);
cg.printPropertyHeader("valueIfFalse");
}
m_expNo->outputCodeModel(cg);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-165
Ver Arquivo
@@ -1,165 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/expression/query_expression.h"
#include "hphp/compiler/expression/simple_query_clause.h"
#include "hphp/compiler/analysis/capture_extractor.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/runtime/base/complex-types.h"
using namespace HPHP;
///////////////////////////////////////////////////////////////////////////////
// constructors/destructors
QueryOrderby::QueryOrderby(EXPRESSION_CONSTRUCTOR_BASE_PARAMETERS)
: Expression(EXPRESSION_CONSTRUCTOR_BASE_PARAMETER_VALUES) {
m_expressions = nullptr;
}
ExpressionPtr QueryOrderby::clone() {
assert(false);
return nullptr;
}
QueryExpression::QueryExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr head, ExpressionPtr body)
: QueryOrderby(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(QueryExpression)) {
m_queryargs = ExpressionListPtr(
new ExpressionList(getScope(), getLocation())
);
m_expressions = ExpressionListPtr(
new ExpressionList(getScope(), getLocation())
);
m_expressions->addElement(head);
assert(body != nullptr && body->is(Expression::KindOfExpressionList));
ExpressionListPtr el(static_pointer_cast<ExpressionList>(body));
for (unsigned int i = 0; i < el->getCount(); i++) {
if ((*el)[i]) m_expressions->addElement((*el)[i]);
}
}
QueryExpression::QueryExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionListPtr clauses)
: QueryOrderby(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(QueryExpression)) {
m_queryargs = ExpressionListPtr(
new ExpressionList(getScope(), getLocation())
);
m_expressions = clauses;
}
///////////////////////////////////////////////////////////////////////////////
// parser functions
///////////////////////////////////////////////////////////////////////////////
// static analysis functions
ExpressionListPtr QueryExpression::getQueryArguments() {
if (m_queryargs->getCount() == 0) serializeQueryExpression();
return m_queryargs;
}
StringData* QueryExpression::getQueryString() {
if (m_querystr == nullptr) serializeQueryExpression();
return m_querystr;
}
void QueryExpression::serializeQueryExpression() {
CaptureExtractor ce;
auto qe = ce.rewrite(static_pointer_cast<Expression>(shared_from_this()));
m_queryargs->clearElements();
for (auto e : ce.getCapturedExpressions()) {
m_queryargs->addElement(e);
}
assert(m_queryargs->getCount() > 0); //syntax requires an initial from clause
std::ostringstream serialized;
CodeGenerator cg(&serialized, CodeGenerator::Output::CodeModel);
cg.setAstClassPrefix("Code"); //TODO: create option for this
qe->outputCodeModel(cg);
std::string s(serialized.str().c_str(), serialized.str().length());
m_querystr = makeStaticString(s);
}
void QueryOrderby::analyzeProgram(AnalysisResultPtr ar) {
for (unsigned int i = 0; i < m_expressions->getCount(); i++) {
(*m_expressions)[i]->analyzeProgram(ar);
}
}
ConstructPtr QueryOrderby::getNthKid(int n) const {
if (n < (int)m_expressions->getCount()) {
return (*m_expressions)[n];
}
return ConstructPtr();
}
int QueryOrderby::getKidCount() const {
return m_expressions->getCount();
}
void QueryOrderby::setNthKid(int n, ConstructPtr cp) {
int m = m_expressions->getCount();
if (n >= m) {
assert(false);
} else {
(*m_expressions)[n] = dynamic_pointer_cast<Expression>(cp);
}
}
TypePtr QueryOrderby::inferTypes(AnalysisResultPtr ar, TypePtr type,
bool coerce) {
for (unsigned int i = 0; i < m_expressions->getCount(); i++) {
if (ExpressionPtr e = (*m_expressions)[i]) {
e->inferAndCheck(ar, Type::Some, false);
}
}
return Type::Object;
}
///////////////////////////////////////////////////////////////////////////////
void QueryOrderby::outputCodeModel(CodeGenerator &cg) {
if (this->getKindOf() == Expression::KindOfOrderbyClause) {
cg.printObjectHeader("OrderbyClause", 2);
} else {
cg.printObjectHeader("QueryExpression", 2);
}
cg.printPropertyHeader("clauses");
m_expressions->outputCodeModel(cg);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
void QueryOrderby::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
if (this->getKindOf() == Expression::KindOfOrderbyClause) {
cg_printf("orderby ");
}
for (unsigned int i = 0; i < m_expressions->getCount(); i++) {
if (ExpressionPtr e = (*m_expressions)[i]) {
e->outputPHP(cg, ar);
if (i > 0) cg_printf(" ");
}
}
}
-89
Ver Arquivo
@@ -1,89 +0,0 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_QUERY_EXPRESSION_H_
#define incl_HPHP_QUERY_EXPRESSION_H_
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/runtime/base/static-string-table.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(QueryOrderby);
class QueryOrderby : public Expression {
public:
DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS;
protected:
explicit QueryOrderby(EXPRESSION_CONSTRUCTOR_BASE_PARAMETERS);
ExpressionListPtr m_expressions;
};
DECLARE_BOOST_TYPES(QueryExpression);
class QueryExpression : public QueryOrderby {
public:
QueryExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionPtr head, ExpressionPtr body);
QueryExpression(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ExpressionListPtr clauses);
virtual ExpressionPtr clone() {
QueryExpressionPtr exp(new QueryExpression(*this));
Expression::deepCopy(exp);
exp->m_expressions = Clone(m_expressions);
exp->m_queryargs = Clone(m_queryargs);
exp->m_querystr = m_querystr;
return exp;
}
ExpressionListPtr getClauses() const { return m_expressions; }
ExpressionListPtr getQueryArguments();
StringData* getQueryString();
private:
void serializeQueryExpression();
ExpressionListPtr m_queryargs;
StringData* m_querystr;
};
DECLARE_BOOST_TYPES(OrderbyClause);
class OrderbyClause : public QueryOrderby {
public:
OrderbyClause(EXPRESSION_CONSTRUCTOR_PARAMETERS, ExpressionPtr orderings)
: QueryOrderby(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(OrderbyClause)) {
assert(orderings && orderings->is(Expression::KindOfExpressionList));
m_expressions = static_pointer_cast<ExpressionList>(orderings);
}
virtual ExpressionPtr clone() {
OrderbyClausePtr exp(new OrderbyClause(*this));
Expression::deepCopy(exp);
exp->m_expressions = Clone(m_expressions);
return exp;
}
ExpressionListPtr getOrderings() const { return m_expressions; }
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_QUERY_EXPRESSION_H_
+2 -53
Ver Arquivo
@@ -384,48 +384,6 @@ std::string ScalarExpression::getIdentifier() const {
return "";
}
///////////////////////////////////////////////////////////////////////////////
void ScalarExpression::outputCodeModel(CodeGenerator &cg) {
switch (m_type) {
case T_NS_C:
case T_LINE:
case T_TRAIT_C:
case T_CLASS_C:
case T_METHOD_C:
case T_FUNC_C: {
cg.printObjectHeader("SimpleVariableExpression", 2);
std::string varName;
switch (m_type) {
case T_NS_C: varName = "__NAMESPACE__"; break;
case T_LINE: varName = "__LINE__"; break;
case T_TRAIT_C: varName = "__TRAIT__"; break;
case T_CLASS_C: varName = "__CLASS__"; break;
case T_METHOD_C: varName = "__METHOD__"; break;
case T_FUNC_C: varName = "__FUNCTION__"; break;
default: break;
}
cg.printPropertyHeader("variableName");
cg.printValue(varName);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
return;
}
default:
break;
}
cg.printObjectHeader("ScalarExpression", 2);
cg.printPropertyHeader("value");
cg.printValue(m_originalValue);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
void ScalarExpression::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
switch (m_type) {
case T_CONSTANT_ENCAPSED_STRING:
@@ -501,7 +459,7 @@ Variant ScalarExpression::getVariant() const {
return String(m_value);
case T_LNUMBER:
case T_COMPILER_HALT_OFFSET:
return getIntValue();
return strtoll(m_value.c_str(), nullptr, 0);
case T_LINE:
return String(m_translated).toInt64();
case T_TRAIT_C:
@@ -540,7 +498,7 @@ bool ScalarExpression::getString(const std::string *&s) const {
bool ScalarExpression::getInt(int64_t &i) const {
if (m_type == T_LNUMBER || m_type == T_COMPILER_HALT_OFFSET) {
i = getIntValue();
i = strtoll(m_value.c_str(), nullptr, 0);
return true;
} else if (m_type == T_LINE) {
i = getLocation() ? getLocation()->line1 : 0;
@@ -566,12 +524,3 @@ void ScalarExpression::setCompilerHaltOffset(int64_t ofs) {
m_value = ss.str();
m_originalValue = ss.str();
}
int64_t ScalarExpression::getIntValue() const {
// binary number syntax "0b" is not supported by strtoll
if (m_value.compare(0, 2, "0b") == 0) {
return strtoll(m_value.c_str() + 2, nullptr, 2);
}
return strtoll(m_value.c_str(), nullptr, 0);
}
@@ -87,8 +87,6 @@ private:
std::string m_translated;
bool m_quoted;
std::string m_comment; // for inlined constant name
int64_t getIntValue() const;
};
///////////////////////////////////////////////////////////////////////////////
+20 -40
Ver Arquivo
@@ -102,17 +102,12 @@ SimpleFunctionCall::SimpleFunctionCall
const std::string &name, bool hadBackslash, ExpressionListPtr params,
ExpressionPtr cls)
: FunctionCall(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(SimpleFunctionCall),
ExpressionPtr(), name, hadBackslash, params, cls)
, m_type(FunType::Unknown)
, m_dynamicConstant(false)
, m_builtinFunction(false)
, m_dynamicInvoke(false)
, m_transformed(false)
, m_changedToBytecode(false)
, m_optimizable(false)
, m_safe(0)
, m_extra(nullptr)
{
ExpressionPtr(), name, hadBackslash, params, cls),
m_type(FunType::Unknown), m_dynamicConstant(false),
m_builtinFunction(false), m_fromCompiler(false),
m_dynamicInvoke(false), m_transformed(false), m_no_volatile_check(false),
m_safe(0), m_extra(nullptr) {
if (!m_class && m_className.empty()) {
m_dynamicInvoke = Option::DynamicInvokeFunctions.find(m_name) !=
Option::DynamicInvokeFunctions.end();
@@ -443,7 +438,7 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
}
case FunType::FBCallUserFuncSafe:
case FunType::FunctionExists:
{
if (!m_no_volatile_check) {
FunctionScopePtr func = ar->findFunction(Util::toLower(symbol));
if (func && func->isUserFunction()) {
func->setVolatile();
@@ -452,7 +447,7 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
}
case FunType::InterfaceExists:
case FunType::ClassExists:
{
if (!m_no_volatile_check) {
ClassScopePtr cls = ar->findClass(Util::toLower(symbol));
if (cls && cls->isUserClass()) {
cls->setVolatile();
@@ -523,7 +518,7 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
markRefParams(m_funcScope, m_name, canInvokeFewArgs());
}
} else if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
if (m_type == FunType::Unknown &&
if (!m_fromCompiler && m_type == FunType::Unknown &&
!m_class && !m_redeclared && !m_dynamicInvoke && !m_funcScope &&
(m_className.empty() ||
(m_classScope &&
@@ -545,9 +540,7 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
}
}
if (!ok) {
if (m_classScope || !Unit::lookupFunc(String(m_name).get())) {
Compiler::Error(Compiler::UnknownFunction, shared_from_this());
}
Compiler::Error(Compiler::UnknownFunction, shared_from_this());
}
}
}
@@ -577,6 +570,7 @@ void SimpleFunctionCall::updateVtFlags() {
m_name == "call_user_func_array" ||
m_name == "forward_static_call" ||
m_name == "forward_static_call_array" ||
m_name == "hphp_create_continuation" ||
m_name == "get_called_class") {
f->setNextLSB(true);
}
@@ -610,6 +604,10 @@ bool SimpleFunctionCall::isCallToFunction(const char *name) const {
!getClass() && getClassName().empty();
}
bool SimpleFunctionCall::isCompilerCallToFunction(const char *name) const {
return m_fromCompiler && isCallToFunction(name);
}
bool SimpleFunctionCall::isSimpleDefine(StringData **outName,
TypedValue *outValue) const {
if (!isCallToFunction("define")) return false;
@@ -959,7 +957,7 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) {
}
break;
}
if (func->isUserFunction()) {
if (!m_no_volatile_check && func->isUserFunction()) {
func->setVolatile();
}
if (!func->isVolatile() && m_type == FunType::FunctionExists) {
@@ -974,7 +972,7 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) {
for (ClassScopePtrVec::const_iterator it = classes.begin();
it != classes.end(); ++it) {
ClassScopePtr cls = *it;
if (cls->isUserClass()) {
if (!m_no_volatile_check && cls->isUserClass()) {
cls->setVolatile();
}
if (cls->isInterface()) {
@@ -998,7 +996,7 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) {
for (ClassScopePtrVec::const_iterator it = classes.begin();
it != classes.end(); ++it) {
ClassScopePtr cls = *it;
if (cls->isUserClass()) {
if (!m_no_volatile_check && cls->isUserClass()) {
cls->setVolatile();
}
if (!cls->isInterface() && !cls->isTrait()) {
@@ -1043,6 +1041,7 @@ ExpressionPtr SimpleFunctionCall::postOptimize(AnalysisResultConstPtr ar) {
ExpressionPtr(), T_ARRAY, true));
return replaceValue(rep);
}
m_params->resetOutputCount();
}
/*
Dont do this for now. Need to take account of newly created
@@ -1275,26 +1274,6 @@ TypePtr SimpleFunctionCall::inferAndCheck(AnalysisResultPtr ar, TypePtr type,
return rtype;
}
///////////////////////////////////////////////////////////////////////////////
void SimpleFunctionCall::outputCodeModel(CodeGenerator &cg) {
if (m_class || !m_className.empty()) {
cg.printObjectHeader("ClassMethodCallExpression", 4);
cg.printPropertyHeader("className");
StaticClassName::outputCodeModel(cg);
cg.printPropertyHeader("methodName");
} else {
cg.printObjectHeader("SimpleFunctionCallExpression", 3);
cg.printPropertyHeader("functionName");
}
cg.printValue(m_origName);
cg.printPropertyHeader("arguments");
cg.printExpressionVector(m_params);
cg.printPropertyHeader("sourceLocation");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -1634,3 +1613,4 @@ ExpressionPtr hphp_opt_is_callable(CodeGenerator *cg,
}
}

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