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
2298 arquivos alterados com 100996 adições e 517365 exclusões
+9 -4
Ver Arquivo
@@ -1,5 +1,10 @@
*.[oad]
*.hhbc
/bin*-g
/bin*-O
/bin/*.so
/bin/hphp_options
/bin/systemlib.php
.mkdir
hphp.log
@@ -36,8 +41,6 @@ hphp.log
/hphp/runtime/ext/*.ext_hhvm.h
/hphp/runtime/ext/*/*.ext_hhvm.cpp
/hphp/runtime/ext/*/*.ext_hhvm.h
/hphp/runtime/ext/*/*/*.ext_hhvm.h
/hphp/runtime/ext/*/*/*.ext_hhvm.cpp
/hphp/runtime/ext_zend_compat/*/*.ext_hhvm.cpp
/hphp/runtime/ext_zend_compat/*/*.ext_hhvm.h
/hphp/runtime/ext_zend_compat/*/*/*.ext_hhvm.cpp
@@ -52,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
@@ -61,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
-1
Ver Arquivo
@@ -23,5 +23,4 @@ env:
script: hphp/hhvm/hhvm hphp/test/run $TEST_RUN_MODE
notifications:
email: false
irc: "chat.freenode.net#hhvm"
-31
Ver Arquivo
@@ -1,31 +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)
CHECK_CXX_SOURCE_COMPILES("#include <time.h>
int main() {
clock_gettime((clockid_t)0, NULL);
return 0;
}" HAVE_CLOCK_GETTIME)
if (HAVE_CLOCK_GETTIME)
add_definitions("-DFOLLY_HAVE_CLOCK_GETTIME=1")
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 -8
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,14 +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 ${GNUCC_48_OPT}")
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)
+16 -18
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,10 +85,13 @@ 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)
# GD checks
@@ -138,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)
@@ -305,17 +302,19 @@ if (NOT RECENT_CCLIENT)
message(FATAL_ERROR "Your version of c-client is too old, you need 2007")
endif()
find_package(Libpam)
if (PAM_INCLUDE_PATH)
include_directories(${PAM_INCLUDE_PATH})
else()
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)
endif()
if (CCLIENT_NEEDS_PAM)
find_package(Libpam REQUIRED)
include_directories(${PAM_INCLUDE_PATH})
else()
add_definitions(-DSKIP_IMAP_GSS=1)
endif()
if (NOT CCLIENT_HAS_SSL)
add_definitions(-DSKIP_IMAP_SSL=1)
endif()
@@ -463,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)
@@ -477,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 -19
Ver Arquivo
@@ -68,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)
@@ -122,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()
+2 -21
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()
@@ -120,10 +105,6 @@ if(APPLE)
add_definitions(-DMACOSX_DEPLOYMENT_TARGET=10.6)
endif()
if(ENABLE_FASTCGI)
add_definitions(-DENABLE_FASTCGI=1)
endif ()
# enable the OSS options if we have any
add_definitions(-DHPHP_OSS=1)
+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 precedessor HPHPc before it) has realized over a 9x increase in web request throughput and over a 5x reduction in memory consumption for Facebook compared with the Zend PHP 5.2 engine + APC.
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.
+4 -27
Ver Arquivo
@@ -22,14 +22,10 @@ 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 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
@@ -37,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 &
@@ -47,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
@@ -67,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
-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
+46 -11
Ver Arquivo
@@ -16,14 +16,44 @@
#
include(HPHPSetup)
include(FollySetup)
# 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)
@@ -32,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)
@@ -44,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)
+2 -3
Ver Arquivo
@@ -1,9 +1,8 @@
Next release
- support date.timezone in ini files
- implement fileinfo
- special comparisons for DateTime
- <cool stuff goes here>
"Sausage" 14-Oct-2013
- 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
+13 -8
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"
@@ -2108,6 +2108,7 @@ int AliasManager::collectAliasInfoRecur(ConstructPtr cs, bool unused) {
}
cs->clearVisited();
cs->clearChildOfYield();
StatementPtr s = dpc(Statement, cs);
if (s) {
@@ -2360,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:
@@ -2395,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) {
@@ -2530,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;
@@ -2606,7 +2611,7 @@ private:
ExpressionListPtr el(
new ExpressionList(
CONSTRUCT_EXP(target),
CONSTRUCT_PARAMS(target),
ExpressionList::ListKindComma));
if (target->isUnused()) {
el->setUnused(true);
@@ -2950,7 +2955,7 @@ private:
slistPtr->insertElement(
ExpStatementPtr(
new ExpStatement(
CONSTRUCT_STMT(slistPtr), assertion)),
CONSTRUCT_PARAMS(slistPtr), assertion)),
idx);
}
break;
@@ -3031,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);
+18 -22
Ver Arquivo
@@ -967,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() {}
@@ -993,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);
@@ -1183,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)
@@ -1228,7 +1225,7 @@ template <typename When>
void
AnalysisResult::preWaitCallback(bool first,
const BlockScopeRawPtrQueue &scopes,
void *context) {
void *opaque) {
// default is no-op
}
@@ -1237,7 +1234,7 @@ bool
AnalysisResult::postWaitCallback(bool first,
bool again,
const BlockScopeRawPtrQueue &scopes,
void *context) {
void *opaque) {
// default is no-op
return again;
}
@@ -1302,7 +1299,7 @@ struct BIPairCmp {
template <typename When>
void
AnalysisResult::processScopesParallel(const char *id,
void *context /* = NULL */) {
void *opaque /* = NULL */) {
BlockScopeRawPtrQueue scopes;
getScopesSet(scopes);
@@ -1339,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
{
@@ -1393,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();
@@ -1565,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: " <<
@@ -1672,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());
}
@@ -1686,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;
@@ -1714,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);
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+51 -300
Ver Arquivo
@@ -28,9 +28,6 @@
#include "hphp/runtime/vm/unit.h"
#include "hphp/util/hash.h"
#include <deque>
#include <utility>
namespace HPHP {
DECLARE_BOOST_TYPES(ClosureExpression);
@@ -98,7 +95,6 @@ public:
IterKind kind;
Id id;
};
#define O(name, imm, pop, push, flags) \
void name(imm);
#define NA
@@ -123,7 +119,6 @@ public:
#define AA ArrayData*
#define BA Label&
#define OA unsigned char
#define VSA std::vector<std::string>&
OPCODES
#undef O
#undef NA
@@ -144,7 +139,6 @@ public:
#undef AA
#undef BA
#undef OA
#undef VSA
private:
ConstructPtr m_node;
UnitEmitter& m_ue;
@@ -322,246 +316,13 @@ 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;
};
class FinallyRouter;
DECLARE_BOOST_TYPES(FinallyRouterEntry);
/*
* FinallyRouterEntry represents a single level of the unified stack
* of constructs that are meaningful from the point of view of finally
* implementation. The levels are used to keep track of the information
* such as the actions that can be taken inside a block.
*/
class FinallyRouterEntry {
public:
enum EntryKind {
// Top-level (global) context.
GlobalEntry,
// Function body / method body entry.
FuncBodyEntry,
// Entry for finally fault funclets emitted after the body of
// a function
FuncFaultEntry,
// Try block entry (begins with try ends after catches).
TryFinallyEntry,
// Finally block entry (begins after catches ends after finally)
FinallyEntry,
// Loop OR a break statement.
LoopEntry,
};
typedef Emitter::IterPair IterPair;
typedef std::vector<IterPair> IterVec;
DECLARE_BOOST_TYPES(Action);
/*
* The structure represents a code path that potentially requires
* running finally blocks. A code path has an assigned state ID that
* is used inside switch statements emitted at the end of finally
* blocks. It also has an optional label (the destination to jump
* to after all the required finally blocks are run).
*/
struct Action {
static const int k_unsetState;
explicit Action(FinallyRouter* router);
~Action();
// Manage state ID reuse.
bool isAllocated();
void allocate();
void release();
FinallyRouter* m_router;
// The target to jump to once all the necessary finally blocks
// are run.
Label m_label;
// The state ID that identifies this action inside finally switch
// statements. This is the id assigned to the "state" unnamed
// local variable.
int m_state;
};
FinallyRouterEntry(FinallyRouter* router,
EntryKind kind,
FinallyRouterEntryPtr parent);
~FinallyRouterEntry();
// Helpers used for freeing iterators when appropriate actions
// require that.
void emitIterBreak(Emitter& e,
IterVec& iters,
Label& target);
void emitIterFree(Emitter& e, IterVec& iters);
void emitIterFree(Emitter& e);
// Emission of code snippets commencing actions. Method
// emitXYZ(e, ...) should be used instead of e.XYZ(...) in
// EmitterVisitor.
void emitReturn(Emitter& e, char sym);
void emitReturnImpl(Emitter& e,
char sym,
IterVec& iters);
void emitGoto(Emitter& e, StringData* name);
void emitGotoImpl(Emitter& e,
StringData* name,
IterVec& iters);
void emitBreak(Emitter& e, int depth);
void emitBreakImpl(Emitter& e,
int depth,
IterVec& iters);
void emitContinue(Emitter& e, int depth);
void emitContinueImpl(Emitter& e,
int depth,
IterVec& iters);
// Emit the switch statement in the finally epilogue. Optimizes
// cases where there is either just a fall-through case, or where
// there is a single case other than fall-through.
void emitFinallySwitch(Emitter& e);
// Helper for emitting beginning of single case from the finally
// epilogue.
void emitCase(Emitter& e, std::vector<Label*>& cases, ActionPtr action);
void emitReturnCase(Emitter& e, std::vector<Label*>& cases, char sym);
void emitReturnCaseImpl(Emitter& e, char sym, IterVec& iters);
void emitBreakCase(Emitter& e, std::vector<Label*>& cases, int depth);
void emitBreakCaseImpl(Emitter& e, int depth, IterVec& iters);
void emitContinueCase(Emitter& e, std::vector<Label*>& cases, int depth);
void emitContinueCaseImpl(Emitter& e, int depth, IterVec& iters);
// Helper for establishing the maximal depth of break / continue
// actions that are allocated.
int getBreakContinueDepth();
// Returns the maximal break / continue depth admissable (aka the
// number of nested loops).
int getMaxBreakContinueDepth();
// Methods used for emitting different cases for the finally
// epilogue switch.
void emitGotoCase(Emitter& e, std::vector<Label*>& cases, StringData* name);
void emitGotoCaseImpl(Emitter& e, StringData* name, IterVec& iters);
void emitReturnCases(Emitter& e, std::vector<Label*>& cases);
void emitGotoCases(Emitter& e, std::vector<Label*>& cases);
void emitBreakContinueCases(Emitter& e, std::vector<Label*>& cases);
void emitAllCases(Emitter& e, std::vector<Label*>& cases);
// Methods used for collecting labels corresponding to the cases
// from the finally epilogue. All the labels are accumulated
// inside the cases array. The array is eventually passed to
// e.Switch as the immediate argument.
void collectReturnCases(std::vector<Label*>& cases);
void collectGotoCases(std::vector<Label*>& cases);
void collectBreakContinueCases(std::vector<Label*>& cases);
void collectCase(std::vector<Label*>& cases,
ActionPtr action);
void collectAllCases(std::vector<Label*>& cases);
// The number of cases to be emitted. This is a helper used in
// establishing whether one of the optimized cases can be used.
int getCaseCount();
// Methods used for allocating new finally-aware code-paths.
// When alloc is set to false, the action is merely allocated in
// memory and shared among different entries. When alloc is set to
// true, the action is additionally assigned a state ID.
ActionPtr registerReturn(StatementPtr s, char sym);
ActionPtr registerGoto(StatementPtr s, StringData* name, bool alloc);
ActionPtr registerBreak(StatementPtr s, int depth, bool alloc);
ActionPtr registerContinue(StatementPtr s, int depth, bool alloc);
// Used to indicate that a particular label is present inside
// an entry. Labels don't have corresponding actions, however
// they need to be tracked in order to handle gotos appropriately.
void registerLabel(StatementPtr s, StringData* name);
// Yield / await is not supported inside a finally block for now.
// This method throws a parse time fatal whenever appropriate.
void registerYieldAwait(ExpressionPtr e);
FinallyRouter* m_router;
EntryKind m_kind;
// Only used for loop / break kind of entries.
Id m_iterId;
bool m_iterRef;
// Because of a bug in code emission, functions sometimes have
// inconsistent return flavours. Therefore instead of a single
// return action, there need to be one return action per flavor
// used. Once the bug is removed, this code can be simplified.
std::map<char, ActionPtr> m_returnActions;
// A map of goto actions. Each goto action is identified by the
// name of the destination label.
std::map<StringData*, ActionPtr, string_data_lt> m_gotoActions;
// A map of goto labels occurrning inside the statement represented
// by this entry. This value is used for establishing whether
// a finally block needs to be executed when performing gotos.
std::set<StringData*, string_data_lt> m_gotoLabels;
// Continue actions identified by their depth.
std::map<int, ActionPtr> m_continueActions;
// Break actions identified by their depth.
std::map<int, ActionPtr> m_breakActions;
// The label denoting the beginning of a finally block inside the
// current try. Only used when the entry kind is a try statement.
Label m_finallyLabel;
// The cases that need to be included in the switch statement. Only
// used when kind is set to try statement.
// These are the actions that are invoked inside the protected region
// protected by the try represented by this entry.
std::set<ActionPtr> m_finallyCases;
// The parent entry.
FinallyRouterEntryPtr m_parent;
};
class FinallyRouter {
public:
typedef FinallyRouterEntry::EntryKind EntryKind;
FinallyRouter();
~FinallyRouter();
// The top entry on the unified stack.
FinallyRouterEntryPtr top();
// Create an entry corresponding to the passed in statement s.
// If the statement is insignificant (e.g. is an if statement),
// nullptr is returned.
FinallyRouterEntryPtr createForStatement(StatementPtr s);
// Create a global (top-level) entry.
FinallyRouterEntryPtr createGlobal(StatementPtr s);
// Create an entry for a functiob body.
FinallyRouterEntryPtr createFuncBody(StatementPtr s);
// Create an entry for a fault funclet inside a function body
FinallyRouterEntryPtr createFuncFault(StatementPtr s);
// Helper function for creating entries.
FinallyRouterEntryPtr create(StatementPtr s, EntryKind kind);
// Enter/leave the passed in entry. Note that entries sometimes need be
// to be constructed before they are entered, or need to be accessed
// after they are left. This especially applies to constructs such
// as loops and try blocks.
void enter(FinallyRouterEntryPtr);
void leave(FinallyRouterEntryPtr);
// Functions used for handling state IDs allocation.
// FIXME (#3275259): This should be moved into global / func
// body / fault funclet entries in order to optimize state
// allocation. See the task description for more details.
int allocateState();
void releaseState(int state);
// The stack of all the entered entries.
std::vector<FinallyRouterEntryPtr> m_entries;
// The state IDs currently allocated. See FIXME above.
std::set<int> m_states;
Label* m_entry;
};
class EmitterVisitor {
friend class UnsetUnnamedLocalThunklet;
friend class FuncFinisher;
public:
explicit EmitterVisitor(UnitEmitter& ue);
~EmitterVisitor();
@@ -571,7 +332,6 @@ 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;
@@ -589,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);
@@ -610,15 +370,6 @@ public:
|| isJumpTarget(m_ue.bcPos())
|| (instrFlags(getPrevOpcode()) & TF) == 0);
}
FinallyRouter& getFinallyRouter() { return m_finallyRouter; }
Id getStateLocal() {
DCHECK(m_stateLocal >= 0);
return m_stateLocal;
}
Id getRetLocal() {
DCHECK(m_retLocal >= 0);
return m_retLocal;
}
class IncludeTimeFatalException : public Exception {
public:
@@ -688,6 +439,31 @@ private:
FuncEmitter* m_fe;
};
class ControlTargets {
public:
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),
@@ -706,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 {
@@ -769,19 +541,16 @@ 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<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;
FinallyRouter m_finallyRouter;
Id m_stateLocal;
Id m_retLocal;
MetaInfoBuilder m_metaInfo;
public:
bool checkIfStackEmpty(const char* forInstruction) const;
@@ -800,11 +569,16 @@ 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);
@@ -814,6 +588,7 @@ public:
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);
@@ -834,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);
@@ -899,55 +675,31 @@ 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,
FinallyRouterEntryPtr entry);
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);
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 newFuncletAndRegion(Offset start,
Offset end,
Thunklet* t,
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
void newFuncletAndRegion(StatementPtr stmt,
Offset start,
Offset end,
Thunklet* t,
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
void newFPIRegion(Offset start, Offset end, Offset fpOff);
void copyOverExnHandlers(FuncEmitter* fe);
@@ -967,7 +719,6 @@ public:
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,
+60 -71
Ver Arquivo
@@ -13,11 +13,8 @@
| 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/analysis_result.h"
#include "hphp/compiler/analysis/class_scope.h"
@@ -26,6 +23,7 @@
#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"
@@ -100,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);
@@ -111,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);
@@ -324,73 +321,66 @@ 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) {
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;
}
}
}
hoistOnly = true;
}
m_includeState = 2;
}
@@ -400,9 +390,11 @@ void FileScope::analyzeIncludes(AnalysisResultPtr ar) {
}
}
void FileScope::visit(AnalysisResultPtr ar,
void (*cb)(AnalysisResultPtr, StatementPtr, void*),
void *data) {
void *data)
{
if (m_pseudoMain) {
cb(ar, m_pseudoMain->getStmt(), data);
}
@@ -417,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(),
-1
Ver Arquivo
@@ -62,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;
-5
Ver Arquivo
@@ -354,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());
-2
Ver Arquivo
@@ -226,8 +226,6 @@ public:
bool allowOverride() const;
void setAllowOverride();
bool needsFinallyLocals() const;
/**
* Whether this function is a runtime helper function
*/
+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);
}
}
-1
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;
+2 -148
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,148 +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::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:%ld;", 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:6:\"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", 4);
printPropertyHeader("expression");
expression->outputCodeModel(*this);
printPropertyHeader("operation");
printValue(PHP_REFERENCE_OP);
printPropertyHeader("location");
printLocation(expression->getLocation());
printObjectFooter();
} else {
expression->outputCodeModel(*this);
}
}
void CodeGenerator::printExpressionVector(ExpressionListPtr el) {
printf("V:6:\"Vector\":%d:{", el->getCount());
if (el->getCount() > 0) {
el->outputCodeModel(*this);
}
printf("}");
}
void CodeGenerator::printExpressionVector(ExpressionPtr e) {
printf("V:6:\"Vector\":1:{");
e->outputCodeModel(*this);
printf("}");
}
void CodeGenerator::printAsBlock(StatementPtr s) {
if (s->is(Statement::KindOfBlockStatement)) {
s->outputCodeModel(*this);
} else {
printObjectHeader("BlockStatement", 2);
printPropertyHeader("statements");
if (s->is(Statement::KindOfStatementList)) {
auto sl = static_pointer_cast<StatementList>(s);
printStatementVector(sl);
} else {
printf("V:6:\"Vector\":1:{");
s->outputCodeModel(*this);
printf("}");
}
printPropertyHeader("location");
printLocation(s->getLocation());
printObjectFooter();
}
}
void CodeGenerator::printStatementVector(StatementListPtr sl) {
printf("V:6:\"Vector\":%d:{", sl->getCount());
if (sl->getCount() > 0) {
sl->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();
}
-27
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_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,34 +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 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 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];
-103
Ver Arquivo
@@ -1,103 +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_REFERENCE_OP = 21,
PHP_REQUIRE_OP = 22,
PHP_REQUIRE_ONCE_OP = 23,
PHP_STRING_CAST_OP = 24,
PHP_UNSET_CAST_OP = 25,
};
/** Enumerates the kinds of type declaration statements. */
enum CodeModelTypeKind {
PHP_CLASS = 1,
PHP_INTERFACE = 2,
PHP_TRAIT = 3,
};
}
#endif // incl_HPHP_CODE_MODEL_ENUMS_H_
+3 -4
Ver Arquivo
@@ -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";
@@ -596,7 +596,6 @@ int process(const CompilerOptions &po) {
return 1;
}
if (Option::WholeProgram || po.target == "analyze") {
Timer timer(Timer::WallTime, "analyzeProgram");
ar->analyzeProgram();
}
}
+6 -7
Ver Arquivo
@@ -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 {
@@ -195,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);
@@ -244,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.
*/
@@ -301,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("location");
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("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
} else {
cg.printObjectHeader("UnaryOpExpression", 4);
cg.printPropertyHeader("expression");
m_variable->outputCodeModel(cg);
cg.printPropertyHeader("operation");
cg.printValue(PHP_ARRAY_APPEND_POINT_OP);
cg.printPropertyHeader("location");
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("location");
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("location");
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", 2);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("operation");
cg.printValue(PHP_AWAIT_OP);
cg.printPropertyHeader("location");
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;
@@ -913,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("location");
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("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -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", 2);
cg.printPropertyHeader("className");
StaticClassName::outputCodeModel(cg);
cg.printPropertyHeader("propertyName");
cg.printValue(m_varName);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -279,19 +279,6 @@ bool ClosureExpression::hasStaticLocalsImpl(ConstructPtr root) {
return false;
}
///////////////////////////////////////////////////////////////////////////////
void ClosureExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ClosureExpression", 3);
cg.printPropertyHeader("function");
m_func->outputCodeModel(cg);
cg.printPropertyHeader("capturedVariables");
cg.printExpressionVector(m_vars);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -273,17 +273,6 @@ TypePtr ConstantExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return actualType;
}
///////////////////////////////////////////////////////////////////////////////
void ConstantExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("SimpleVariableExpression", 2);
cg.printPropertyHeader("name");
cg.printValue(getNonNSOriginalName());
cg.printPropertyHeader("location");
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("location");
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("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -119,21 +119,6 @@ bool EncapsListExpression::canonCompare(ExpressionPtr e) const {
return m_type == el->m_type;
}
///////////////////////////////////////////////////////////////////////////////
void EncapsListExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("EncapsListExpression", 2);
cg.printPropertyHeader("delimiter");
cg.printValue(m_type);
if (m_exps) {
cg.printPropertyHeader("expressions");
cg.printExpressionVector(m_exps);
}
cg.printPropertyHeader("location");
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();
}
-5
Ver Arquivo
@@ -36,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; \
@@ -350,10 +349,6 @@ public:
return isNoRemove() && m_assertedType;
}
virtual bool allowCellByRef() const {
return false;
}
static ExpressionPtr MakeConstant(AnalysisResultConstPtr ar,
BlockScopePtr scope,
LocationPtr loc,
+14 -9
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) {
}
@@ -248,6 +249,19 @@ void ExpressionList::stripConcat() {
}
}
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)) {
@@ -464,15 +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];
cg.printExpression(exp, exp?exp->hasContext(RefParameter):false);
}
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+9
Ver Arquivo
@@ -75,6 +75,14 @@ public:
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;
@@ -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
-13
Ver Arquivo
@@ -273,19 +273,6 @@ TypePtr ListAssignment::inferTypes(AnalysisResultPtr ar, TypePtr type,
return m_array->inferAndCheck(ar, Type::Variant, false);
}
///////////////////////////////////////////////////////////////////////////////
void ListAssignment::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ListAssignmentExpression", 3);
cg.printPropertyHeader("variables");
cg.printExpressionVector(m_variables);
cg.printPropertyHeader("expression");
m_array->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -131,29 +131,6 @@ TypePtr ModifierExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return TypePtr();
}
///////////////////////////////////////////////////////////////////////////////
void ModifierExpression::outputCodeModel(CodeGenerator &cg) {
cg.printf("V:6:\"Vector\":%d:{", (int)m_modifiers.size());
for (unsigned int i = 0; i < m_modifiers.size(); i++) {
cg.printObjectHeader("Modifier", 1);
cg.printPropertyHeader("name");
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
@@ -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("location");
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("location");
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("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -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:6:\"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("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-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("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -384,45 +384,6 @@ std::string ScalarExpression::getIdentifier() const {
return "";
}
///////////////////////////////////////////////////////////////////////////////
void ScalarExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ScalarExpression", 2);
cg.printPropertyHeader("value");
switch (m_type) {
case T_CONSTANT_ENCAPSED_STRING:
case T_ENCAPSED_AND_WHITESPACE:
case T_STRING:
case T_NUM_STRING:
cg.printValue(m_value);
break;
case T_LNUMBER:
case T_COMPILER_HALT_OFFSET:
cg.printValue((int64_t)strtoll(m_value.c_str(), nullptr, 0));
break;
case T_LINE:
cg.printValue(String(m_translated).toInt64());
break;
case T_TRAIT_C:
case T_CLASS_C:
case T_NS_C:
case T_METHOD_C:
case T_FUNC_C:
cg.printValue(m_translated);
break;
case T_DNUMBER:
cg.printValue(String(m_value).toDouble());
break;
default:
assert(false);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
void ScalarExpression::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
switch (m_type) {
case T_CONSTANT_ENCAPSED_STRING:
+18 -37
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 &&
@@ -575,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);
}
@@ -608,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;
@@ -957,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) {
@@ -972,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()) {
@@ -996,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()) {
@@ -1041,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
@@ -1273,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");
}
m_nameExp->outputCodeModel(cg);
cg.printPropertyHeader("arguments");
cg.printExpressionVector(m_params);
cg.printPropertyHeader("location");
cg.printLocation(m_nameExp->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+4 -16
Ver Arquivo
@@ -40,6 +40,7 @@ public:
bool isDefineWithoutImpl(AnalysisResultConstPtr ar);
void setValid() { m_valid = true; }
void setFromCompiler() { m_fromCompiler = true; }
void setThrowFatal() { m_type = FunType::ThrowFatal; }
void setThrowParseFatal() { m_type = FunType::ThrowParseFatal; }
bool isParseFatalFunction() const {
@@ -77,21 +78,8 @@ public:
void updateVtFlags();
void setLocalThis(const std::string &name) { m_localThis = name; }
bool isCallToFunction(const char *name) const;
bool isCompilerCallToFunction(const char *name) const;
void resolveNSFallbackFunc(AnalysisResultConstPtr ar, FileScopePtr fs);
void setOptimizable() {
m_optimizable = true;
}
bool isOptimizable() const {
return m_optimizable;
}
void changeToBytecode() {
m_changedToBytecode = true;
}
virtual bool allowCellByRef() const override {
return m_changedToBytecode;
}
protected:
enum class FunType {
Unknown,
@@ -119,11 +107,11 @@ protected:
FunType m_type;
unsigned m_dynamicConstant : 1;
unsigned m_builtinFunction : 1;
unsigned m_fromCompiler : 1;
unsigned m_invokeFewArgsDecision : 1;
unsigned m_dynamicInvoke : 1;
unsigned m_transformed : 1;
unsigned m_changedToBytecode : 1; // true if it morphed into a bytecode
unsigned m_optimizable : 1; // true if it can be morphed into a bytecode
unsigned m_no_volatile_check : 1;
int m_safe;
ExpressionPtr m_safeDef;
-11
Ver Arquivo
@@ -307,17 +307,6 @@ TypePtr SimpleVariable::inferAndCheck(AnalysisResultPtr ar, TypePtr type,
return actual;
}
///////////////////////////////////////////////////////////////////////////////
void SimpleVariable::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("SimpleVariableExpression", 2);
cg.printPropertyHeader("variableName");
cg.printValue(m_name);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -167,20 +167,6 @@ bool StaticClassName::checkPresent() {
///////////////////////////////////////////////////////////////////////////////
void StaticClassName::outputCodeModel(CodeGenerator &cg) {
if (isSelf()) {
cg.printf("self");
} else if (isParent()) {
cg.printf("parent");
} else if (isStatic()) {
cg.printf("static");
} else {
cg.printf("%s", m_origClassName.c_str());
}
}
///////////////////////////////////////////////////////////////////////////////
void StaticClassName::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
if (m_class) {
m_class->outputPHP(cg, ar);
@@ -56,7 +56,6 @@ protected:
std::string m_className;
void updateClassName();
void outputCodeModel(CodeGenerator &cg);
void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
private:
unsigned m_self : 1;
@@ -337,22 +337,6 @@ bool StaticMemberExpression::canonCompare(ExpressionPtr e) const {
return m_className == s->m_className;
}
///////////////////////////////////////////////////////////////////////////////
void StaticMemberExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ClassPropertyExpression", 2);
cg.printPropertyHeader("className");
StaticClassName::outputCodeModel(cg);
if (m_exp->is(Expression::KindOfScalarExpression)) {
cg.printPropertyHeader("propertyName");
} else {
cg.printPropertyHeader("propertyExpression");
}
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -20,7 +20,6 @@
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/statement/statement_list.h"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/compiler/analysis/function_scope.h"
@@ -568,80 +567,6 @@ ExpressionPtr UnaryOpExpression::unneededHelper() {
return static_pointer_cast<Expression>(shared_from_this());
}
///////////////////////////////////////////////////////////////////////////////
void UnaryOpExpression::outputCodeModel(CodeGenerator &cg) {
switch (m_op) {
case T_UNSET:
case T_EXIT:
case T_ARRAY:
case T_ISSET:
case T_EMPTY:
case T_EVAL: {
cg.printObjectHeader("SimpleFunctionCallExpression", 3);
std::string funcName;
switch (m_op) {
case T_UNSET: funcName = "unset"; break;
case T_EXIT: funcName = "exit"; break;
case T_ARRAY: funcName = "array"; break;
case T_ISSET: funcName = "isset"; break;
case T_EMPTY: funcName = "empty"; break;
case T_EVAL: funcName = "eval"; break;
default: break;
}
cg.printPropertyHeader("functionName");
cg.printValue(funcName);
cg.printPropertyHeader("arguments");
printf("V:6:\"Vector\":1:{");
m_exp->outputCodeModel(cg);
printf("}");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
return;
}
default:
break;
}
cg.printObjectHeader("UnaryOpExpression", 3);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("operation");
int op = 0;
switch (m_op) {
case T_CLONE: op = PHP_CLONE_OP; break;
case T_INC:
op = m_front ? PHP_PRE_INCREMENT_OP : PHP_POST_INCREMENT_OP;
break;
case T_DEC:
op = m_front ? PHP_PRE_DECREMENT_OP : PHP_POST_DECREMENT_OP;
break;
case '+': op = PHP_PLUS_OP; break;
case '-': op = PHP_MINUS_OP; break;
case '!': op = PHP_NOT_OP; break;
case '~': op = PHP_BITWISE_NOT_OP; break;
case T_INT_CAST: op = PHP_INT_CAST_OP; break;
case T_DOUBLE_CAST: op = PHP_FLOAT_CAST_OP; break;
case T_STRING_CAST: op = PHP_STRING_CAST_OP; break;
case T_ARRAY_CAST: op = PHP_ARRAY_CAST_OP; break;
case T_OBJECT_CAST: op = PHP_OBJECT_CAST_OP; break;
case T_BOOL_CAST: op = PHP_BOOL_CAST_OP; break;
case T_UNSET_CAST: op = PHP_UNSET_CAST_OP; break;
case '@': op = PHP_ERROR_CONTROL_OP; break;
case T_INCLUDE: op = PHP_INCLUDE_OP; break;
case T_INCLUDE_ONCE: op = PHP_INCLUDE_ONCE_OP; break;
case T_REQUIRE: op = PHP_REQUIRE_OP; break;
case T_REQUIRE_ONCE: op = PHP_REQUIRE_ONCE_OP; break;
default:
assert(false);
}
cg.printValue(op);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-33
Ver Arquivo
@@ -15,17 +15,10 @@
*/
#include "hphp/compiler/expression/user_attribute.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/compiler/expression/unary_op_expression.h"
#include "hphp/parser/scanner.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(Expression);
DECLARE_BOOST_TYPES(ExpressionList);
DECLARE_BOOST_TYPES(UnaryOpExpression);
// constructors/destructors
UserAttribute::UserAttribute
@@ -58,32 +51,6 @@ TypePtr UserAttribute::inferTypes(AnalysisResultPtr ar, TypePtr type,
return TypePtr();
}
///////////////////////////////////////////////////////////////////////////////
void UserAttribute::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("CodeAttribute", m_exp != nullptr ? 3 : 2);
cg.printPropertyHeader("attributeName");
cg.printValue(m_name);
if (m_exp != nullptr && m_exp->is(Expression::KindOfUnaryOpExpression)) {
UnaryOpExpressionPtr u(static_pointer_cast<UnaryOpExpression>(m_exp));
if (u->getOp() == T_ARRAY) {
ExpressionPtr ex = u->getExpression();
if (ex->is(Expression::KindOfExpressionList)) {
ExpressionListPtr el(static_pointer_cast<ExpressionList>(ex));
cg.printPropertyHeader("expressions");
cg.printExpressionVector(el);
} else {
assert(false);
}
} else {
assert(false);
}
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+1 -15
Ver Arquivo
@@ -50,6 +50,7 @@ void YieldExpression::analyzeProgram(AnalysisResultPtr ar) {
if (m_keyExp) {
m_keyExp->analyzeProgram(ar);
}
m_valExp->setChildOfYield();
m_valExp->analyzeProgram(ar);
m_label.setNew();
@@ -95,21 +96,6 @@ TypePtr YieldExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return Type::Variant;
}
///////////////////////////////////////////////////////////////////////////////
void YieldExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("YieldExpression", m_keyExp != nullptr ? 3 : 2);
cg.printPropertyHeader("expression");
if (m_keyExp != nullptr) {
cg.printPropertyHeader("key");
m_keyExp->outputCodeModel(cg);
}
cg.printPropertyHeader("value");
m_valExp->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+11 -2
Ver Arquivo
@@ -118,6 +118,7 @@ bool Option::EnableHipHopExperimentalSyntax = false;
bool Option::EnableShortTags = true;
bool Option::EnableAspTags = false;
bool Option::EnableXHP = false;
bool Option::EnableFinallyStatement = false;
int Option::ParserThreadCount = 0;
int Option::GetScannerType() {
@@ -130,7 +131,10 @@ int Option::GetScannerType() {
}
int Option::InvokeFewArgsCount = 6;
bool Option::InvokeWithSpecificArgs = true;
bool Option::FlattenInvoke = true;
int Option::InlineFunctionThreshold = -1;
bool Option::UseVirtualDispatch = false;
bool Option::EliminateDeadCode = true;
bool Option::CopyProp = false;
bool Option::LocalCopyProp = true;
@@ -141,7 +145,6 @@ bool Option::VariableCoalescing = false;
bool Option::ArrayAccessIdempotent = false;
bool Option::DumpAst = false;
bool Option::WholeProgram = true;
bool Option::UseHHBBC = getenv("HHVM_HHBBC");
bool Option::RecordErrors = true;
std::string Option::DocJson;
@@ -150,6 +153,8 @@ bool Option::AllVolatile = false;
StringBag Option::OptionStrings;
bool Option::GenerateCppLibCode = false;
bool Option::GenerateSourceInfo = false;
bool Option::GenerateDocComments = true;
void (*Option::m_hookHandler)(Hdf &config);
@@ -278,11 +283,16 @@ void Option::Load(Hdf &config) {
ParserThreadCount = Process::GetCPUCount();
}
EnableFinallyStatement = config["EnableFinallyStatement"].getBool();
EnableEval = (EvalLevel)config["EnableEval"].getByte(0);
AllDynamic = config["AllDynamic"].getBool(true);
AllVolatile = config["AllVolatile"].getBool();
GenerateCppLibCode = config["GenerateCppLibCode"].getBool(false);
GenerateSourceInfo = config["GenerateSourceInfo"].getBool(false);
GenerateDocComments = config["GenerateDocComments"].getBool(true);
UseVirtualDispatch = config["UseVirtualDispatch"].getBool(false);
EliminateDeadCode = config["EliminateDeadCode"].getBool(true);
CopyProp = config["CopyProp"].getBool(false);
LocalCopyProp = config["LocalCopyProp"].getBool(true);
@@ -293,7 +303,6 @@ void Option::Load(Hdf &config) {
ArrayAccessIdempotent = config["ArrayAccessIdempotent"].getBool(false);
DumpAst = config["DumpAst"].getBool(false);
WholeProgram = config["WholeProgram"].getBool(true);
UseHHBBC = config["UseHHBBC"].getBool(UseHHBBC);
// Temporary, during file-cache migration.
FileCache::UseNewCache = config["UseNewCache"].getBool(false);
+6 -1
Ver Arquivo
@@ -222,6 +222,7 @@ public:
static bool EnableShortTags;
static bool EnableAspTags;
static bool EnableXHP;
static bool EnableFinallyStatement;
static int ParserThreadCount;
static int GetScannerType();
@@ -237,7 +238,10 @@ public:
* Optimizations
*/
static int InvokeFewArgsCount;
static bool InvokeWithSpecificArgs;
static bool FlattenInvoke;
static int InlineFunctionThreshold;
static bool UseVirtualDispatch;
static bool EliminateDeadCode;
static bool CopyProp;
static bool LocalCopyProp;
@@ -248,12 +252,13 @@ public:
/**
* Output options
*/
static bool GenerateCppLibCode;
static bool GenerateSourceInfo;
static bool GenerateDocComments;
static bool ControlFlow;
static bool VariableCoalescing;
static bool DumpAst;
static bool WholeProgram;
static bool UseHHBBC; // see hhbbc/README
static bool RecordErrors;
static std::string DocJson; // filename to dump doc JSON to
+5 -4
Ver Arquivo
@@ -193,14 +193,14 @@ FileCachePtr Package::getFileCache() {
///////////////////////////////////////////////////////////////////////////////
class ParserWorker :
public JobQueueWorker<std::pair<const char *,bool>, Package*, true, true> {
public JobQueueWorker<std::pair<const char *,bool>, true, true> {
public:
bool m_ret;
ParserWorker() : m_ret(true) {}
virtual void doJob(JobType job) {
bool ret;
try {
Package *package = m_context;
Package *package = (Package*)m_opaque;
ret = package->parseImpl(job.first);
} catch (Exception &e) {
Logger::Error("%s", e.getMessage().c_str());
@@ -222,7 +222,8 @@ void Package::addSourceFile(const char *fileName, bool check /* = false */) {
Lock lock(m_mutex);
bool inserted = m_filesToParse.insert(Util::canonicalize(fileName)).second;
if (inserted && m_dispatcher) {
((JobQueueDispatcher<ParserWorker>*)m_dispatcher)->enqueue(
((JobQueueDispatcher<ParserWorker::JobType,
ParserWorker>*)m_dispatcher)->enqueue(
std::make_pair(m_files.add(fileName), check));
}
}
@@ -239,7 +240,7 @@ bool Package::parse(bool check) {
}
if (threadCount <= 0) threadCount = 1;
JobQueueDispatcher<ParserWorker>
JobQueueDispatcher<ParserWorker::JobType, ParserWorker>
dispatcher(threadCount, true, 0, false, this);
m_dispatcher = &dispatcher;
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+24 -159
Ver Arquivo
@@ -100,17 +100,13 @@
#endif
#define NEW_EXP0(cls) \
cls##Ptr(new cls(BlockScopePtr(), \
getLocation()))
cls##Ptr(new cls(BlockScopePtr(), getLocation()))
#define NEW_EXP(cls, e...) \
cls##Ptr(new cls(BlockScopePtr(), \
getLocation(), ##e))
cls##Ptr(new cls(BlockScopePtr(), getLocation(), ##e))
#define NEW_STMT0(cls) \
cls##Ptr(new cls(BlockScopePtr(), getLabelScope(), \
getLocation()))
cls##Ptr(new cls(BlockScopePtr(), getLocation()))
#define NEW_STMT(cls, e...) \
cls##Ptr(new cls(BlockScopePtr(), getLabelScope(), \
getLocation(), ##e))
cls##Ptr(new cls(BlockScopePtr(), getLocation(), ##e))
#define PARSE_ERROR(fmt, args...) HPHP_PARSER_ERROR(fmt, this, ##args)
@@ -155,8 +151,7 @@ StatementListPtr Parser::ParseString(const String& input, AnalysisResultPtr ar,
Parser::Parser(Scanner &scanner, const char *fileName,
AnalysisResultPtr ar, int fileSize /* = 0 */)
: ParserBase(scanner, fileName), m_ar(ar), m_lambdaMode(false),
m_closureGenerator(false), m_nsState(SeenNothing),
m_aliasTable(getAutoAliasedClasses(), [&] { return isAutoAliasOn(); }) {
m_closureGenerator(false), m_nsState(SeenNothing) {
string md5str = Eval::FileRepository::unitMd5(scanner.getMd5());
MD5 md5 = MD5(md5str.c_str());
@@ -217,6 +212,10 @@ string Parser::errString() {
return m_error.empty() ? getMessage() : m_error;
}
bool Parser::enableFinallyStatement() {
return Option::EnableFinallyStatement;
}
void Parser::pushComment() {
m_comments.push_back(m_scanner.detachDocComment());
}
@@ -249,39 +248,6 @@ void Parser::completeScope(BlockScopePtr inner) {
}
}
LabelScopePtr Parser::getLabelScope() const {
DCHECK(!m_labelScopes.empty());
DCHECK(!m_labelScopes.back().empty());
DCHECK(m_labelScopes.back().back() != nullptr);
return m_labelScopes.back().back();
}
void Parser::onNewLabelScope(bool fresh) {
if (fresh) {
m_labelScopes.push_back(LabelScopePtrVec());
}
DCHECK(!m_labelScopes.empty());
LabelScopePtr labelScope(new LabelScope());
m_labelScopes.back().push_back(labelScope);
}
void Parser::onScopeLabel(const Token& stmt, const Token& label) {
DCHECK(!m_labelScopes.empty());
DCHECK(!m_labelScopes.back().empty());
for (auto& scope : m_labelScopes.back()) {
scope->addLabel(stmt.stmt, label.text());
}
}
void Parser::onCompleteLabelScope(bool fresh) {
assert(!m_labelScopes.empty());
assert(!m_labelScopes.back().empty());
m_labelScopes.back().pop_back();
if (fresh) {
m_labelScopes.pop_back();
}
}
///////////////////////////////////////////////////////////////////////////////
// variables
@@ -420,7 +386,7 @@ void Parser::onCallParam(Token &out, Token *params, Token &expr, bool ref) {
}
void Parser::onCall(Token &out, bool dynamic, Token &name, Token &params,
Token *cls) {
Token *cls, bool fromCompiler) {
ExpressionPtr clsExp;
if (cls) {
clsExp = cls->exp;
@@ -429,6 +395,7 @@ void Parser::onCall(Token &out, bool dynamic, Token &name, Token &params,
out->exp = NEW_EXP(DynamicFunctionCall, name->exp,
dynamic_pointer_cast<ExpressionList>(params->exp),
clsExp);
assert(!fromCompiler);
} else {
const string &s = name.text();
// strip out namespaces for func_get_args and friends check
@@ -448,13 +415,8 @@ void Parser::onCall(Token &out, bool dynamic, Token &name, Token &params,
(new RealSimpleFunctionCall
(BlockScopePtr(), getLocation(), name->text(), name->num() & 2,
dynamic_pointer_cast<ExpressionList>(params->exp), clsExp));
if (m_scanner.isHHSyntaxEnabled() && !(name->num() & 2)) {
// If the function name is without any backslashes or
// namespace qualification then we treat this as a candidate
// for optimization via bytecode promotion.
// "idx" is the only function in that class for now but it's
// cheaper to set the bit that to check for the function name
call->setOptimizable();
if (fromCompiler) {
call->setFromCompiler();
}
out->exp = call;
@@ -944,7 +906,7 @@ StatementPtr Parser::onFunctionHelper(FunctionType type,
StatementListPtr stmts = stmt->stmt || stmt->num() != 1 ?
dynamic_pointer_cast<StatementList>(stmt->stmt)
: NEW_STMT0(StatementList);
: NEW_EXP0(StatementList);
ExpressionListPtr old_params =
dynamic_pointer_cast<ExpressionList>(params->exp);
@@ -1048,8 +1010,7 @@ void Parser::onParam(Token &out, Token *params, Token &type, Token &var,
void Parser::onClassStart(int type, Token &name) {
const Type::TypePtrMap& typeHintTypes =
Type::GetTypeHintTypes(m_scanner.isHHSyntaxEnabled());
if (0 == strcasecmp("self", name.text().c_str()) ||
0 == strcasecmp("parent", name.text().c_str()) ||
if (name.text() == "self" || name.text() == "parent" ||
typeHintTypes.find(name.text()) != typeHintTypes.end()) {
PARSE_ERROR("Cannot use '%s' as class name as it is reserved",
name.text().c_str());
@@ -1670,18 +1631,12 @@ void Parser::onTry(Token &out, Token &tryStmt, Token &className, Token &var,
out->stmt = NEW_STMT(TryStatement, tryStmt->stmt,
dynamic_pointer_cast<StatementList>(stmtList),
finallyStmt->stmt);
if (tryStmt->stmt) {
out->stmt->setLabelScope(stmtList->getLabelScope());
}
}
void Parser::onTry(Token &out, Token &tryStmt, Token &finallyStmt) {
out->stmt = NEW_STMT(TryStatement, tryStmt->stmt,
dynamic_pointer_cast<StatementList>(NEW_STMT0(StatementList)),
finallyStmt->stmt);
if (tryStmt->stmt) {
out->stmt->setLabelScope(tryStmt->stmt->getLabelScope());
}
}
void Parser::onCatch(Token &out, Token &catches, Token &className, Token &var,
@@ -1699,11 +1654,6 @@ void Parser::onCatch(Token &out, Token &catches, Token &className, Token &var,
void Parser::onFinally(Token &out, Token &stmt) {
out->stmt = NEW_STMT(FinallyStatement, stmt->stmt);
// TODO (#3271396) This can be greatly improved. In particular
// even when a finally block exists inside a function it is often
// the case that the unnamed locals state & ret are not needed.
// See task description for further details.
m_file->setAttribute(FileScope::NeedsFinallyLocals);
}
void Parser::onThrow(Token &out, Token &expr) {
@@ -1825,86 +1775,6 @@ void Parser::onTypeSpecialization(Token& type, char specialization) {
///////////////////////////////////////////////////////////////////////////////
// namespace support
//////////////////// AliasTable /////////////////////
Parser::AliasTable::AliasTable(const std::vector<AliasEntry>& autoAliases,
std::function<bool ()> autoOracle) :
m_autoAliases(autoAliases), m_autoOracle(autoOracle),
m_alreadyImported(false) {
if (!m_autoOracle) {
setFalseOracle();
}
}
void Parser::AliasTable::setFalseOracle() {
m_autoOracle = [] () { return false; };
}
/*
* Add the auto-imports to the map.
* This is called by all the other operations, so the auto-import occurs
* on-demand.
*/
void Parser::AliasTable::addAutoImports() {
if (!m_alreadyImported && m_autoOracle()) {
m_alreadyImported = true;
for (auto entry : m_autoAliases) {
m_aliases[entry.alias] = (NameEntry){entry.name, true};
}
}
}
std::string Parser::AliasTable::getName(std::string alias) {
addAutoImports();
auto it = m_aliases.find(alias);
return (m_aliases.end() == it) ? "" : it->second.name;
}
bool Parser::AliasTable::isAliased(std::string alias) {
addAutoImports();
return m_aliases.find(alias) != m_aliases.end();
}
bool Parser::AliasTable::isAutoImported(std::string alias) {
addAutoImports();
auto it = m_aliases.find(alias);
return it != m_aliases.end() && it->second.isAuto;
}
void Parser::AliasTable::map(std::string alias, std::string name) {
addAutoImports();
m_aliases[alias] = (NameEntry){name, false};
}
/*
* To be called when we enter a fresh namespace.
*/
void Parser::AliasTable::clear() {
m_aliases.clear();
m_alreadyImported = false;
}
//////////////////////////////////////////////////////
/*
* We auto-alias classes on HH mode and only if we're in the global namespace.
*/
bool Parser::isAutoAliasOn() {
return m_scanner.isHHSyntaxEnabled() && ("" == m_namespace);
}
std::vector<Parser::AliasTable::AliasEntry> Parser::getAutoAliasedClasses() {
std::vector<AliasTable::AliasEntry> aliases;
aliases.push_back(
(AliasTable::AliasEntry){"Traversable", "HH\\Traversable"});
aliases.push_back(
(AliasTable::AliasEntry){"Iterator", "HH\\Iterator"});
return aliases;
}
void Parser::nns(int token) {
if (m_nsState == SeenNamespaceStatement && token != ';') {
error("No code may exist outside of namespace {}: %s",
@@ -1930,9 +1800,10 @@ void Parser::onNamespaceStart(const std::string &ns,
m_nsState = InsideNamespace;
m_nsFileScope = file_scope;
m_aliases.clear();
pushComment();
m_namespace = ns;
m_aliasTable.clear();
}
void Parser::onNamespaceEnd() {
@@ -1949,17 +1820,12 @@ void Parser::onUse(const std::string &ns, const std::string &as) {
key = ns.substr(pos + 1);
}
}
// It's not an error if the alias already exists but is auto-imported.
// In that case, it gets replaced.
if (m_aliasTable.isAliased(key) && !m_aliasTable.isAutoImported(key) &&
m_aliasTable.getName(key) != ns) {
if (m_aliases.find(key) != m_aliases.end() && m_aliases[key] != ns) {
error("Cannot use %s as %s because the name is already in use: %s",
ns.c_str(), key.c_str(), getMessage().c_str());
return;
}
m_aliasTable.map(key, ns);
m_aliases[key] = ns;
}
std::string Parser::nsDecl(const std::string &name) {
@@ -1976,16 +1842,15 @@ std::string Parser::resolve(const std::string &ns, bool cls) {
alias = ns.substr(0, pos);
}
if (m_aliasTable.isAliased(alias)) {
auto name = m_aliasTable.getName(alias);
hphp_string_imap<std::string>::const_iterator iter = m_aliases.find(alias);
if (iter != m_aliases.end()) {
// Was it a namespace alias?
if (pos != string::npos) {
return name + ns.substr(pos);
return iter->second + ns.substr(pos);
}
// Only classes can appear directly in "use" statements
if (cls) {
return name;
return iter->second;
}
}
@@ -2050,7 +1915,7 @@ void Parser::registerAlias(std::string name) {
size_t pos = name.rfind(NAMESPACE_SEP);
if (pos != string::npos) {
string key = name.substr(pos + 1);
m_aliasTable.map(key, name);
m_aliases[key] = name;
}
}
+4 -82
Ver Arquivo
@@ -17,8 +17,6 @@
#ifndef incl_HPHP_COMPILER_PARSER_H_
#define incl_HPHP_COMPILER_PARSER_H_
#include <functional>
#include "hphp/runtime/base/exceptions.h"
#include "hphp/parser/parser.h"
#include "hphp/compiler/construct.h"
@@ -55,7 +53,6 @@ namespace HPHP {
DECLARE_BOOST_TYPES(Expression);
DECLARE_BOOST_TYPES(Statement);
DECLARE_BOOST_TYPES(StatementList);
DECLARE_BOOST_TYPES(LabelScope);
DECLARE_BOOST_TYPES(Location);
DECLARE_BOOST_TYPES(AnalysisResult);
DECLARE_BOOST_TYPES(BlockScope);
@@ -127,6 +124,7 @@ public:
virtual bool parseImpl();
bool parse();
virtual void error(const char* fmt, ...) ATTRIBUTE_PRINTF(2,3);
virtual bool enableFinallyStatement();
IMPLEMENT_XHP_ATTRIBUTES;
virtual void fatal(const Location* loc, const char* msg);
@@ -159,7 +157,8 @@ public:
void onStaticMember(Token &out, Token &cls, Token &name);
void onRefDim(Token &out, Token &var, Token &offset);
void onCallParam(Token &out, Token *params, Token &expr, bool ref);
void onCall(Token &out, bool dynamic, Token &name, Token &params, Token *cls);
void onCall(Token &out, bool dynamic, Token &name, Token &params,
Token *cls, bool fromCompiler = false);
void onEncapsList(Token &out, int type, Token &list);
void addEncap(Token &out, Token *list, Token &expr, int type);
void encapRefDim(Token &out, Token &var, Token &offset);
@@ -275,36 +274,6 @@ public:
std::string nsDecl(const std::string &name);
std::string resolve(const std::string &ns, bool cls);
/*
* Get the current label scope. A new label scope is demarcated by
* one of the following: a loop, a switch statement, a finally block,
* a try block or one of the constructs demarcating variables scopes
* (i.e. functions, closures, etc.)
* For every label scope, we keep track of the labels
* that are available inside it. This is required for supporting
* features such as try ... finally.
*/
LabelScopePtr getLabelScope() const;
/*
* Called whenever a new label scope is entered. The fresh parameter
* indicates whether the scope is also a variable scope (i.e. a
* function, a closure, ...) or just a label scope (i.e. a loop body,
* a switch statement, a finally block, ...).
*/
void onNewLabelScope(bool fresh);
/*
* Called whenever a new label is encountered.
*/
void onScopeLabel(const Token& stmt, const Token& label);
/*
* Called whenever a label scope ends. The fresh parameter has the
* same meaning as for onNewLabelScope.
*/
void onCompleteLabelScope(bool fresh);
virtual void invalidateGoto(TStatementPtr stmt, GotoError error);
virtual void invalidateLabel(TStatementPtr stmt);
@@ -339,7 +308,6 @@ private:
FileScopePtr m_file;
std::vector<std::string> m_comments; // for docComment stack
std::vector<BlockScopePtrVec> m_scopes;
std::vector<LabelScopePtrVec> m_labelScopes;
std::vector<FunctionContext> m_funcContexts;
std::vector<std::vector<StatementPtr> > m_prependingStatements;
std::vector<ScalarExpressionPtr> m_compilerHaltOffsetVec;
@@ -401,57 +369,11 @@ private:
SeenNamespaceStatement,
InsideNamespace,
};
/*
* An AliasTable maps aliases to names.
* We use it instead a regular map because it lazily imports a bunch of
* names into the current namespace when appropriate.
*/
class AliasTable {
public:
struct AliasEntry {
std::string alias;
std::string name;
};
AliasTable(const std::vector<AliasEntry>& autoAliases,
std::function<bool ()> autoOracle);
std::string getName(std::string alias);
bool isAliased(std::string alias);
bool isAutoImported(std::string alias);
void map(std::string alias, std::string name);
void clear();
private:
struct NameEntry {
std::string name;
bool isAuto; // Is the name automatically-imported?
};
hphp_string_imap<NameEntry> m_aliases;
// These get imported every time we enter a new namespace.
std::vector<AliasEntry> m_autoAliases;
// Returns true if stuff should be auto-imported.
std::function<bool ()> m_autoOracle;
// Have we already auto-imported names for the current namespace?
// This is useful because auto-imports are done lazily.
bool m_alreadyImported;
void setFalseOracle();
void addAutoImports();
};
NamespaceState m_nsState;
bool m_nsFileScope;
std::string m_namespace; // current namespace
AliasTable m_aliasTable;
hphp_string_imap<std::string> m_aliases;
void registerAlias(std::string name);
bool isAutoAliasOn();
std::vector<AliasTable::AliasEntry> getAutoAliasedClasses();
};
///////////////////////////////////////////////////////////////////////////////
-13
Ver Arquivo
@@ -93,19 +93,6 @@ void BlockStatement::inferTypes(AnalysisResultPtr ar) {
if (m_stmts) m_stmts->inferTypes(ar);
}
///////////////////////////////////////////////////////////////////////////////
void BlockStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("BlockStatement", m_stmts != nullptr ? 2 : 1);
if (m_stmts != nullptr) {
cg.printPropertyHeader("statements");
m_stmts->outputCodeModel(cg);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-15
Ver Arquivo
@@ -75,21 +75,6 @@ StatementPtr BreakStatement::preOptimize(AnalysisResultConstPtr ar) {
void BreakStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void BreakStatement::outputCodeModel(CodeGenerator &cg) {
if (strncmp(m_name, "break", 5)) {
cg.printObjectHeader("BreakStatement", 2);
} else {
cg.printObjectHeader("ContinueStatement", 2);
}
cg.printPropertyHeader("depth");
cg.printValue((int)m_depth);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-20
Ver Arquivo
@@ -118,26 +118,6 @@ void CaseStatement::inferAndCheck(AnalysisResultPtr ar, TypePtr type,
if (m_stmt) m_stmt->inferTypes(ar);
}
///////////////////////////////////////////////////////////////////////////////
void CaseStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 1;
if (m_condition != nullptr) numProps++;
if (m_stmt != nullptr) numProps++;
cg.printObjectHeader("CaseStatement", numProps);
if (m_condition != nullptr) {
cg.printPropertyHeader("condition");
m_condition->outputCodeModel(cg);
}
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-19
Ver Arquivo
@@ -134,25 +134,6 @@ void CatchStatement::inferTypes(AnalysisResultPtr ar) {
if (m_stmt) m_stmt->inferTypes(ar);
}
///////////////////////////////////////////////////////////////////////////////
void CatchStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 3;
if (m_stmt != nullptr) numProps++;
cg.printObjectHeader("CatchStatement", numProps);
cg.printPropertyHeader("className");
cg.printValue(m_origClassName);
cg.printPropertyHeader("variableName");
cg.printValue(m_variable->getName());
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-11
Ver Arquivo
@@ -130,17 +130,6 @@ void ClassConstant::inferTypes(AnalysisResultPtr ar) {
m_exp->inferAndCheck(ar, Type::Some, false);
}
///////////////////////////////////////////////////////////////////////////////
void ClassConstant::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ConstantStatement", 2);
cg.printPropertyHeader("expressions");
cg.printExpressionVector(m_exp);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-54
Ver Arquivo
@@ -31,7 +31,6 @@
#include "hphp/util/util.h"
#include "hphp/compiler/statement/interface_statement.h"
#include "hphp/compiler/statement/use_trait_statement.h"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/compiler/option.h"
#include <sstream>
#include <algorithm>
@@ -212,59 +211,6 @@ void ClassStatement::analyzeProgram(AnalysisResultPtr ar) {
void ClassStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void ClassStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 4;
if (m_attrList != nullptr) numProps++;
if (m_type == T_ABSTRACT || m_type == T_FINAL) numProps++;
if (!m_parent.empty()) numProps++;
if (m_base != nullptr) numProps++;
if (m_stmt != nullptr) numProps++;
if (!m_docComment.empty()) numProps++;
cg.printObjectHeader("TypeStatement", numProps);
if (m_attrList != nullptr) {
cg.printPropertyHeader("attributes");
cg.printExpressionVector(m_attrList);
}
if (m_type == T_ABSTRACT) {
cg.printPropertyHeader("modifiers");
cg.printModifierVector("abstract");
} else if (m_type == T_FINAL) {
cg.printPropertyHeader("modifiers");
cg.printModifierVector("final");
}
cg.printPropertyHeader("kind");
if (m_type == T_TRAIT) {
cg.printValue(PHP_TRAIT);
} else {
cg.printValue(PHP_CLASS);
}
cg.printPropertyHeader("name");
cg.printValue(m_originalName);
//TODO: type parameters (task 3262469)
if (!m_parent.empty()) {
cg.printPropertyHeader("baseClass");
cg.printTypeExpression(m_originalParent);
}
if (m_base != nullptr) {
cg.printPropertyHeader("interfaces");
cg.printExpressionVector(m_base);
}
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
if (!m_docComment.empty()) {
cg.printPropertyHeader("comments");
cg.printValue(m_docComment);
}
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-13
Ver Arquivo
@@ -279,19 +279,6 @@ void ClassVariable::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void ClassVariable::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ClassVariableStatement", 3);
cg.printPropertyHeader("modifiers");
m_modifiers->outputCodeModel(cg);
cg.printPropertyHeader("expressions");
cg.printExpressionVector(m_declaration);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-15
Ver Arquivo
@@ -90,21 +90,6 @@ void DoStatement::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void DoStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("DoStatement", m_stmt != nullptr ? 3 : 2);
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("condition");
m_condition->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-11
Ver Arquivo
@@ -81,17 +81,6 @@ void EchoStatement::inferTypes(AnalysisResultPtr ar) {
m_exp->inferAndCheck(ar, Type::String, false);
}
///////////////////////////////////////////////////////////////////////////////
void EchoStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("EchoStatement", 2);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-11
Ver Arquivo
@@ -96,17 +96,6 @@ void ExpStatement::inferTypes(AnalysisResultPtr ar) {
m_exp->inferAndCheck(ar, Type::Any, false);
}
///////////////////////////////////////////////////////////////////////////////
void ExpStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ExpressionStatement", 2);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -92,19 +92,6 @@ void FinallyStatement::inferTypes(AnalysisResultPtr ar) {
if (m_stmt) m_stmt->inferTypes(ar);
}
///////////////////////////////////////////////////////////////////////////////
void FinallyStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("FinallyStatement", m_stmt == nullptr ? 1 : 2);
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-30
Ver Arquivo
@@ -120,36 +120,6 @@ void ForStatement::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void ForStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 1;
if (m_exp1 != nullptr) numProps++;
if (m_exp2 != nullptr) numProps++;
if (m_exp3 != nullptr) numProps++;
if (m_stmt != nullptr) numProps++;
cg.printObjectHeader("ForStatement", numProps);
if (m_exp1 != nullptr) {
cg.printPropertyHeader("expression1");
m_exp1->outputCodeModel(cg);
}
if (m_exp2 != nullptr) {
cg.printPropertyHeader("expression2");
m_exp2->outputCodeModel(cg);
}
if (m_exp3 != nullptr) {
cg.printPropertyHeader("expression3");
m_exp3->outputCodeModel(cg);
}
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -151,30 +151,6 @@ void ForEachStatement::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void ForEachStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 3;
if (m_name != nullptr) numProps++;
if (m_stmt != nullptr) numProps++;
cg.printObjectHeader("ForeachStatement", numProps);
cg.printPropertyHeader("collection");
m_array->outputCodeModel(cg);
if (m_name != nullptr) {
cg.printPropertyHeader("key");
m_name->outputCodeModel(cg);
}
cg.printPropertyHeader("value");
cg.printExpression(m_value, m_ref);
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -132,12 +132,6 @@ void FunctionStatement::analyzeProgram(AnalysisResultPtr ar) {
void FunctionStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void FunctionStatement::outputCodeModel(CodeGenerator &cg) {
MethodStatement::outputCodeModel(cg);
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-11
Ver Arquivo
@@ -135,17 +135,6 @@ void GlobalStatement::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void GlobalStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("GlobalStatement", 2);
cg.printPropertyHeader("expressions");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-11
Ver Arquivo
@@ -86,17 +86,6 @@ void GotoStatement::setNthKid(int n, ConstructPtr cp) {
void GotoStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void GotoStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("GotoStatement", 2);
cg.printPropertyHeader("label");
cg.printValue(m_label);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -83,25 +83,6 @@ void IfBranchStatement::inferTypes(AnalysisResultPtr ar) {
if (m_stmt) m_stmt->inferTypes(ar);
}
///////////////////////////////////////////////////////////////////////////////
void IfBranchStatement::outputCodeModel(CodeGenerator &cg) {
if (m_condition == nullptr) {
if (m_stmt != nullptr) m_stmt->outputCodeModel(cg);
return;
}
cg.printObjectHeader("ConditionalStatement", 3);
cg.printPropertyHeader("condition");
m_condition->outputCodeModel(cg);
if (m_stmt != nullptr) {
cg.printPropertyHeader("trueBlock");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-35
Ver Arquivo
@@ -216,41 +216,6 @@ void IfStatement::inferTypes(AnalysisResultPtr ar) {
if (m_stmts) m_stmts->inferTypes(ar);
}
///////////////////////////////////////////////////////////////////////////////
void IfStatement::outputCodeModel(CodeGenerator &cg) {
for (int i = 0; i < m_stmts->getCount(); i++) {
IfBranchStatementPtr branch =
dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[i]);
assert(branch != nullptr); // this cast always succeeds, by construction.
auto condition = branch->getCondition();
auto statements = branch->getStmt();
auto numProps = 1;
if (condition != nullptr) numProps++;
if (statements != nullptr) numProps++;
if (i < m_stmts->getCount() - 1) numProps++;
if (i > 0) {
cg.printPropertyHeader("falseBlock");
if (i < m_stmts->getCount() - 1) {
printf("V:6:\"Vector\":1:{");
}
}
if (condition != nullptr) {
cg.printObjectHeader("ConditionalStatement", 3);
cg.printPropertyHeader("condition");
condition->outputCodeModel(cg);
cg.printPropertyHeader("trueBlock");
}
if (statements != nullptr) {
cg.printAsBlock(statements);
}
}
for (int i = 0; i < m_stmts->getCount() - 1; i++) {
cg.printf("}");
cg.printObjectFooter();
}
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -26,7 +26,6 @@
#include "hphp/compiler/analysis/variable_table.h"
#include "hphp/util/util.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/compiler/parser/parser.h"
using namespace HPHP;
@@ -253,42 +252,6 @@ StatementPtr InterfaceStatement::preOptimize(AnalysisResultConstPtr ar) {
void InterfaceStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void InterfaceStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 3;
if (m_attrList != nullptr) numProps++;
if (m_base != nullptr) numProps++;
if (m_stmt != nullptr) numProps++;
if (!m_docComment.empty()) numProps++;
cg.printObjectHeader("TypeStatement", numProps);
if (m_attrList != nullptr) {
cg.printPropertyHeader("attributes");
cg.printExpressionVector(m_attrList);
}
cg.printPropertyHeader("kind");
cg.printValue(PHP_INTERFACE);
cg.printPropertyHeader("name");
cg.printValue(m_originalName);
//TODO: type parameters (task 3262469)
if (m_base != nullptr) {
cg.printPropertyHeader("interfaces");
cg.printExpressionVector(m_base);
}
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
if (!m_docComment.empty()) {
cg.printPropertyHeader("comments");
cg.printValue(m_docComment);
}
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-11
Ver Arquivo
@@ -67,17 +67,6 @@ void LabelStatement::setNthKid(int n, ConstructPtr cp) {
void LabelStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void LabelStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("LabelStatement", 2);
cg.printPropertyHeader("label");
cg.printValue(m_label);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+1 -47
Ver Arquivo
@@ -547,8 +547,7 @@ void MethodStatement::inferFunctionTypes(AnalysisResultPtr ar) {
Variant(Variant::NullInit()));
ReturnStatementPtr returnStmt =
ReturnStatementPtr(
new ReturnStatement(getScope(), getLabelScope(),
getLocation(), constant));
new ReturnStatement(getScope(), getLocation(), constant));
m_stmt->addElement(returnStmt);
}
}
@@ -563,51 +562,6 @@ void MethodStatement::inferFunctionTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void MethodStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 3;
if (m_attrList != nullptr) numProps++;
if (m_ref) numProps++;
if (m_params != nullptr) numProps++;
if (m_retTypeAnnotation != nullptr) numProps++;
if (m_stmt != nullptr) numProps++;
if (!m_docComment.empty()) numProps++;
cg.printObjectHeader("FunctionStatement", numProps);
if (m_attrList != nullptr) {
cg.printPropertyHeader("attributes");
cg.printExpressionVector(m_attrList);
}
cg.printPropertyHeader("modifiers");
m_modifiers->outputCodeModel(cg);
if (m_ref) {
cg.printPropertyHeader("returnsReference");
cg.printValue(m_ref);
}
cg.printPropertyHeader("name");
cg.printValue(m_originalName);
//TODO: type parameters (task 3262469)
if (m_params != nullptr) {
cg.printPropertyHeader("parameters");
cg.printExpressionVector(m_params);
}
if (m_retTypeAnnotation != nullptr) {
cg.printPropertyHeader("returnType");
m_retTypeAnnotation->outputCodeModel(cg);
}
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
if (!m_docComment.empty()) {
cg.printPropertyHeader("comments");
cg.printValue(m_docComment);
}
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-14
Ver Arquivo
@@ -115,20 +115,6 @@ void ReturnStatement::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void ReturnStatement::outputCodeModel(CodeGenerator &cg) {
auto nump = m_exp ? 2 : 1;
cg.printObjectHeader("ReturnStatement", nump);
if (m_exp) {
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+1 -4
Ver Arquivo
@@ -28,10 +28,7 @@ const char *Statement::Names[] = {
};
Statement::Statement(STATEMENT_CONSTRUCTOR_BASE_PARAMETERS)
: Construct(scope, loc),
m_kindOf(kindOf),
m_labelScope(labelScope) {
DCHECK(m_labelScope != nullptr);
: Construct(scope, loc), m_kindOf(kindOf) {
}
///////////////////////////////////////////////////////////////////////////////
+5 -16
Ver Arquivo
@@ -18,23 +18,19 @@
#define incl_HPHP_STATEMENT_H_
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/analysis/label_scope.h"
#include <string>
#define STATEMENT_CONSTRUCTOR_BASE_PARAMETERS \
BlockScopePtr scope, LabelScopePtr labelScope, LocationPtr loc, \
Statement::KindOf kindOf
BlockScopePtr scope, LocationPtr loc, Statement::KindOf kindOf
#define STATEMENT_CONSTRUCTOR_BASE_PARAMETER_VALUES \
scope, labelScope, loc, kindOf
scope, loc, kindOf
#define STATEMENT_CONSTRUCTOR_PARAMETERS \
BlockScopePtr scope, LabelScopePtr labelScope, LocationPtr loc
BlockScopePtr scope, LocationPtr loc
#define STATEMENT_CONSTRUCTOR_PARAMETER_VALUES(kindOf) \
scope, labelScope, loc, Statement::KindOf##kindOf
scope, loc, Statement::KindOf##kindOf
#define DECLARE_BASE_STATEMENT_VIRTUAL_FUNCTIONS \
virtual void analyzeProgram(AnalysisResultPtr ar); \
virtual StatementPtr clone(); \
virtual void inferTypes(AnalysisResultPtr ar); \
virtual void outputCodeModel(CodeGenerator &cg); \
virtual void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
#define DECLARE_STATEMENT_VIRTUAL_FUNCTIONS \
DECLARE_BASE_STATEMENT_VIRTUAL_FUNCTIONS; \
@@ -42,15 +38,12 @@
virtual int getKidCount() const; \
virtual void setNthKid(int n, ConstructPtr cp)
#define NULL_STATEMENT() \
BlockStatementPtr(new BlockStatement(getScope(), \
getLabelScope(), \
getLocation(), \
BlockStatementPtr(new BlockStatement(getScope(), getLocation(), \
StatementListPtr()))
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(Statement);
DECLARE_BOOST_TYPES(LabelScope);
#define DECLARE_STATEMENT_TYPES(x) \
x(FunctionStatement), \
@@ -156,14 +149,10 @@ public:
virtual int getRecursiveCount() const { return 1; }
LabelScopePtr getLabelScope() { return m_labelScope; }
void setLabelScope(LabelScopePtr labelScope) { m_labelScope = labelScope; }
protected:
KindOf m_kindOf;
int m_silencerCountMax;
int m_silencerCountCurrent;
LabelScopePtr m_labelScope;
};
///////////////////////////////////////////////////////////////////////////////
+1 -10
Ver Arquivo
@@ -262,8 +262,7 @@ bool StatementList::mergeConcatAssign() {
var, exp1, T_CONCAT_EQUAL));
}
expStmt = ExpStatementPtr
(new ExpStatement(getScope(), getLabelScope(),
getLocation(), exp));
(new ExpStatement(getScope(), getLocation(), exp));
m_stmts[i - length] = expStmt;
for (j = i - (length - 1); i > j; i--) removeElement(j);
@@ -414,14 +413,6 @@ void StatementList::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void StatementList::outputCodeModel(CodeGenerator &cg) {
for (unsigned int i = 0; i < m_stmts.size(); i++) {
m_stmts[i]->outputCodeModel(cg);
}
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-11
Ver Arquivo
@@ -188,17 +188,6 @@ void StaticStatement::inferTypes(AnalysisResultPtr ar) {
scope->getVariables()->clearAttribute(VariableTable::InsideStaticStatement);
}
///////////////////////////////////////////////////////////////////////////////
void StaticStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("StaticStatement", 2);
cg.printPropertyHeader("expressions");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-18
Ver Arquivo
@@ -185,24 +185,6 @@ void SwitchStatement::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void SwitchStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 2;
if (m_cases != nullptr) numProps++;
cg.printObjectHeader("SwitchStatement", numProps);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
if (m_cases != nullptr) {
cg.printPropertyHeader("caseStatements");
cg.printStatementVector(m_cases);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-11
Ver Arquivo
@@ -73,17 +73,6 @@ void ThrowStatement::inferTypes(AnalysisResultPtr ar) {
m_exp->inferAndCheck(ar, Type::Object, false);
}
///////////////////////////////////////////////////////////////////////////////
void ThrowStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ThrowStatement", 2);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -103,28 +103,6 @@ void TraitAliasStatement::setNthKid(int n, ConstructPtr cp) {
void TraitAliasStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void TraitAliasStatement::outputCodeModel(CodeGenerator &cg) {
auto propCount = 3;
auto traitName = m_traitName->getString();
if (!traitName.empty()) propCount++;
cg.printObjectHeader("TraitAliasStatement", propCount);
if (!traitName.empty()) {
cg.printPropertyHeader("traitName");
cg.printValue(traitName);
}
cg.printPropertyHeader("methodName1");
m_methodName->outputCodeModel(cg);
cg.printPropertyHeader("modifiers");
m_modifiers->outputCodeModel(cg);
cg.printPropertyHeader("methodName2");
m_newMethodName->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -107,21 +107,6 @@ void TraitPrecStatement::setNthKid(int n, ConstructPtr cp) {
void TraitPrecStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void TraitPrecStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("TraitInsteadStatement", 3);
cg.printPropertyHeader("traitName");
m_traitName->outputCodeModel(cg);
cg.printPropertyHeader("methodName");
m_methodName->outputCodeModel(cg);
cg.printPropertyHeader("otherTraitNames");
cg.printExpressionVector(m_otherTraitNames);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-25
Ver Arquivo
@@ -126,31 +126,6 @@ void TryStatement::inferTypes(AnalysisResultPtr ar) {
if (m_finallyStmt) m_finallyStmt->inferTypes(ar);
}
///////////////////////////////////////////////////////////////////////////////
void TryStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 1;
if (m_tryStmt != nullptr) numProps++;
if (m_catches->getCount() > 0) numProps++;
if (m_finallyStmt != nullptr) numProps++;
cg.printObjectHeader("TryStatement", numProps);
if (m_tryStmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_tryStmt);
}
if (m_catches->getCount() > 0) {
cg.printPropertyHeader("catchStatements");
cg.printStatementVector(m_catches);
}
if (m_finallyStmt != nullptr) {
cg.printPropertyHeader("finallyStatement");
m_finallyStmt->outputCodeModel(cg);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -56,17 +56,6 @@ void TypedefStatement::analyzeProgram(AnalysisResultPtr) {}
void TypedefStatement::inferTypes(AnalysisResultPtr) {}
void TypedefStatement::outputCodeModel(CodeGenerator& cg) {
cg.printObjectHeader("TypedefStatement", 3);
cg.printPropertyHeader("name");
cg.printValue(name);
cg.printPropertyHeader("typeAnnotation");
annot->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
void TypedefStatement::outputPHP(CodeGenerator& cg, AnalysisResultPtr ar) {
}

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