703 Commits

Autor SHA1 Mensagem Data
Paul Tarjan c4499f273d parallel makes 2014-01-28 19:50:23 -08:00
Erik b538a34e89 Support for UNIX sockets
Add a new config param, Server.FileSocket. When
Server.FileSocket
is set it will be used inplace of a network socket for the primary
server. This uses a new parameter to ServerOptions, m_useFileSocket,
to toggle between treating the address as a socket path or a network
address.

To initialize a socket connection thrift expects the socket file to not
exist. To support this the 'something nice' retry in startServer will
unlink an existing socket only if fuser claims it is unused.
Server.EvilShutdown enables unlinking the socket regardless of current
users.

Closes #1594

Reviewed By: @ptarjan

Differential Revision: D1135876

Pulled By: @sgolemon
2014-01-28 15:38:35 -08:00
Sean Cannella c3b11e0c55 Switch Map and Set to use tracked smart allocators
Switches Map and Set to use tracked allocators. Vector uses
smart_realloc which will require a bit more work.

Reviewed By: @edwinsmith

Differential Revision: D1146939
2014-01-28 15:38:31 -08:00
Paul Tarjan 62c0212045 stop killing the socket until all data is sent
For small responses this was ok, since sending the data didn't take much time. For large requests, they would get truncated without this.

I checked for leaks by printing in the FastCGIConnection constructor and destructor and making sure they match up.

Closes #1631

Reviewed By: @simpkins

Differential Revision: D1147016
2014-01-28 15:38:28 -08:00
Daniel Sloof b4845ed26d SimpleXML rewrite
Update SimpleXML to be compliant with Zend and fix a bunch of
tests.

Closes #1387
Closes #1530

Reviewed By: @ptarjan

Differential Revision: D1135882

Pulled By: @scannell
2014-01-28 15:38:21 -08:00
rbelenov fe7a4fcff9 Support for Intel VTune Amplifier XE
Intel VTune Amplifier XE
(http://software.intel.com/en-us/intel-vtune-amplifier-xe), the
performance analysis tool, supports mapping of performance data from IP
addresses to function names and source file/lines for custom JIT
engines; the engine should provide mapping from generated code to source
using JIT API (http://software.intel.com/en-us/node/458070). This patch
add the reporting to hhvm, allowing to profile PHP code execution and
see both generated assembly and PHP source for hotspots.

The reporting is controlled via Eval.JitUseVtuneAPI runtime option, so
the default behaviour is not affected. If the option is set and hhvm is
profiled by VTune, the information on compiled code is reported via JIT
API and stored in data file which is used during postprocessing and data
visualization.

The patch includes some files from VTune; the are distrubuted under BSD
license.

Closes #1254

Reviewed By: @ottoni

Differential Revision: D1133559

Pulled By: @scannell
2014-01-28 15:38:17 -08:00
bsimmers fd6d3c4dd2 Disable flaky zend test
Reviewed By: @edwinsmith

Differential Revision: D1147082
2014-01-28 15:38:11 -08:00
Owen Yamauchi d004ca9c6b Implement codegen for Call
After LdLoc went down, this is the next top punt. This forced me to get
the bind-call machinery working, and a bunch of other stuff -- it kind
of snowballed on me. Redispatching from prologues and handling stack
overflow also had to work. We were also forgetting to rewind the
globalData frontier if translation failed, and this change combined with
that to actually blow out globalData in a couple of tests.

Small bonus: deleting a bunch of "JIT::" that used to be "Transl::".

Reviewed By: @edwinsmith

Differential Revision: D1134414
2014-01-28 15:38:07 -08:00
Edwin Smith 35ca2405fc Remove dead function: emitContVarEnvHelperCall().
It was never called.

Reviewed By: @ottoni

Differential Revision: D1146574
2014-01-28 15:38:00 -08:00
Stuart Loxton 8f05139460 Fix Zend strrpos compatibility
Fixes Zend strrpos compatibility and adds test.

Closes #1564
Closes #1632

Reviewed By: @bertmaher

Differential Revision: D1142139

Pulled By: @scannell
2014-01-28 15:37:53 -08:00
Camillus Gerard Cai 9b2b28d678 Define missing IMAGETYPE_ constants
Defined IMAGETYPE_UNKNOWN and IMAGETYPE_COUNT

Closes #1634
Closes #1638

Reviewed By: @ptarjan

Differential Revision: D1144855

Pulled By: @scannell
2014-01-28 15:37:49 -08:00
Paul Saab fc26e82dc2 Prevent garbage on DNS_TXT records
Bug #64458 fixed an off by one error when decoding TXT records
that resulted with garbage at the end of the string returned.

Reviewed By: @scannell

Differential Revision: D1146140
2014-01-28 15:37:46 -08:00
Fred Emmott e38a481061 Fix scoping for evaling default ReflectionParameter values
Closes #1449
Closes #1652

Reviewed By: @ptarjan

Differential Revision: D1141045
2014-01-28 15:37:42 -08:00
Fred Emmott 379a930d49 Fix spl_autoload_unregister($unused_but_valid_handler)
If a valid handler is passed in, but wasn't registered, we'd just remove the last one:

- find_if() would return ::end()
- erase() treats that to mean erase the last one

Behavior in the new test was:
- correctly remove 'b'
- incorrectly remove 'a' when asked to remove 'b' again
- segfault when asked to remove 'b' a third time

Reviewed By: @ptarjan

Differential Revision: D1145531
2014-01-28 15:37:39 -08:00
Fred Emmott f2f8c75444 Fix memory management for xinclude nodes
Previously: ==580== ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x604400212103

We were recursively freeing the node, including the attribute nodes - however, libxml2 doesn't malloc them separately - all we needed to do was unlink and free the root.

This fixes a fatal in PHPUnit's test suite.

Reviewed By: @ptarjan

Differential Revision: D1144722
2014-01-28 15:37:35 -08:00
Fred Emmott c68c15b39f Fix incorrect ownerDocument after DOMDocument::createElement
Closes #1551

Fixed while investigating an ASAN failure when running PHPUnit's suite.

Reviewed By: @ptarjan

Differential Revision: D1144627
2014-01-28 15:37:32 -08:00
Sara Golemon d776975c82 Revert "Build ext_zend_compat extensions by default"
This reverts commit 8bf8e13796.

Not behaving as it's supposed to.  Revert until I can figure that out.
2014-01-28 11:11:46 -08:00
Sara Golemon 8bf8e13796 Build ext_zend_compat extensions by default 2014-01-28 09:17:56 -08:00
Jim Radford c052283289 Implement stream_context_{get,set}_default
Implement stream_context_{get,set}_default

Closes #1642

Reviewed By: @ptarjan

Differential Revision: D1145658

Pulled By: @scannell
2014-01-28 09:17:56 -08:00
Sean Cannella a9c43f1b82 Convert ext/zlib to HNI
Convert ext/zlib to HNI

Closes #1635

Reviewed By: @ptarjan

Differential Revision: D1143714
2014-01-28 09:17:55 -08:00
Jim Radford 7d4b75583e LdapLink::sweep shouldn't free smart allocated objects
LdapLink::sweep, avoid freeing smart allocated objects

Closes #1644

Reviewed By: @ptarjan

Differential Revision: D1144565

Pulled By: @scannell
2014-01-28 09:17:55 -08:00
Jim Radford 05c1c762f4 UrlFile::sweep shouldn't free smart allocated objs
UrlFile::sweep shouldn't free smart allocated objs

Closes #1643

Reviewed By: @jdelong

Differential Revision: D1144563

Pulled By: @scannell
2014-01-28 09:17:54 -08:00
Drew Paroski 09d121c851 Update array_shift to support collections
This diff updates the implementation of array_shift to support mutable
collections. A very simple scheme was used to make Vector and Set support
adding elements to the front similar to what HphpArray currently does. I
leave improving the data structures' perf when adding elements to the front
to a subsequent diff.

Reviewed By: @elgenie

Differential Revision: D1140008
2014-01-28 09:17:54 -08:00
Eugene Letuchy 1f3095e8cc make phinq tests slightly more reviewable
... attempting to use diff on expect files containing
 non-printing characters doesn't seem like a good idea, and having
 .expect that are treated as binary makes them hard to review.

Reviewed By: @hermanventer

Differential Revision: D1144149

(flaky www test)
2014-01-28 09:17:54 -08:00
Paul Tarjan b69b36096d support SCRIPT_FILENAME
Some fastcgi documentation doesn't tell you to pass all the params, only a handful. Even the official docs say this http://wiki.nginx.org/HttpFastcgiModule I think we should support the mode where we don't know the document root, jsut the absolute filename. I've already had to help 2 people in github with this issue so I think it is prevelant

Reviewed By: @scannell

Differential Revision: D1125309
2014-01-28 09:17:53 -08:00
Edwin Smith a55228796d Fix XLS spill slot alignment for SIMD registers
If XLS spills a SIMD register, we need the spill slot to
be 16-byte aligned. Also the checkShuffle() assertions weren't
quite right when spilling/loading SIMD registers.

Reviewed By: @jdelong

Differential Revision: D1144168
2014-01-28 09:17:53 -08:00
Owen Yamauchi 9070858a18 Implement codegen for SpillFrame, CallBuiltin, CheckType
SpillFrame is the next top punt after Call. This diff is preparation to
get the Call diff to pass all the tests. Also:

- I removed some code that I said I was going to remove in my last diff
  but forgot. :/

- There was a bug in emitStore, where I was failing to zero-extend bool
  srcs. This caused some interesting test failures once CallBuiltin was
  implemented, because if you call a builtin that returns bool from C++,
  you'll get garbage in the higher-order bytes.

- I had to increase the max number of arguments you can pass to a host
  call.

- Finally, I moved the reserved-stack-space constants out of the X64
  namespace and strengthened some of the asserts around the simulator's
  stack pointer (I ran into this while working).

Reviewed By: @edwinsmith

Differential Revision: D1139057
2014-01-28 09:17:52 -08:00
Paul Tarjan f7d82dfa0b document --php
Closes #1610

Reviewed By: @jdelong

Differential Revision: D1145021
2014-01-28 09:17:52 -08:00
Edwin Smith 9582398cb9 Remove legacy linear scan register allocator
Also rename linear-scan.h to reg-alloc.h, it still contains
a few leftover definitions and it's a useful place to put
declarations that don't depend on the implementation.

Reviewed By: @swtaarrs

Differential Revision: D1135081
2014-01-28 09:17:52 -08:00
Drew Paroski 3fe57c93db Update array_unshift to support Vector and Set
This diff updates the implementation of array_unshift to support Vector
and Set for the first parameter. A very simple scheme was used to make
Vector and Set support adding elements to the front similar to what
HphpArray currently does. I leave improving the data structures' perf
when adding elements to the front to a subsequent diff.

Along the way, I fixed the behavior of array_unshift() to match PHP 5.5
in the case where the first parameter is not an array, Vector, or Set.

Reviewed By: @elgenie

Differential Revision: D1139932
2014-01-28 09:17:51 -08:00
Jordan DeLong a8956cf943 Fix a bug with properties initialized to __DIR__ or __FILE__
Reported on freenode by nelt.  The deepInitHelper code
assumes the result of any deep-initialized property is reference
counted.  Since we recently changed opcodes that push static strings
to push KindOfStaticString, this means in the interpreter we'd hit an
assertion here.  (The JIT was unaffected, and neither case does
anything wrong in an opt build.)

Reviewed By: @paroski

Differential Revision: D1144110
2014-01-28 09:17:51 -08:00
Paul Tarjan f30fc478c3 try these again
I want to see what contbuild has to say about them

Reviewed By: @scannell

Differential Revision: D1116576
2014-01-28 09:17:50 -08:00
aravind a2df4d2e35 Revert "[hh] autoload: don't swallow fatals when autoloading"
This reverts commit 78e4c601db4c0b6ce55b44ae201fedaf47b65501.

Reviewed By: @elgenie

Differential Revision: D1144365
2014-01-28 09:17:50 -08:00
Eugene Letuchy f58e20caf3 array_slice(): support for collections, remove dead code
A straight-forward delegation to ArrayIter does the job.
 After analysis of the uses of slicing code, it seems that slicing can
 be confined to just the ext_array function, since the other uses for
 func_get_args have been subsumed by special purpose bytecodes. Thus,
 this diff also removes Array::slice, ArrayUtil::Slice, func_get_arg,
 and func_get_args.

Reviewed By: @jdelong

Differential Revision: D1142189
2014-01-28 09:17:50 -08:00
Eugene Letuchy 7613e239a6 collections: get rid of CollectionType::StableMap
... since StableMap is an alias for Map (as of {D1116834}),
 there can be no collections of this type.

Reviewed By: @jdelong

Differential Revision: D1119658
2014-01-28 09:17:49 -08:00
Eugene Letuchy ecc2f9b686 collections: unify StableMap and Map as HH\Map
* Turns ##c_StableMap## into a typedef for ##c_Map##
* ## StableMap ## and ## Map ## are both parse-time aliases for ## HH\Map ## (auto-imported under HipHopSyntax)
* Incorporates anietoro's {D1105491}.

Note: this cannot be committed until we're sure about the equality
semantics that make the most sense for the Map/StableMap hybrid (see {D1116829})

Reviewed By: @paroski

Differential Revision: D1116834
2014-01-28 09:17:49 -08:00
Eugene Letuchy 1903ce4d06 make f_array_rand faster when only one key is to be returned
Same big-O complexity, but smaller constant factors ... iterate
 ~1/2 as many elements, generate 1 instead of n random numbers.

Reviewed By: @jdelong

Differential Revision: D1142089
2014-01-28 09:17:48 -08:00
Eugene Letuchy b90ad1e32d collections: support in array_flip() builtin
A straight-forward iteration does the job.

Reviewed By: @jdelong

Differential Revision: D1142068
2014-01-28 09:17:48 -08:00
Bert Maher 2fbfba627e Avoid assertion failure while trying to print an empty block
Doing block->next() on an empty block causes an assertion
failure.  While that should never happen in normal operation, it's
kind of annoying when you're in gdb and want to print a block without
checking first whether it's empty.

Reviewed By: @ottoni

Differential Revision: D1143080
2014-01-28 09:17:48 -08:00
Eugene Letuchy 11e808ef24 collections: support in array_reverse() builtin
Rather than building a way of iterating every collection in
 reverse, `array_reverse` is accomplished by reversing the result of
 converting the collection to an array.

Reviewed By: @paroski

Differential Revision: D1142062
2014-01-28 09:17:47 -08:00
Paul Tarjan b873e69600 remove assert for ::class and make it fatal instead
If you do `parent::class` in a pseudomain you end up in this case. Zend gives this message in that case

Reviewed By: @elgenie

Differential Revision: D1140116
2014-01-28 09:17:47 -08:00
bsimmers 20f3e66d92 Disable/trim flaky tests
- Disable sleep_await.php and curlUpload.php for being flaky
- Remove potentially flaky parts from ext_network.php

Reviewed By: @bertmaher

Differential Revision: D1143085
2014-01-28 09:17:46 -08:00
Owen Yamauchi 3ef0ec891d Convert a few CALL_OPCODEs for ARM
These were all causing me trouble with my upcoming diffs -- punting on
these was causing some tests to time out due to punting so much.

Reviewed By: @edwinsmith

Differential Revision: D1142730
2014-01-28 09:17:46 -08:00
Owen Yamauchi a5261ea56c Fix a sandcastle crash due to PGO mode
I'm only 95% convinced that this is the cause of a sandcastle crash.
We're not calling transCounterAddr with sequential translation ids
anymore (apparently) so it's possible that we need to allocate more than
one chunk of new counters.

I ran a sandcastle with this fix applied and it didn't crash, but the
crash wasn't 100% before, so you never know.

Reviewed By: @ottoni

Differential Revision: D1142512
2014-01-28 09:17:46 -08:00
Simon Welsh beb5d544a5 Convert standard/url to HNI
Convert standard/url to HNI

Closes #1604

Reviewed By: @ptarjan

Differential Revision: D1135473

Pulled By: @scannell
2014-01-28 09:17:45 -08:00
Eugene Letuchy c724f89d7b autoloading: change currently-loading array to be indexed by classNames
Mainly interested in the perflab here, as looping over all the values
 is certainly less efficient O(autoload-depth) as opposed to O(1).

 Also, gets rid of the last use of Array::valueExists

Reviewed By: @scannell

Differential Revision: D1137619
2014-01-28 09:17:45 -08:00
Fred Emmott 417328fefb Implement ini_get_all()
Used by PHPUnit, as triggered by Mockery

Reviewed By: @ptarjan

Differential Revision: D1136971
2014-01-28 09:17:44 -08:00
Fred Emmott 02694e94e4 Move magic ini settings out of IniSettings
Pre-req on implementing ini_get_all() sanely.

Reviewed By: @ptarjan

Differential Revision: D1134579
2014-01-28 09:17:44 -08:00
Alan Frindell edcdac373b Wait for the PProfServer before main exits
Looking into shutdown crashes I found this one with jemalloc junk enabled.

Reviewed By: @scannell

Differential Revision: D1139409
2014-01-28 09:17:44 -08:00
Edwin Smith 4404f655c5 Reduce default MaxRegs setting to avoid wraparound.
Fix wraparound bug in XLS that was reducing available registers.

Reviewed By: @bertmaher

Differential Revision: D1142120
2014-01-28 09:17:43 -08:00
Guilherme Ottoni 67e3047271 Fix rare race condition keeping track of prologue callers
profileSrcKey() compares the request number with
Eval.JitProfileRequests to decide whether or not the given SrcKey will
be generated in profiling mode.  As a result, using profileSrcKey() to
decide whether a given prologue was generated in profile mode or not
was innaccurate: a caller generated in an older request (<
JitProfileRequests) would expect the prologue to be a Proflogue (since
it was JITed beforehand), but the prologue could have been created by
a concurrent, newer request (> JitProfileRequests), which generated the
prologue in non-profiling mode.

This diff fixes the problem by directly checking if the prologue
address is in the profile code section to determine whether it's a
Proflogue or not.

Reviewed By: aravind

Differential Revision: D1141101
2014-01-28 09:17:43 -08:00
Bert Maher cdbc15f571 Remove an unused enum from TraceBuilder
It's unused

Reviewed By: @jdelong

Differential Revision: D1140914
2014-01-28 09:17:43 -08:00
bsimmers 41ec39a6ca Hide new assert behind a flag
DbgAssertRetAddr was useful when I was debugging a specific issue but
I think it's a bit excessive for general use. Don't emit it unless we ask for
extra asserts.

Reviewed By: @bertmaher

Differential Revision: D1140555
2014-01-28 09:17:42 -08:00
Jordan DeLong 1ce2c9cae3 Add simplifier case for BoxPtr
Reviewed By: @bertmaher

Differential Revision: D1136598
2014-01-28 09:17:42 -08:00
Jordan DeLong e4a04562a6 Remove partial non-working and not-enabled implementation of IncDecS
There's no case in ir-translator to get here, so this is dead
code.  It looks like it was maybe trying to use a LdMem as a guard, so
I'm not going to try to turn this on---we can implement it later.

Reviewed By: @bertmaher

Differential Revision: D1136590
2014-01-28 09:17:42 -08:00
Jordan DeLong 9fa3ca15f3 When using HNI return types in hhbbc type inference, include TInitNull
I didn't realize but of course they are generally
implied-nullable right now.  (I think we'll eventually want a way to
plumb the nullability through and require things like ?array if it can
be null.)  cc @Alite404Exception

Reviewed By: @dariorussi

Differential Revision: D1135647
2014-01-28 09:17:41 -08:00
Jordan DeLong dc8d03593b Fix a bug in constant propagation
I think this hasn't shown up yet because nothing has been
getting constprop'd with two inputs of different eval stack flavors.

Reviewed By: @dariorussi

Differential Revision: D1135575
2014-01-28 09:17:41 -08:00
Jordan DeLong 619e177992 Improve couldBeThisObj/mustBeThisObj for hhbbc minstr inference
A TODO was to look a the type of bases that aren't inside the
frame.  I did this, but then I realized neither of these changes can
kick in yet.  The couldBeThisObj needs support for unrelated object
types knowing they aren't related (#3343798), and the mustBeThisObj
will always say false if the base isn't in the FrameThis anyway,
because anything we know about a heap type must include InitNull at
least right now.

We might as well put this in as a test case for #3343798 though.  (And
I clarified some comments about how refs work, and fixed something
wrong with BaseR wrt this.)

Reviewed By: @dariorussi

Differential Revision: D1135320
2014-01-28 09:17:40 -08:00
Jordan DeLong abc1e26ee5 Make the JIT actually take advantage of hhbbc private property inference
The JIT wasn't really able to use the private property
information from HHBBC, because by the time we saw an AssertT opcode
the property was already extracted.

This diff changes the hphpcType in each class' property info to a new
RepoAuthType struct which can contain both the kind of information
hhbbc can provide as well as what hphpc can provide.  Sets the JIT up
to use it, and update prediction-opts to handle the hhbbc case (which
will now generate things like LdMem<Obj<Foo>|InitNull> instead of
LdMem<Cell>.)

A later diff will use the same RepoAuthType flag (plus the repo global
data) to fix the issue with unserialize() being able to break inferred
private property types.

Reviewed By: @ottoni

Differential Revision: D1135298
2014-01-28 09:17:40 -08:00
Jordan DeLong 8920673580 Enable private property inference
After D1132987 it seems to work.

Reviewed By: @dariorussi

Differential Revision: D1133202
2014-01-28 09:17:39 -08:00
Bert Maher 802dab3974 Move runtime helper from translator-x64 to translator-runtime
Some random cleanup I came across.

Reviewed By: @swtaarrs

Differential Revision: D1140317
2014-01-28 09:17:39 -08:00
Brandon Wamboldt b1090c3e04 Fix cURL tests by implementing server script
Many cURL extension tests require an HTTP server to be running
with a specific PHP file available.

Travis will now run this script using the built-in HHVM web server.

I've add skip files so if the user doesn't have the required environment
variable set it will skip the tests, just like PHP does.

Closes #1487

Reviewed By: @ptarjan

Differential Revision: D1117179

Pulled By: @scannell
2014-01-28 09:17:39 -08:00
Sean Cannella b54dff5b10 Add charset= support to PDO mysql DSN
Adds support for charset= in the PDO mysql DSN.

Closes #1309
Closes #1489

Reviewed By: @ptarjan

Differential Revision: D1137883
2014-01-28 09:17:38 -08:00
Ainsley Escorce-Jones 9d28061e71 json_decode() parity with PHP 5.4
Added depth as the optional third parameter, there is now no
fixed maximum depth for the JSON parser, default depth is still 512, if
a user specifies a larger depth limit then the various stacks are
resized.

JSON_BIGINT_AS_STRING is now supported alongside the FB collection
options.

Closes #1470
Closes #1496

Reviewed By: @ptarjan

Differential Revision: D1117099

Pulled By: @scannell
2014-01-28 09:17:38 -08:00
Sean Cannella 621b302b23 Revert "Implement ::class"
Reviewed By: ptarjan

This reverts commit 73975187358058e071bbfca5094bb0fc6e23ef86.
2014-01-28 09:17:37 -08:00
Paul Tarjan a94f25001c Implement ::class
Done mostly in the parser. There was one weird thing, traits have `self::CLASS` refer to themselves instead of the class that uses them. I had to do runtime support for `parent::CLASS` and `static::CLASS`.

Closes #1096

Reviewed By: @elgenie

Differential Revision: D1129169
2014-01-28 09:17:37 -08:00
Paul Tarjan eb2312a5de keep around rawPostData just incase someone reads from php://input
What do you think about this? Usually we keep it around anyways in a global variable (`$HTTP_RAW_POST_DATA`) but that is possible to turn off, so we need a fool-proof place to put it to support `php://input`. Before this diff, the code only gave the last packet of the header in libevent and asserted on fastcgi.

Thoughts? I think it is worth supporting as the php docs says

http://www.php.net/manual/en/ini.core.php#ini.always-populate-raw-post-data
... the preferred method for accessing the raw POST data is php://input.

Closes #1557

Reviewed By: afrind

Differential Revision: D1129130
2014-01-28 09:17:36 -08:00
Dario Russi 82906a26f5 remove runtime options for APC stats
Now that we removed the options from the config files we can remove the options in the code as well

Reviewed By: @jdelong

Differential Revision: D1135707
2014-01-28 08:05:54 -08:00
Eugene Letuchy 35971e45fa collections: support in_array() and array_search() builtins
... and remove utility functions rendered irrelevant

Reviewed By: @paroski

Differential Revision: D1137616
2014-01-28 08:05:53 -08:00
Alex Malyshev 39bc81c7b0 Don't use boost::to_upper
perf is showing that it's calling dynamic_cast, a lot.

Reviewed By: @jdelong

Differential Revision: D1136788
2014-01-28 08:05:53 -08:00
Emil Hesslow e77fc64dc7 Break out stuff to mysql_common so I can reuse it for mysqli
- This mostly just moves stuff around. The idea was to put everything that is f_mysql_ in ext_mysql and move everything else into mysql_common
- It also breaks up the query function into two parts because I need it for mysqli
  - Doing the query
  - And getting the result part

Reviewed By: @ptarjan

Differential Revision: D1106027
2014-01-28 08:05:53 -08:00
Fred Emmott c6c2fa766e Add assert to check for Array return types in IDL
'Array' ends up being KindOfObject, and leads to mysterious segfaults.

Reviewed By: @ptarjan

Differential Revision: D1136568
2014-01-28 08:05:52 -08:00
Owen Yamauchi 75e8e34ba7 Implement codegen for StLoc, Box, and CheckStk in ARM
There's one test case that's giving me fits in trying to implement Call,
and if we were just codegen'ing these opcodes, the problem would just go
away. So here they are.

StLoc happens to be third most frequent punt. CheckStk forced me to get
the jump-chaining machinery working, and it's surprisingly simple.

Reviewed By: @ottoni

Differential Revision: D1136517
2014-01-28 08:05:52 -08:00
aravind 4fda422743 Update NEWS for "Coolio"
Per title.

Reviewed By: @ptarjan

Differential Revision: D1136689
2014-01-28 08:05:51 -08:00
Arnaud GRANAL e03fc4652e pfsockopen returns incorrect connections
Persistent connections currently return a cached connection for (key = "hostname").
Expected behavior is to return a cached connection for (key = "hostname + port").
As a result, persistent connections write and read from the wrong socket if you have multiple connections to the same hostname but different port.

Redis hhvm implementation is affected by this bug (probably other modules too, but not MySQL at least, who uses its own socket cache handler).

Closes #1599

Reviewed By: ps

Differential Revision: D1135971

Pulled By: @scannell
2014-01-28 08:05:51 -08:00
Edwin Smith c5aa39b100 Convert Interval::children to intrusive singly linked list.
std::list is inconvenient for three reasons:
1. when splitting, we have to iterate to find the split position
even though we already have the interval we care about.
2. Loops that visit each split interval must do work for the
parent, then a separate loop for the child.
3. we never need the "prev" pointers

A plain 'next' pointer (aka intrusive singly-linked list) solves
all three problems.

Reviewed By: @bertmaher

Differential Revision: D1135956
2014-01-28 08:05:51 -08:00
Eugene Letuchy 4cc71b677f collections: support min() and max() builtins
Specifically, their one-argument form.

Reviewed By: @paroski

Differential Revision: D1137651
2014-01-28 08:05:50 -08:00
Eugene Letuchy c754019212 collections: support array_fill_keys ...
... and eliminate some single-use array util functions (of
 questionable utility)

Reviewed By: @paroski

Differential Revision: D1137568
2014-01-28 08:05:50 -08:00
Simon Welsh 6c214555e9 Convert ext/apache to HNI
Convert ext/apache to HNI

Closes #1607

Reviewed By: @ptarjan

Differential Revision: D1135889

Pulled By: @scannell
2014-01-28 08:05:45 -08:00
Simon Welsh 6076b94d6d Convert ext/ctype to HNI
Convert ext/ctype to HNI

Closes #1612

Reviewed By: @ptarjan

Differential Revision: D1135975

Pulled By: @scannell
2014-01-28 08:05:01 -08:00
Owen Yamauchi 40100fff5c Normalize ARM's link-register-saving convention
In trying to implement codegen for the Call opcode, I'm running into
problems with the differences between ARM and x64's calling conventions,
specifically with regard to how they save return addresses.

Until now, our ARM code hasn't been treating the link register (the
return address register) like it's supposed to be treated. The register
is technically caller-saved, but normal ARM programs (such as C programs
compiled by gcc) don't save and restore it around callsites. Instead,
non-leaf functions just save it at the very beginning and restore it
just before returning, simply as part of setting up and tearing down the
frame.

What this means for us is that we're now saving it on the stack
immediately on entry to the TC, since, viewed through the traditional
calling-convention lens, the entire TC is a non-leaf function. This
means that we no longer need to save/restore around host calls.

Reviewed By: @edwinsmith

Differential Revision: D1133438
2014-01-28 07:49:27 -08:00
seanc 1e23dec9f0 Split Travis slow/zend test runs further
Summary: This splits the larger Travis test runs roughly evenly to
increase the chance that the tests will pass before hitting the timeout.

Reviewed By: ptarjan
2014-01-22 13:53:44 -08:00
Drew Paroski c1d4b02110 Fix BaseMap::eraseNoCompact to decref string keys
Reviewed By: @elgenie

Differential Revision: D1137646
2014-01-22 12:47:54 -08:00
Bert Maher 9241f43016 Eliminate unused stubBlock() template function
It's unused.

Reviewed By: @swtaarrs

Differential Revision: D1136316
2014-01-22 12:47:54 -08:00
Dario Russi ed23d1a406 Normalize string wrt namespace when used in function or class context
Bytecodes that resolve strings to a class or a function need to normalize the string so it never starts with '\'

Reviewed By: @jdelong

Differential Revision: D1135085
2014-01-22 12:47:54 -08:00
Bert Maher f041b97bff Remove MethodLookup namespace
Namespace isn't needed now that we're using enum classes.

Reviewed By: @jdelong

Differential Revision: D1135968
2014-01-22 12:47:54 -08:00
Jordan DeLong 3009a5a45d Resize the static string table after argument parsing if the size was wrong
Also, change the default size to match cli.hdf, so we don't
do a resize on command line scripts.

Reviewed By: @edwinsmith

Differential Revision: D1126293
2014-01-22 12:47:54 -08:00
Jordan DeLong 2440764f5e Remove MetaInfo::Kind::NonRefCounted
This has been disabled since shortly after it was added,
since hphpc doesn't handle exception edges correctly and reports wrong
information.

Reviewed By: @swtaarrs

Differential Revision: D1135310
2014-01-22 12:47:53 -08:00
Jordan DeLong 13364a8234 Remove AssertStkVal/OverrideLocVal and HHBCTranslator::assertString
Dead after D1133071.  bsimmers said he never really liked
them anyway.

Reviewed By: @swtaarrs

Differential Revision: D1135305
2014-01-22 12:47:53 -08:00
Jordan DeLong 4d9f5d33ef Remove MetaInfo::Kind::String; seems to not kick in anymore
Quite a while back I perflabbed turning this off and saw red,
but I think it must've been noise.  I ran perflabs with an
always_assert(0) in applyInputMetaData here and it never triggered.

Reviewed By: @edwinsmith

Differential Revision: D1133071
2014-01-22 12:47:53 -08:00
Jordan DeLong 994c02283b Use raise_typehint_error for ?Foo hints
So we can use them in static analysis.  Requires a www change
for the error handler.

Reviewed By: @elgenie

Differential Revision: D1125242
2014-01-22 12:47:53 -08:00
Nicholas Ormrod 15de092f49 Removed duplicate #includes
Removed duplicate #includes.

Reviewed By: robbert

Differential Revision: D1136491
2014-01-22 12:47:53 -08:00
Surupa Biswas 80a9ae11b2 Warnings for incorrect params passed to ReflectionProperty get/setValue
Added warnings to match Zend behavior for incorrect number of arguments passed
and for not passing an object as the first parameter when reflecting on instance properties.

Reviewed By: @ptarjan

Differential Revision: D1135118
2014-01-22 12:47:53 -08:00
Jordan DeLong 446a61b422 Fix 86pinit bug in hhbbc relating to collection initializers
I thought 86pinit could only set private properties to
uncounted types, but there's also collection literals.  Merge in
TInitCell---in these classes all private properties initialized by
86pinit will end up as TCell for now, since they start as uninit in
the scalar initializer.  (Things with non-scalar initializers also
will be TInitCell.)  We'll make it do better later.

Reviewed By: @dariorussi

Differential Revision: D1135293
2014-01-22 12:47:52 -08:00
Jordan DeLong 329527e19f Change indentation in lookup_constraint, add task# for a TODO
Reviewed By: @dariorussi

Differential Revision: D1134307
2014-01-22 12:47:52 -08:00
Jordan DeLong d45bc155e5 Add some logging to the assertions about unique classes actually being unique
I've hit this once or twice, and I think it probably is a
race in hphpc or something (it is not consistent).  Just add some
logging to try to help debug next time.  (So far it's always
Ix-related closure classes that have AttrUnique but actually aren't in
the cores I've had.)

Reviewed By: @swtaarrs

Differential Revision: D1135290
2014-01-22 12:47:52 -08:00
Fred Emmott 2762e7b5a0 Support ReflectionClass::getConstructor() for old-style superclass constructors
Reviewed By: @ptarjan

Differential Revision: D1132467
2014-01-22 12:47:52 -08:00
Sean Cannella 700026adc7 Merge pull request #1614 from skyfms/master
Allow disabling hardware counters from cmake
2014-01-22 07:47:32 -08:00
Edwin Smith 55212b92e9 Rename Interval::info -> loc in xls.cpp
Leftover from the RegisterInfo->PhysLoc rename.

Reviewed By: @bertmaher

Differential Revision: D1135841
2014-01-22 05:30:57 -08:00
bsimmers e31c664c02 Disable flaky zend test
Reviewed By: @bertmaher

Differential Revision: D1135985
2014-01-22 05:30:51 -08:00
Kristaps Kaupe e79df3c25e Allow disabling hardware counters from cmake. 2014-01-22 00:59:13 +02:00
Sean Cannella 204745bfe6 PHP_VERSION_ID should not be greater than all Zend
PHP_VERSION_ID is now 504999 which is > all Zend versions which
makes using it for comparisons of less than 5.5/5.6/etc. impossible.

Closes #1603

Reviewed By: @sgolemon

Differential Revision: D1135461
2014-01-21 11:20:15 -08:00
Guilherme Ottoni c7c45e0f04 Turn on the Region JIT (take 2)
Except for ARM.

Reviewed By: @swtaarrs

Differential Revision: D1119650
2014-01-21 11:20:11 -08:00
Drew Paroski 9793cd6059 Update Set to retain insertion order
Reviewed By: @elgenie

Differential Revision: D1129210
2014-01-20 10:12:32 -08:00
Rachel Kroll b82a14d235 Report thread ID in status pages
Reviewed By: tracelog

Differential Revision: D1134840
2014-01-20 10:09:09 -08:00
Paul Tarjan a13cb40a90 work on FastCGI perf
* parse all the fastcgi headers at once
* uppercase the key instead of using case insensitive. This won't return the original casing, but HTTP is case insensitive anyways, so it shouldn't matter *cross fingers*
* stop generating a vector in the header map and do it at readtime
* use `unordered_map`

Reviewed By: @jdelong

Differential Revision: D1128430
2014-01-20 10:09:06 -08:00
Dario Russi 7590d5e084 APC optimizations for arrays and strings to allow them to be shared "static" style.
Making APC strings and APC array with proper shape uncouted and truly shared in APC, saving on copy and ref count

Reviewed By: @jdelong

Differential Revision: D1114228
2014-01-20 10:09:03 -08:00
Joel Marcey f7ea7e74e1 Refactor the framework test script for better modularity and maintenance
I have wanted to break up run.php into its own files and refactor things a bit. So I am now doing that.

Note that the frameworks directory now contains the PHP for individual frameworks and that framework_downloads will contain the actual github code for the frameworks

During refactoring, I found some interesting new issues:

1. The recent changes to reflection (ext_reflection-classes.php, etc.) have caused my test finder to hiccup for cases where I find the tests with reflection. This may be bad code on my part; but I am not sure. Right now it seems the issues are coming with IsSubclassOf, but this is just a guess. I am trying to come up with a repo case.

2. The percentage of Magento2 has dropped into the upper 80% range. And this is due to some namespace fatals that are occurring. We need to dig into that. Note, that we are using a more recent git hash for Magento2 (instead of the August one as before) and they added more namespace support during that time. We are also seeing a drop in Drupal as well, but not to the same degree.

@ptarjan, this diff does not make the abstract Framework class public yet. That can be done in a subsequent diff :-)

Reviewed By: @ptarjan

Differential Revision: D1133446
2014-01-20 10:08:59 -08:00
Dario Russi 4ecab8ca94 Make $this available (aka not null) after it has been accessed once and subsequent code would have not run
after $this has been used (dereferenced) all subsequent accesses do not need to check for null

Reviewed By: @jdelong

Differential Revision: D1132614
2014-01-20 10:08:56 -08:00
Alex Malyshev 69a83741fc Support more of EG and PG in ext_zend_compat
Not all of the functions return references, so they can't be written to,
only read from.

Reviewed By: @ptarjan

Differential Revision: D1128247
2014-01-20 10:08:49 -08:00
bsimmers 6aa6d171e1 Add some asserts to the jit
These were all added while debugging an xls issue and they seem
generally useful.

Reviewed By: @edwinsmith

Differential Revision: D1132041
2014-01-20 10:08:45 -08:00
Bert Maher 2d6e5ba266 Pop stack before ContEnter
If we pop the stack after ContEnter, it creates a
LdStack/TakeStack that keeps an SSATmp live across a call, which
(rightfully) causes an assertion to fail later.

This isn't a problem if we have refcount opts or dce on, since those
passes will remove the TakeStack, but it would still be good to have
our IR correct in the absence of optimization.

Reviewed By: @swtaarrs

Differential Revision: D1134125
2014-01-20 10:08:42 -08:00
bsimmers c96f6e7c49 Make sure we don't throw without catch blocks
Some optimizations rely on being able to insert code on all exit
edges, so anything that can throw much have a catch block. This diff adds a
runtime check for that and fixes all cases I hit in local and prod testing.

Reviewed By: @edwinsmith

Differential Revision: D1132380
2014-01-20 10:08:39 -08:00
bsimmers e18f7406b0 Remove IRTrace from the jit
Exit traces are gone so this was fairly straightforward.

Reviewed By: @edwinsmith

Differential Revision: D1129611
2014-01-20 10:08:35 -08:00
bsimmers d7dba127d3 Purge exit traces from the jit
This diff eliminates all exit traces from the jit, turning them into
regular old Unlikely blocks in the main trace. IRTrace is still around and we
have one per IRUnit; I'm planning on eliminating it in a separate
diff. IRTrace's BlockList is gone, so now we just store a pointer to the entry
Block and walk the cfg from there.

Reviewed By: @edwinsmith

Differential Revision: D1128179
2014-01-20 10:08:31 -08:00
Sean Cannella 88d6079dc3 Fix server stats reporting
Fix server stats reporting

Reviewed By: @dariorussi

Differential Revision: D1133875
2014-01-20 10:08:28 -08:00
Fred Emmott 973c5847f2 Make SQLite3::version static
Depended on by codeigniter

Reviewed By: @ptarjan

Differential Revision: D1130812
2014-01-20 10:08:24 -08:00
Dario Russi e1d79f54d5 Update ir specification
IR opcodes added during lockdown had missing specifications

Reviewed By: @swtaarrs

Differential Revision: D1134268
2014-01-20 10:08:21 -08:00
bsimmers 58ddd23cec Disable flaky zend test
Reviewed By: @edwinsmith

Differential Revision: D1133886
2014-01-20 10:08:17 -08:00
Dario Russi cfaf436001 NewCol should push specific object types
NewCol and ColAddNewElemC should infer the proper collection type

Reviewed By: @jdelong

Differential Revision: D1129076
2014-01-20 10:08:13 -08:00
Eugene Letuchy ee4a6f7b35 misc: set error handler slightly differently in typehint_number test
... perhaps it will work better in repo mode if the test-installed error
handler always throws an exception, instead of relying on the return
value.

Reviewed By: @jdelong

Differential Revision: D1133463
2014-01-20 10:08:10 -08:00
Edwin Smith 47bc94d3a4 Enable xls by default
Flips the switch, and fixes computeLiveRegs() to account
for Shuffle destinations.

Reviewed By: @swtaarrs

Differential Revision: D1114596
2014-01-20 10:08:06 -08:00
Bert Maher daef8573ec Use getNativeFunctionName in Disasm
Get rid of duplicated code for demangling function names

Reviewed By: @swtaarrs

Differential Revision: D1132428
2014-01-20 10:08:02 -08:00
Evert Pot e93f235669 Added support for CURLOPT_POSTREDIR
Added support for CURLOPT_POSTREDIR

Closes #1477
Closes #1583

Reviewed By: @JoelMarcey

Differential Revision: D1131605

Pulled By: @scannell
2014-01-20 10:07:58 -08:00
Scott Renfro 9d74c2ce93 Change fb_utf8_substr() semantics to return '' on error
Already made the corresponding change in flib.  This
is more consistent with mb_substr() and more consistent with
a typed world -- fb_utf8_substr()'s return value will pass
typehints for strings, for example.

Reviewed By: @alokmenghrajani

Differential Revision: D493517
2014-01-17 14:46:18 -08:00
Jordan DeLong adaaaff943 Add .norepo to a test
I had this in the wrong diff, so broke trunk pushing a stack.

Reviewed By: @elgenie

Differential Revision: D1133199
2014-01-17 14:46:18 -08:00
Eugene Letuchy 8b247bafd1 'num' typehint
It's quite advantageous to be able to support int|float as a
 typehint without introducing support for full-blown unions. To make
 that equivalence happen, a bit of runtime support is necessary

Reviewed By: @jdelong

Differential Revision: D1128502
2014-01-17 14:46:00 -08:00
Owen Yamauchi 4fe752d8e5 Implement DecRef{Stack,Loc,Mem} in ARM mode
DecRefStack is the #2 punt. This involved a surprising amount of code.
Decreffing is hard, apparently.

Reviewed By: @edwinsmith

Differential Revision: D1131799
2014-01-17 01:43:53 -08:00
Jordan DeLong 4f56be3f8f Give up on private property inference on CreateCl opcodes
For now.  As is it can infer incorrect property types since
it isn't set up to look at the closure bodies.

Reviewed By: @dariorussi

Differential Revision: D1132987
2014-01-17 01:43:49 -08:00
Jordan DeLong eb8f8f3825 Fix several issues with type assert opcodes
Type assertions were allocating new DynLocations every time
we encountered them, which breaks getOutputUsage (it uses DynLocation
pointer equality to track the flow of values).  When encountering
assertions, it also wasn't doing the optimization that we have in
applyInputMetaData to eliminate earlier predictions on the same
location.  Finally, this diff finishes the support for optional object
types (fixes inlining and object property accesses in these
situations).

Reviewed By: @swtaarrs

Differential Revision: D1128602
2014-01-17 01:43:45 -08:00
Jordan DeLong 040e87ba69 Make type hint errors disallow recovery if repo was compiled with HardTypeHints
Fix a long-standing issue that could segfault the VM in
RepoAuthoritative mode (not in practice in www, since our error
handler always throws in this case).  To do this, adds a Repo global
metadata blob that we can use to communicate whatever global
compilation information we want to the runtime (I've wished we had
this for a few things in the past).

Reviewed By: @edwinsmith

Differential Revision: D1125218
2014-01-17 01:43:42 -08:00
Jordan DeLong 4be2cfd7d6 A few code review items I accidentally missed
Reviewed By: @edwinsmith

Differential Revision: D1126655
2014-01-17 01:43:38 -08:00
Jordan DeLong 8a8d6fe852 Returning from a function reads locals
Looking at the JIT's output with HHBBC on, I noticed guards
in tracelets that only do RetC weren't going away.  This is because I
forgot to tell the interpreter that return opcodes read locals, so the
assert opcodes weren't being added.

Reviewed By: @swtaarrs

Differential Revision: D1125188
2014-01-17 01:43:34 -08:00
Jordan DeLong f68a1d9c12 AssertObj opcode support for possibly-null types
I think for us to get anything from private property
inference, we have to be able to assert these types and rely on
tracelet guards to remove the nulls.

Reviewed By: @dariorussi

Differential Revision: D1125172
2014-01-17 01:43:30 -08:00
Jordan DeLong 78072ded36 Do better on bc::Clone of ?Obj<=Foo and ?Obj=Foo
A really small thing we needed to have the recently added
is_opt() and unopt() things to do.  Before it would just push TObj.
Now we can push the type with the possible null removed (since we'd
fatal if it was null).

Reviewed By: @dariorussi

Differential Revision: D1125107
2014-01-17 01:43:26 -08:00
Jordan DeLong 510881234a Infer that the Catch opcode always pushes a subclass of Exception
You can't throw non-Exception derived classes.  Also, catch
can't throw.

Reviewed By: @dariorussi

Differential Revision: D1125105
2014-01-17 01:43:23 -08:00
Jordan DeLong 19bd90df5e Use HNI return types in hhbbc's return type inference
We could do better for object types, but probably not worth
the effort yet until there's more conversion.

Reviewed By: @edwinsmith

Differential Revision: D1125101
2014-01-17 01:43:19 -08:00
nareshv 0acddafb3e Test runner improvements
- Added -i option to include only certain tests to be executed.
- Print the norepo reason next to skipped message for tests with .norepo
  file

Closes #1582

Reviewed By: @ptarjan

Differential Revision: D1131390

Pulled By: @scannell
2014-01-17 01:43:15 -08:00
Dmitry Panin 1445bce38d Fixed key collision in get_html_translation_table
in expression String::FromChar(i + em.basechar)
we casted "i + em.basechar" to char and therefore we got some
collisions of keys in translation table.
This diff uses more appropriate String::FromCStr as keys

Reviewed By: @ptarjan

Differential Revision: D1125958
2014-01-17 01:42:33 -08:00
Fred Emmott 0309f90d0f duplicate cell in rare loadCns path
- gets decrefed in frame_free_locals_helper_inl
- matches the behavior in the other non-error paths
- bsimmers is going to look at LookupCns - Uncounted is probably incorrect

Reviewed By: @swtaarrs

Differential Revision: D1130546
2014-01-17 01:42:28 -08:00
Owen Yamauchi 1c24482fa1 Delete unused exit edge support from DecRef instructions
These instructions never actually have an exit edge. Their flags in ir.h
indicate as much, as well as all of the places where they're gen()'ed.
All that code in code-gen was just cluttering up the place.

Reviewed By: @jdelong

Differential Revision: D1129774
2014-01-17 01:42:24 -08:00
Owen Yamauchi 5c6896ccd1 Implement LdFuncCached in ARM mode
This is the #3 punting opcode. The top two are Call and DecRefStack;
Call is in the works but proving to be rather nontrivial, and
DecRefStack is also going to be slightly tricky. This one, on the other
hand, is super simple.

Reviewed By: @edwinsmith

Differential Revision: D1129534
2014-01-17 01:40:54 -08:00
Joel Marcey 41f7f531fe Move the rest of the config to YAML
We started moving core config to YAML. Seems to work well. Let's move the rest over.

Reviewed By: @ptarjan

Differential Revision: D1130844
2014-01-17 01:40:54 -08:00
Guilherme Blanco fcba0889ad phpversion($extension) support
Implemented support for extension version check in phpversion()
following Zend compatibility. Updated all extensions on HHVM to match
versions on PECL and php-src master branch.

Closes #1506

Reviewed By: @JoelMarcey

Differential Revision: D1117334

Pulled By: @scannell
2014-01-17 01:40:54 -08:00
Fred Emmott e9b618ffe3 Reflection: use PreClass for method ordering and profiling info, Class for rest
Neither has sufficient data by itself

Reviewed By: @ptarjan

Differential Revision: D1129761
2014-01-17 01:40:54 -08:00
Paul Tarjan 3adf3d2994 fix test/run spew
Reviewed By: @swtaarrs

Differential Revision: D1129148
2014-01-17 01:40:54 -08:00
bsimmers 09c77a558f Change getNativeFunctionName to return a std::string
This is never used in perf-sensitive code and using std::string is
much cleaner and safer.

Reviewed By: @bertmaher

Differential Revision: D1126781
2014-01-17 01:40:53 -08:00
Bert Maher 8876047b0d Admin command for TC section addresses
It's nice to be able to ask the VM where the various TC
sections are.

Reviewed By: @ottoni

Differential Revision: D1128800
2014-01-17 01:40:53 -08:00
Guilherme Ottoni 8d55dfe117 Stop profiling translations at unconditional jumps
We should let the region selector decide whether or not to merge
profiling translations connected by an unconditional jump into a
longer trace.  So don't eagerly trace through unconditional jumps in
profiling mode.

Reviewed By: @edwinsmith

Differential Revision: D1128517
2014-01-17 01:40:53 -08:00
Alex Malyshev e2df82dc85 gd_info() had a misspelled string
Need "JPEG Support", not "JPG Support" to match Zend.

Reviewed By: @JoelMarcey

Differential Revision: D1128945
2014-01-17 01:40:53 -08:00
Herman Venter 40f82f5b6f Extract query parameter expressions from queries
Query expressions may contain sub expressions that can only be evaluated in the context of the query expression. These expressions effectively parameterize the query sent to the query engine (which typically runs out of process). Since query provider (which is distinct from the query engine) also runs in a separate context (albeit in the same thread) cannot evaluate these expressions in the right context, these expressions are replaced with references to compiler generated parameter variables in the expression tree sent to the query provider. When a query is evaluated, the values of the elided expressions are provided to the query method as additional arguments (the first argument being the expression tree). Note that the first elided expression is the receiver object for the query method call.

The extraction algorithm is a top down left to right traversal of the query AST that elides any expression which is not of a form that query processors are expected to be able to handle. The permitted forms are simple variables (that are bound to identifiers introduced by the query expression), constants, some unary operations, some binary operations, simple function calls and property accesses. If a sub expression of a permitted form is not itself permissible, it is replaced with a query parameter reference.

Reviewed By: @paroski

Differential Revision: D1124818
2014-01-17 01:40:53 -08:00
Paul Tarjan 0512e912e1 Don't use the Log.File in CLI
Right now we print both to stderr and the log file. Instead I think we should just ignore the option altogether in CLI mode. If we want to support that option we should support the INI setting http://www.php.net/manual/en/errorfunc.configuration.php#ini.error-log . The hdf option feels more like the apache log location than the php one.

Reviewed By: @jdelong

Differential Revision: D1085173
2014-01-17 01:40:53 -08:00
Joel Marcey 52de3ca164 Add Joomla CMS to the framework test runner
We have the Joomla framework, now let's add the CMS as well.

Reviewed By: @ptarjan

Differential Revision: D1128952
2014-01-17 01:40:52 -08:00
Emil Hesslow 470379e631 Fix for handling double backslashes
- The parser wasn't able to parse "as\\"

Reviewed By: @ptarjan

Differential Revision: D1128312
2014-01-17 01:40:52 -08:00
Emil Hesslow 7ee169a7eb New try to get in the ini parser stuff
- This rerevert D1116195 and D1116199
- It also fixes a problem when ini files contains junk. So instead of outputing junk on stdout it now fails parsing those files
- I also went re-run a bunch of tests that now passes.

Reviewed By: @ptarjan

Differential Revision: D1127923
2014-01-17 01:40:52 -08:00
Emil Hesslow 36eac72b6e Re-import ext/standard/tests/general_functions
tools/import_zend_test.py -z ~/php-src-PHP-5.5/ -o ext/standard/tests/general_functions

Reviewed By: @ptarjan

Differential Revision: D1127780
2014-01-17 01:40:52 -08:00
Kristaps Kaupe f2e996ade1 clang fixes
Fix a few clang warnings / errors.

Closes #1570

Reviewed By: @alexmalyshev

Differential Revision: D1128347

Pulled By: @scannell
2014-01-17 01:40:52 -08:00
Eugene Letuchy 53ffeac06d autoload: don't swallow fatals when autoloading
For a nonexistent class for which the autoloader map knows a file is
 present known, the autoload should behave the same way as if a
 require_once were made to that file and propagate any fatals that
 result. If on the other hand, the file for the class was unknown or
 the class was not successfully loaded (but there was no fatal), we
 continue to call the userspace-supplied faiure callback function.

Reviewed By: @ptarjan

Differential Revision: D1122740
2014-01-17 01:40:52 -08:00
Eugene Letuchy 4aeb3e599e collections: template vector::filter|map ...
... to allow versions with callbacks that take values only vs
 keys-and-values to reuse code.

Reviewed By: @jdelong

Differential Revision: D1127092
2014-01-17 01:40:52 -08:00
Eugene Letuchy 2097d7947d collections: share code between Map::->foo and ->fooWithKey
Hella templates for higher order collection functions:
 - map (+withKey)
 - filter (+withKey)
 - retain (+withKey)

Reviewed By: @jdelong

Differential Revision: D1126448
2014-01-17 01:40:51 -08:00
Eugene Letuchy 252f67b99b collections: add retain() and retainWithKey() to {Map|StableMap}
... the in-place mutating cousin of filter, retain takes a
 predicate callback for each entry in the map and uses the return
 value to determine whether to keep the element around.

 Deferring ##Vector## and ##Set## (easy).

Reviewed By: @jdelong

Differential Revision: D1121508
2014-01-17 01:40:51 -08:00
Fred Emmott 39a5e928aa Implement ReflectionParam::__toString
Used by Mockery to get type hint values. I'm submitting a diff to Mockery to make it use getTypehintText if available, but this should be implemented anyway.

Added two tests - one for confirming we're Zend-compatible (with .expect generated by Zend), the other for checking that non-null defaults work for basic-type typehints (which aren't supported by Zend)

Reviewed By: @ptarjan

Differential Revision: D1127714
2014-01-17 01:40:51 -08:00
javer 2091a8114d Fix memory leak in PDO::fetchAll()
Fix memory leak when fetching data using PDO::fetchAll().

Closes #1569

Reviewed By: @JoelMarcey

Differential Revision: D1128106

Pulled By: @scannell
2014-01-17 01:40:51 -08:00
Jordan DeLong 1c3aa1bf3d Abort when Repo::Repo fails instead of calling exit()
This can fail if we're out of file descriptors.  Calling exit
while other threads are still running leads to bad crashes in random
places, depending on the order that global destructors get run.
Instead let's always_assert with a message.

Reviewed By: @scannell

Differential Revision: D1125004
2014-01-17 01:40:51 -08:00
Antony Puckey ea14973c5e add getRemoteAddr to transport which defaults to empty string.
add getRemoteAddr to fastcgi transport to return the proper header. if no remoteAddr set it to the remoteHost ( libevent ) only set REMOTE_HOST if there is something in it as per php-src

Closes #1559

Reviewed By: @scannell

Differential Revision: D1126545

Pulled By: @ptarjan
2014-01-17 01:40:51 -08:00
Alex Malyshev b44e9c1889 Remove 'static' from function declared in a separate header
collectionDeepCopyBaseMap declared in ext_collections.h, but defined in
ext_collections.cpp. No idea why gcc doesn't catch it.

Reviewed By: @elgenie

Differential Revision: D1127006
2014-01-17 01:40:50 -08:00
bsimmers 60821e0166 Refactor TranslatorX64's CodeBlocks into a CodeCache module
I did this in preparation for something which ended up not working
out, but this could be worth keeping.

Reviewed By: @oyamauchi

Differential Revision: D1125965
2014-01-17 01:40:50 -08:00
Emil Hesslow 91c03c40a4 A bunch of different CSV fixes
- Do a bunch of small changes to make HHVM error when Zend does

Reviewed By: @ptarjan

Differential Revision: D970379
2014-01-17 01:40:50 -08:00
Sara Golemon 220a453220 Change docskel.php to use a local phpdoc checkout rather than svn.php.net
Runs MUCH faster this way.

Reviewed By: @ptarjan

Differential Revision: D1126413
2014-01-17 01:40:50 -08:00
Paul Tarjan 33dfe04716 time before sudo 2014-01-16 17:50:07 -08:00
Paul Tarjan b60492db9c See how long each step takes 2014-01-16 17:32:27 -08:00
ptarjan 5caac83428 remove folly files that were removed 2014-01-16 15:50:13 -08:00
ptarjan 08edc30657 update folly so there isn't two IOBuf.cpp files 2014-01-16 15:38:22 -08:00
mwilliams 7eb3262d3d Dont ignore errors from FT_Get_Glyph
"image" is left uninitialized if we do.

Reviewed By: @scannell

Differential Revision: D1126277
2014-01-14 11:42:01 -08:00
Joel Marcey 42795f08a5 Use Yaml for framework test runner configuration. Add github url to it too.
Yaml just seems cleaner and overall better for this type of configuration.

Decided to use a PHP YAML parser to avoid having to turn on EnableZendCompat explictly at the command line, particularly in open source.

So chose: https://github.com/mustangostang/spyc

Reviewed By: @ptarjan

Differential Revision: D1127123
2014-01-14 11:42:00 -08:00
Simon Welsh aa173f6ce8 Change ext/reflection from IDL to HNI
Change ext/reflection from IDL to HNI.

Also adds HNI support for HipHopSpecific through the
__HipHopSpecific user attribute. Code that wants to check for this
should use Func::getFuncInfo(mi) instead of Func::methInfo() (I only saw
Reflection using it).

Closes #1484

Reviewed By: @JoelMarcey

Differential Revision: D1124639

Pulled By: @scannell
2014-01-14 11:41:54 -08:00
Sean Cannella 9a35c755d3 Fix missing include in OSX
One more missing include on OSX in util/

Reviewed By: @alexmalyshev

Differential Revision: D1126910
2014-01-14 11:41:35 -08:00
Drew Paroski 7ded25076f Rename Set::difference() to Set::removeAll()
The difference method is confusingly named; its name does not imply that it
modifies the original Set. This diff renames "difference" to "removeAll" to
make it clearer. Eventually the difference() method will be removed after
all callers have been updated.

Reviewed By: @elgenie

Differential Revision: D1120227
2014-01-14 11:41:34 -08:00
Simon Welsh a464ad28e8 Convert ext/bzip2 to HNI
Adds error handling to the bzerr*() functions, allowing one of
the current bad tests to pass.

Closes #1547

Reviewed By: @sgolemon

Differential Revision: D1125459

Pulled By: @scannell
2014-01-14 11:41:27 -08:00
Antony Puckey f1fdcdd8ab Set HTTPS header appropriately in fastcgi
Check passed header values for HTTPS.

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

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

Closes #1546

Reviewed By: @ptarjan

Differential Revision: D1125440

Pulled By: @scannell
2014-01-13 15:58:06 -08:00
Simon Welsh 1914e07d21 Convert ext/phar to HNI
Closes #1548

Reviewed By: @sgolemon

Differential Revision: D1125469

Pulled By: @scannell
2014-01-13 15:57:58 -08:00
Edwin Smith 35a0406935 Rename hphp-value.cpp/h to typed-value
Since it defines class TypedValue

Reviewed By: @bertmaher

Differential Revision: D1125416
2014-01-13 15:20:10 -08:00
Paul Tarjan 9762e8fb56 fix fastcgi segfaults a better way
I think this is what julk originally wanted. He has a `m_keepConn` boolean that is set by `ConnectionFlags::KEEP_CONN` and if that is false, he calls this callback in both the error and the success case.

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

Closes #1522

Reviewed By: @scannell

Differential Revision: D1124995
2014-01-13 15:20:06 -08:00
Bert Maher 3b6d74078f Add FP, SP to hhirTracelet tracing
Adding this was pretty helpful for tracking down a stack
corruption bug.

Reviewed By: @swtaarrs

Differential Revision: D1125781
2014-01-13 15:20:03 -08:00
Jordan DeLong 73d02b43e9 Clean up a few TODOs relating to analyzing builtins in hhbbc
Some cases in class resolution that were happening for
builtins now won't (I checked).  They are mostly just "in principle"
possible now, and shouldn't really happen as far as I know aside from
one case: if you put "implements Foo" and Foo is actually a class.  I
can't get hphpc to mark AttrUnique on anything that would fail in
those places other than that.

Reviewed By: @edwinsmith

Differential Revision: D1125093
2014-01-13 15:19:56 -08:00
Jordan DeLong 2906fe6c98 Missing things in HHBBC representation: HNI types and isAsync
Now that HHBBC compiles systemlib, it needs to support
passing HNI-native function return types.  Also I apparently missed
isAsync only on the parse side (a newish test caught it).

I made native info a struct even though it only has one thing so
far---I think later we'll want the function pointer and a flag about
whether we can invoke it with constant arguments during compilation
time.

Reviewed By: @edwinsmith

Differential Revision: D1125080
2014-01-13 15:19:52 -08:00
Jordan DeLong d0a7b63495 Fix hhbbc issues with magic builtin interfaces (KeyedTraversable, etc)
After turning on hhbbc on systemlib, these interface names
are statically resolved, so it was assuming things like $x instanceof
Traversable is only true if $x is an object, and that an array
couldn't pass one of those parameter type hints.

Reviewed By: @dariorussi

Differential Revision: D1125061
2014-01-13 15:19:49 -08:00
Jordan DeLong d145f254e6 Use tbb::concurrent_hash_map for the Index dependency map
It was previously just a std::mutex around a
std::unordered_map, which seems to be a big source of contention after
putting systemlib is in the mix.

Reviewed By: @edwinsmith

Differential Revision: D1125048
2014-01-13 15:19:45 -08:00
Jordan DeLong a8111978fa Add support for "bumping" trace levels, use it to not trace systemlib in hhbbc
Use this so systemlib units will only be traced if the level
is higher than normal.

Reviewed By: @edwinsmith

Differential Revision: D1125039
2014-01-13 15:19:42 -08:00
Jordan DeLong cabe7cc3a7 Let systemlib units go through hhbbc
After the change to include systemlib in hphpc's static
analysis, I temporarily cut them out of whole_program in HHBBC.  The
problem was just that systemlib needs to end up merge only, but none
of hhbbc's output units are merge only.  Solve this with a special
case in emit.cpp for now.

This seems to make a ~2x slow down in how long the first analyze pass
takes hhbbc.  I think the reason is that now *tons* of things are
registering dependencies to common builtins that didn't use to
(e.g. idx)---it seems to be spending a lot of time on the single lock
there now.  (Will probably change it to tbb ...)

Reviewed By: @dariorussi

Differential Revision: D1125024
2014-01-13 15:19:39 -08:00
Jordan DeLong fd00ef394e Remove includes of util.h from .cpp files in hphp/util
Replace some uses with folly functions or boost.  I kept
string_vsnprintf in its own header for now.  We could probably move it
to folly/String.h (folly has stringPrintf and such, just no vararg
version), but on the other hand using va_list is not very encouraged
so maybe we should just leave it here for these legacy uses.

Reviewed By: @ptarjan

Differential Revision: D1124742
2014-01-13 15:19:32 -08:00
Jordan DeLong 7ccb4ef44f Remove includes of util.h from util/ headers
Few of them were using functions exported by util.h, they
were just using it to grab things like std::map.  Fixed some
downstream direct-includes.  Where trivial, used folly or boost
instead of Util::.

Reviewed By: @ptarjan

Differential Revision: D1124738
2014-01-13 15:19:28 -08:00
Jordan DeLong e26c7caf12 Move LogFileFlusher to its own header
Out of util.h.  For now, put drop_caches into
compatability.h, but that could easily turn into a blob-header also if
we're not careful.  Also made some style changes: make the virtual
private (virtual functions should rarely be protected), override
keyword, non-static member initializer, s/class/struct/.

Reviewed By: @edwinsmith

Differential Revision: D1124736
2014-01-13 15:19:25 -08:00
Jordan DeLong 63893eecb4 Remove s_file_mutex from util.cpp
Apparently dead.

Reviewed By: @bertmaher

Differential Revision: D1124735
2014-01-13 15:19:21 -08:00
Fred Emmott ee1e4278f0 HHVM MySQL corrections for bogus connections
Followup to https://github.com/facebook/hhvm/commit/76cab4dd67c3b20ad64927ada9bd71d0c4

Reviewed By: @ptarjan

Differential Revision: D1124285
2014-01-13 15:19:05 -08:00
bsimmers 624945ba03 Document TakeStack better, emit it in fewer situations
There was no obvious context for why it was being emitted in
simplifyLdStack, and we don't need to emit it if the new value is already from
a raw load.

Reviewed By: @edwinsmith

Differential Revision: D1114188
2014-01-13 15:19:01 -08:00
bsimmers 15a3e7b0d5 Print test commands when --verbose is present in test/run
Sometimes I want to see the command to run a test even if it's not
failing.

Reviewed By: @ptarjan

Differential Revision: D1114189
2014-01-13 15:18:57 -08:00
Bert Maher 3e52a380a2 Don't preemptively optimize away conditional jumps
There may be a stack adjustment needed.

Reviewed By: @ottoni

Differential Revision: D1124766
2014-01-13 15:18:50 -08:00
Owen Yamauchi ee2f2d18cb Implement codegen for LdLoc, IncRef, AssertType
LdLoc was the goal here (it was by far the most frequent punt). It's
really simple to implement, but it turned out that doing codegen for it
had a few cascading effects.

- We're now carrying registers across InterpOne calls, so switch to
  using cgCallHelper there.

- Using cgCallHelper for interp-one now requires cgCallHelper to support
  immediate arguments to helpers.

- IncRef and AssertType are now generated in such a way that we can't
  punt on them (even if you punt on them, they show up in
  hhbc-translator output).

Reviewed By: @edwinsmith

Differential Revision: D1120272
2014-01-13 10:11:11 -08:00
Daniel Sloof 42b810671f Fix valgrind issue in Github build
This fixes a JIT crash with VALGRIND=1.

Closes #1483

Reviewed By: @ptarjan

Differential Revision: D1117038

Pulled By: @scannell
2014-01-13 10:11:07 -08:00
Owen Yamauchi e8e49bd45e Implement the equivalent of CALL_OPCODE for ARM
This gets the native-call machinery working on ARM. I tried hard to
avoid copypasta, but unfortunately I think some amount of it is
inevitable.

I've only converted one of the simplest possible opcodes (ConvIntToStr)
for now, because I've knowingly punted on some stuff for now, most
notably arguments passed on the stack. This diff gets the basics in
place; in future diffs I'll convert more opcodes and iron out the issues
that arise.

- shuffleArgs(), like SpillStack, is another one of those annoying cases
  where most of the logic is platform-independent but there are several
  instruction-emitting calls buried deep down.

- I moved ArgDesc and ArgGroup into their own file, which was fairly
  smooth, especially now that PhysReg isn't x64-specific.

- I split out Immed from asm-x64.h because it's not x64-specific and
  ArgDesc depends on it.

Reviewed By: @edwinsmith

Differential Revision: D1121726
2014-01-13 10:11:04 -08:00
Paul Tarjan d9ca0e9feb disabled tests
Including the disabled tests for mongo so I can slowly enable them

Reviewed By: @paroski

Differential Revision: D979400
2014-01-13 10:10:59 -08:00
Paul Tarjan d037846e9e return false for bad preg_match
Closes #1347

Reviewed By: @JoelMarcey

Differential Revision: D1125164
2014-01-13 10:10:53 -08:00
Paul Tarjan fe8075951a remove StaticContentCache scan at startup
This was added many moons ago for static content perf. Basically we scanned whatever was on disk and made a map of all the file extensions we wanted to serve. We also allow files to be loaded from disk if `EnableStaticContentFromDisk` is set (which is default on).

Having this was bad for fastcgi since `SourceRoot` doesn't even make sense there.

Reviewed By: @jdelong

Differential Revision: D1124447
2014-01-13 10:10:48 -08:00
Paul Tarjan 0e20e402d9 Support mod_fastcgi
when using mod_fastcgi SCRIPT_NAME is the Action instead of the actual document you want
this commit uses PATH_TRANSLATED - DOCUMENT_ROOT

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

Reviewed By: @scannell

Differential Revision: D1114124
2014-01-13 10:10:44 -08:00
Dario Russi 2f7661c7a2 Call iterNext indirectly via table with heavily specialized helpers
Make iterNext and iterNextK super specialized helpers and invoke via indirect call instead of call to single helper

Reviewed By: @paroski

Differential Revision: D1084030
2014-01-13 10:10:39 -08:00
Dario Russi 00514c2f3b Remove APC stats
We are moving away from unused stats and start moving the stats to a more sensible infrastructure

Reviewed By: @jdelong

Differential Revision: D1110559
2014-01-13 10:10:34 -08:00
Sara Golemon ba8b4bf75a Implement Intl's DateFormatter class
This is actually a partial implementation because DateFormatter
is tightly bound to IntlCalendar (and its children).
Rather than make a massive hard-to-review diff,
I've implemented most of the DateFormater bits here
and will finish them off with a followup IntlCalendar diff.

Reviewed By: @ptarjan

Differential Revision: D1119360
2014-01-11 18:11:05 -08:00
Jordan DeLong 2abbadcec1 Don't restrict auto-alias names to the global namespace
In practice, this is a bit surprising behavior for code in
<?hh mode that also uses namespaces.

Reviewed By: @dariorussi

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

Closes #1347

Reviewed By: @markw65

Differential Revision: D1118365
2014-01-11 18:10:58 -08:00
Guilherme Ottoni f9c54437b2 Initialize all fields in NormalizedInstruction's constructor
I noticed various fields weren't being initialized there while
investigating a failure with the region JIT that seems related to
uninitialized memory.  This doesn't fix the failure, but seems worth
fixing anyway.

Reviewed By: @scannell

Differential Revision: D1123322
2014-01-11 18:10:51 -08:00
Jordan DeLong f6c9f5ebf6 Fix ReflectionFunction for closures with uninitialized static locals
ReflectionFunction::getStaticVariables returns both use vars
and closure static locals.  In zend, if there are name conflicts
between the two sets, things get weird (see task #3499967).  Also, in
zend, the value of the static is computed at closure allocation time,
which means calling this on an unevaluated closure gives the static's
value.  For us, the closure has to be invoked to execute a
StaticLocInit (prior to that, the 86static_foo property is
KindOfUninit, so we'd raise the notice @elynde hit).

This changes things to not raise when reading properties (only the
statics could be uninit), and strip the 86static_ prefix, which is
closer to what zend shows.  But we're still a bit different...

Reviewed By: @ptarjan

Differential Revision: D1120161
2014-01-11 18:10:48 -08:00
Simon Welsh d963fa2019 Handle unserializing a finfo object.
Zend currently throws:
Warning: finfo::file(): The invalid fileinfo object.
when trying to do something on an unserialised object. I consider this a
bug in Zend and there doesn't appear to be any tests covering that
behaviour.

This currently segfaults when deconstructing the unserialised object in
HHVM.

Closes #1527

Reviewed By: @ptarjan

Differential Revision: D1123430

Pulled By: @scannell
2014-01-11 18:10:44 -08:00
Patryk Pomykalski 4607dcf3a0 Mongodb hacks and test
For testing zend compatibility bugs.

Closes #1479

Reviewed By: @scannell

Differential Revision: D1117041

Pulled By: @ptarjan
2014-01-10 15:30:48 -08:00
Simon Welsh 8dfad03dfa Convert ext/bcmath to HNI
Converts ext/bcmath to HNI and adds support for scaling

Closes #1534

Reviewed By: @sgolemon

Differential Revision: D1123805

Pulled By: @scannell
2014-01-10 15:30:42 -08:00
Fred Emmott 3d9cfbea18 Fix rendering DateTime objects with offset TZs
- m_tz and m_time/tz_info are only relevant if m_time->zone_type == 3
 - if zone_type == 1, m_time->z is the only relevant thing
 - however, there can still be something completely irrelevant in tz_info - and format() was using this to find the offset
 - call offset() instead of asking the tz_info for it

Closes #1406

Reviewed By: @ptarjan

Differential Revision: D1120967
2014-01-10 15:22:41 -08:00
James Miller faaaa3b646 Fix namespace typedefs
Typedefs weren't being normalized, so checks that should have
worked, didn't.

Closes #1526

Reviewed By: @gabelevi

Differential Revision: D1123427

Pulled By: @scannell
2014-01-10 15:22:07 -08:00
Sara Golemon 9593a491df Use pkg-config to find freetype2 and clean up cmake module
This was doing clowny things including looking for a
header that we're not interested in using.

Closes #1380
2014-01-10 11:28:00 -08:00
Joseph Marrama 3cf3ba4497 Fix the build with the newer versions of libdwarf
This fixes an error with inconsistent types being used for the 'name'
parameter when registering a libdwarf callback against newer versions
of libdwarf (versions where the 'name' parameter is a const char*).

I verified that this compiles with the latest version of libdwarf.

Closes #1525

Reviewed By: @alexmalyshev

Differential Revision: D1122805

Pulled By: @scannell
2014-01-10 09:44:22 -08:00
Alex Malyshev 2cba5eda8e vm_decode_function doesn't verify parent has __call[Static]
When running call_user_func(array('C', 'parent::doesntExist')), Zend
runs C::__call if it exists and if the parent of C also has a
__call method. We were just checking C.

Closes #1471

Reviewed By: @ptarjan

Differential Revision: D1121885
2014-01-10 09:44:18 -08:00
Bert Maher 220245cb53 Miscellaneous cleanup of Array
This is basically just moving things around to make the API
more obvious and conform to our general coding style.

Reviewed By: @edwinsmith

Differential Revision: D1121410
2014-01-10 09:44:11 -08:00
Bert Maher d03733937f Remove Array::lval since it basically duplicates Array::lvalAt
Array::lval is almost identical; it just requires that
AccessFlags::Key be passed where string-integer keys can be created
(e.g., dynamic object properties).

Reviewed By: @markw65

Differential Revision: D1121403
2014-01-10 09:44:07 -08:00
Joel Marcey 383b963111 Move frameworks to master or develop branches
Move all the frameworks away from just specific git hashes to a master, develop (or equivalent) branch.

We start off with specific git hashes for the branch, but now there is a --latest and --reset option that gets the latest source for that branch and updates our new frameworks.json file with the latest hash.

I will do a --reset after this diff is approved to get new .expect files, etc.

Reviewed By: @ptarjan

Differential Revision: D1099135
2014-01-10 09:43:56 -08:00
Herman Venter 5922bf689d Add Code Model support for "require extends class" and "require implements interface" statements.
Added templates for two new statement types. Added serialization support. Added references to these types to the generator scripts.

Reviewed By: @elgenie

Differential Revision: D1118441
2014-01-10 09:43:49 -08:00
Alex Malyshev e08ed9c636 New round of clang-3.4 fixes
* clang doesn't like that a lambda without a return type can return
  either T or const T

* Template function was declared as non-static but defined as static

* Unused variables on findPassFP

Reviewed By: @jdelong

Differential Revision: D1121470
2014-01-09 11:22:15 -08:00
Sean Cannella c95c0c0210 Fix systemlib lint errors
Fix systemlib lint errors

Reviewed By: @markw65

Differential Revision: D1121699
2014-01-09 11:22:12 -08:00
Fred Emmott 76cab4dd67 Fix several MySQL segfaults when passing invalid connection IDs
Converts ID to pointer, wasn't checking the pointer was valid. Warnings are already raised by the lookup function.

These appear to all be functions that don't exist in Zend. Based behavior on existing code when returning bools, libmysql documentation when returning ints.

Closes #1297
Closes #1295
Closes #1296
Closes #1294

Reviewed By: @ptarjan

Differential Revision: D1120382
2014-01-09 11:22:08 -08:00
Fred Emmott 5bb1d221ff Fix xmlwriter_open_uri with no actual output
3 crashes fixed :)

- don't try and write 0 bytes. this makes no sense, and assert-fails for some URIs, including PlainFile
- Take ownership of m_uri
- libxml2 owns what was m_uri_output. Don't double-free.

Closes #1293

Reviewed By: @markw65

Differential Revision: D1119825
2014-01-09 11:22:02 -08:00
Antony Puckey 089a18e65f Populate fastcgi (transport-specific) headers
Added new function CopyServerParams in http-protocol which uses the new transport function getServerParams that adds any transport specific SERVER variables ie: FASTCGI_PARAMS to the _SERVER array

Closes #1437
Closes #1511

Reviewed By: @sgolemon

Differential Revision: D1120838

Pulled By: @scannell
2014-01-09 11:21:55 -08:00
Paul Tarjan d5659d79d2 don't rely on the COMPILE_DL_ thing to create the extension
thanks to the awesome @andralex we not longer have to hook into the thing that was inside an ifdef. This should fix lots of problems in the OSS build.

Basically we are now relying on the implicit copy constructor of `char *` to `ZendExtension` to register the extension.

Reviewed By: @sgolemon

Differential Revision: D1119700
2014-01-09 11:21:48 -08:00
Eugene Letuchy eeca955c97 collections: collapse base_vector.{h,cpp} into ext_collections
... this allows ExtCollectionObjectData to move out of
 object-data.h and resolves inconsistency between `BaseVector` and its
 cousins `BaseMap` and `BaseSet`. This diff is just a copy-paste: no
 changes were made in the added lines.

Reviewed By: @paroski

Differential Revision: D1120174
2014-01-09 11:21:45 -08:00
Edwin Smith 1bd963d868 Get rid of forEachTraceInst()
Each place we use it, we can do an iteration over reachable
blocks instead.

Reviewed By: @ottoni

Differential Revision: D1118394
2014-01-09 11:21:41 -08:00
Guilherme Ottoni 815939f497 Fix race in bind-call service request
The prologue we're binding to may change while the thread waits for the write lease, so read the latest value after acquiring the write lease.

Reviewed By: @scannell

Differential Revision: D1120488
2014-01-09 11:21:34 -08:00
Alex Malyshev 72ced07376 Replace ArrayIter* with ArrayIter in DOMNodeIterator
Don't know what the point was with using an ArrayIter* in the first
place. It was being deleted in c_DOMNodeIterator::sweep(), which would
try to decRefAndRelease() the ArrayData and hit an assert in
MemoryManager.

Reviewed By: @ptarjan

Differential Revision: D1109230
2014-01-09 11:21:23 -08:00
Fred Emmott 87670afba5 Allow passing a node to DOMDocument::saveHTML
Also, change behavior of saveHTML() to match formatting options of Zend (required for this test to pass)

Closes #1099

Reviewed By: @ptarjan

Differential Revision: D1119532
2014-01-09 11:21:13 -08:00
Eugene Letuchy 27580ef53f update NEWS for recent collections + trait changes
Reviewed By: @scannell

Differential Revision: D1120107
2014-01-09 11:21:09 -08:00
Eugene Letuchy 522cf50eb0 collections: remove default: case from switch(CollectionType)
... to take advantage of the compiler warnings for using `switch` on
 an enum and not covering all the cases. After this diff, adding new
 collection types should now be much easier, since the compiler should
 be able to ferret out (most of) the missing functionality.

Reviewed By: @jdelong

Differential Revision: D1120079
2014-01-09 11:21:05 -08:00
Eugene Letuchy 88f72709b8 collections: remove <Collection>::put(k,v) method ...
... which has been deprecated in favor of set(k,v) for some time

Reviewed By: @jdelong

Differential Revision: D1120043
2014-01-09 11:21:01 -08:00
Eugene Letuchy dd79d86fa9 collections: introduce ExtCollectionObjectData
... instead of making various collection constructors set the
 object data attributes.

Reviewed By: @jdelong

Differential Revision: D1120031
2014-01-09 11:20:58 -08:00
Eugene Letuchy 7759020ffd collections: support frozen<collection> == <collection>
It seems like equality comparison within subtypes of
 {Vector,Set,Map} should be supported.

Reviewed By: @paroski

Differential Revision: D1117505
2014-01-09 11:13:59 -08:00
Eugene Letuchy 044b1a86e8 collections: add HH\FrozenMap
- parser transform for "FrozenMap" in HH\FrozenMap
 - array iterator: work in terms of BaseMap
 - fix clone to work on FrozenSet and FrozenVector
 - add Collection::is{Map|Vector|Set}Type to types.h to facilitate
   uses of Base{Map|Vector|Set}:: functionality
 - create collectionInitSet to distinguish keyed sets in literals
   (usable for FrozenMap) from keyed sets in mutations
 - add support for Frozen collections to compiler's ExpressionList::setCollectionType

Reviewed By: @paroski

Differential Revision: D1119583
2014-01-09 11:13:56 -08:00
Eugene Letuchy d7b4ed0ece collections: make StableMap and Map ==-comparable (using unordered Map equality)
... by forwarding $collection == $object to collectionEquals,
 even when $collection and $object are not the exact same class.

 This might set up the ability to also make Collection and
 FrozenCollection inter-comparable.

Reviewed By: @paroski

Differential Revision: D1116829
2014-01-09 11:13:52 -08:00
Eugene Letuchy bcdfa62d62 idl files: use | instead of _ for namespaces
_ is the one and only non-alphanumeric character that can
 show up in valid PHP classnames. Switch to | (or another character)
 should allow idl files to define classes containing _'s. We haven't
 hit this issue yet, but only as the result of classes such as
 `PHP_Unserializable_Class` happening to be defined in systemlib.php
 as opposed to idl files

Reviewed By: @jdelong

Differential Revision: D1116701
2014-01-09 11:13:48 -08:00
Jordan DeLong 0d04e63200 Initial hhbbc support for inferring private property types
To implement this, the member instruction support needed to
be beefed up a fair bit, and support was needed for scheduling whole
classes at a time in whole program mode.  Checking it in disabled;
it's still a work in progress.

Reviewed By: @dariorussi

Differential Revision: D1115782
2014-01-09 11:13:44 -08:00
Paul Tarjan f52716b149 stop forcing some tests to bad
Our test infra has changed so much, lets see how these do

Reviewed By: @alexmalyshev

Differential Revision: D1116573
2014-01-09 11:13:40 -08:00
Paul Tarjan d6cff51de1 delete some functions
`function_exists` returning false is better than throwing

Closes #1512

Reviewed By: @scannell

Differential Revision: D1118722
2014-01-09 11:13:35 -08:00
Paul Tarjan 61a840dd92 remove v infront of version number
It looks weird for the nightlies. I currently have

  HipHop VM vnightly-2014-01-06 (rel)
  Compiler: heads/master-0-g708d7c03f394d0fe537021161f7b5eff5497edbe
  Repo schema: 4f6cadf45ef19259e958e2796ca894f6df7b6db9

Reviewed By: @jdelong

Differential Revision: D1117594
2014-01-09 11:13:32 -08:00
Guilherme Ottoni beefa9ae21 Fix race in bindJmp service request
There's was an old race in the bindJmp service request, where a
translation gets invalidated while we're trying to bind a jump to it.
This was exposed by the region JIT, but it can also happen in sandbox
mode.

Reviewed By: @markw65

Differential Revision: D1118962
2014-01-09 11:13:27 -08:00
Owen Yamauchi fa82eb96ea Fix ARM mode, part 3: disable PGO, SetL issues
PGO mode isn't implemented in ARM mode. It's nontrivial to implement,
and I want to get the contbuild re-enabled as soon as possible so I'm
just turning off PGO in ARM mode for now.

Additionally, a test was failing because of another interp-one problem
with SetL, where we were trying to box an Uncounted. I added the logic
that boxing an Uninit promotes to InitNull.

Reviewed By: @ottoni

Differential Revision: D1118876
2014-01-09 11:13:23 -08:00
Bert Maher 40a8c7016f AHot size is 0 if it is unallocated
Trying to get vm-tcspace from the admin port of a sandbox
server crashes the VM, because AHot isn't allocated.  Just return 0 in
this case.

Reviewed By: @ottoni

Differential Revision: D1118505
2014-01-09 11:13:19 -08:00
Ori Livneh e49a9f8230 Fix RDTSC calibration in ext_hotprofiler
Do a busy loop instead of usleep(5000), since usleep(5000)
causes the CPU to halt, giving meaningless results.

Originally submitted by Tim Starling as pull request #65 for
preinheimer/xhprof.

Closes #1488

Reviewed By: @mikemag

Differential Revision: D1118168

Pulled By: @scannell
2014-01-09 11:13:15 -08:00
Sean Cannella 82e7a6ddc9 Revert "Turn on Region JIT with profile-guided traces"
This reverts commit 18da4c1a84e4678fe7d83b8272b0449c7dbbdd74.

Reviewed By: @ptarjan

Differential Revision: D1118688
2014-01-09 11:13:10 -08:00
Sean Cannella 802e93f6d1 Merge pull request #1520 from alexmalyshev/master
Add CMake support for using clang++ as the C++ compiler
2014-01-08 17:33:11 -08:00
Alexander Malyshev 162f859e83 Add CMake support for using clang++ as the C++ compiler
There was a weird issue where CHECK_CXX_SOURCE_COMPILES wouldn't find
clock_gettime under clang++, switching to CHECK_FUNCTION_EXISTS worked
both under clang++ and g++ on Ubuntu 13.10
2014-01-08 17:09:39 -08:00
Sean Canella 86db8b953c Fix compatibility.cpp/.h for non-Linux
Reviewed By: @ptarjan

Differential Revision: D1119787
2014-01-07 18:22:14 -08:00
Owen Yamauchi 278fc10f2a Fix ARM mode, part 2: DCE
Broken by D1109820. When eliminating the branch from an unguarded load,
and it's the last instruction in its block, we have to add a jump after
it so that the last instruction in the block "isBlockEnd".

Reviewed By: @edwinsmith

Differential Revision: D1117803
2014-01-07 10:39:33 -08:00
Owen Yamauchi 1edcf08d41 Fix ARM mode part 1: spill-stack
This got broken by D1107251. Time to just "implement" ("copy") cgStore
from the x64 backend for real, instead of just a few paths that I think
are important.

Reviewed By: @edwinsmith

Differential Revision: D1117398
2014-01-07 10:39:33 -08:00
Sean Cannella b0fddcb4db Update NEWS for "Beastie Boys"
Update NEWS for release

Reviewed By: @edwinsmith

Differential Revision: D1118494
2014-01-07 10:39:33 -08:00
Scott MacVicar 95f96e7287 Fix libxml_disable_entity_loader()
This wasn't calling requestInit and setting the libxml handler no null.
So the first time an error came along it would reset the handler from
no-op to reading again.

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

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

Reviewed By: @jdelong

Differential Revision: D1116686
2014-01-07 10:39:32 -08:00
Paul Tarjan 8a2b1f7905 change 404 page to list paths
Many people are having trouble with the open source build getting a "Not Found" message and not knowing what to do from there. What do you think about showing the paths we tried? If you set `RuntimeOption::ErrorDocument404` then that will be used instead.

Reviewed By: @scannell

Differential Revision: D1109693
2014-01-07 10:39:32 -08:00
Joseph Marrama d629f22d6d Fixed the import script in ext_zend_compat
The import.php script called a non-existant method 'getSubpath'
on a FileInfo object. This commit fixes it so it now works. I verified
this works importing a new extension with multiple source files in
nested directories.

Closes #1509

Reviewed By: @ptarjan

Differential Revision: D1118180

Pulled By: @scannell
2014-01-07 10:39:32 -08:00
Jan Oravec a9a72ec46c Fix memory leak in Gen{Map,Vector}WaitHandle
The code assumed obj->clone() function to return an ObjectData* with
zero refcount, but the refcount is initialized to 1 by clone().

Let's attach() this already refcounted ObjectData* to the Object.

Reviewed By: @jdelong

Differential Revision: D1117583
2014-01-07 10:39:31 -08:00
Jordan DeLong bf8736b06c Replace mapInsertUnique with checks of .second
Reviewed By: @markw65

Differential Revision: D1116397
2014-01-07 10:39:31 -08:00
Jordan DeLong 74a78e4322 Move util/base.h to util/deprecated for remaining users
Most of the remaining stuff under hphp/compiler that gets it
from hphp/compiler/hphp.h

Reviewed By: @markw65

Differential Revision: D1115344
2014-01-07 10:39:31 -08:00
Jordan DeLong 6fb82db7ab Fatal on eval in RepoAuthoritative mode
Reviewed By: @ptarjan

Differential Revision: D1116204
2014-01-07 10:39:30 -08:00
Jordan DeLong 5db636ae70 Stop unit tests from doing eval() in repo mode
Most of these tests were only about eval, so they get norepo.
For FPassC, I pulled the eval case into its own test.  This is
separate from the diff to actual make eval fatal in RepoAuthoritative
in case we end up needing to revert that one ...

Reviewed By: @scannell

Differential Revision: D1116200
2014-01-07 10:39:30 -08:00
Elliot Lynde 29b90f97be Add ReflectionFunctionAbstract::isAsync
See attached task. We want to kill mockYield but need to be able tell if a function is async.

Reviewed By: @jano

Differential Revision: D1110027
2014-01-07 10:39:29 -08:00
Guilherme Ottoni 7e61c7e09c Turn on Region JIT with profile-guided traces
This diff turns on the initial version of the region JIT, with
"hottrace" regions.  To contain profiling and retranslation overheads,
the region JIT only targets functions marked as hot for now.  Compared
to the tracelet JIT, CPU time is in the noise according to perflab and
production testing. The region translator still has performance
issues, both known (e.g. guard relaxation is still disabled) and
unknown (translateRegion with tracelet regions still produces worse
code than translateTracelet, even with guard relaxation out of the
picture), and we'll continue to work on these.  Once we address these
issues, and try other ideas that the region JIT enables, we should
start seeing performance gains.  Nevertheless, we feel like the
current state is good enough to push the region JIT to release.  So,
if no one has any objection, we'd like to turn on the region JIT and
try to get it in the next release.

Reviewed By: @bertmaher

Differential Revision: D1116793
2014-01-07 10:39:29 -08:00
Kristaps Kaupe 01e6a895ea Libdwarf 20130729 (and later) support
Libdwarf 20130729 not only has changed Dwarf_Callback_Func_c
definition, but also adds two new functions dwarf_encode_leb128 and
dwarf_encode_signed_leb128. So, we can check for a presence of symbol in
a library, to distinguish between the old and new libdwarf.

Closes #1490

Reviewed By: @ptarjan

Differential Revision: D1117070

Pulled By: @scannell
2014-01-07 10:39:23 -08:00
Alexander 35c9784c6e PDOException should have a property "errorInfo"
Added two tests, one to verify the property exists, another one to
verify that the extra error info is actually set.

Closes #1412
Closes #1498

Reviewed By: @ptarjan

Differential Revision: D1117082

Pulled By: @scannell
2014-01-07 10:16:54 -08:00
Alexander a9a2737ac5 DateTime::createFromFormat() return FALSE on error
DateTime::createFromFormat() should return false on failure.

Closes #1495
Closes #1497

Reviewed By: @ptarjan

Differential Revision: D1117091

Pulled By: @scannell
2014-01-07 10:16:50 -08:00
Paul Tarjan 0b5fd84276 import tests that used to spew
this is so awesome that these work

Reviewed By: @scannell

Differential Revision: D1116552
2014-01-07 10:16:46 -08:00
Eugene Letuchy f773f87f7b check trait requirements during flattening
In repo mode, traits are flattened into the preClasses of using
 classes. After {D1111932}, there's no attempt made to import traits
 at class instantiation time (in repo mode), so the checks of trait
 requirements were not done. This diff patches up that hole, with the
 (small) limitation of not quite tracking the chain of
 trait-using-trait usages in error messages.

Reviewed By: @markw65

Differential Revision: D1116296
2014-01-07 10:16:39 -08:00
Eugene Letuchy a1d2e230bc skip trait import in repo mode
In repo mode, we've already done whole program analysis and
 imported trait methods, properties, and interfaces into the
 containing preclass. It doesn't make sense to redo that work when
 instantiating Class*s.

 The downstream effects of this change in repo mode are:
  - reflection should get (marginally) faster: no work for trait alias
    rules until the first time they're reflected upon
  - "used traits" reflection uses preclasses only, except for the case
    of object prop iteration, which continues to use the list of trait
    classes and works as before, but better (outside of repo mode,
    trait props are used ; in repo mode, trait props are ignored as
    redundant)
  - less work at warmup (doing nothing is faster than doing something
    for each trait method)
  - trait requirements are not enforced (left for followup diff)

Reviewed By: @markw65

Differential Revision: D1111932
2014-01-07 10:16:36 -08:00
Eugene Letuchy 9d7f144ac8 removed unnecessary subdirectories in test/slow/hh_namespace_migration
test/slow/hh_namespace_migration/redundant/redundant1.php is not useful

Reviewed By: @jdelong

Differential Revision: D1116835
2014-01-07 10:16:32 -08:00
Sean Cannella 270d5dfb57 Implement support for binary-number syntax
Implements support for binary number syntax ("0b10")

Closes #1425
Closes #1454

Reviewed By: @jdelong

Differential Revision: D1114405
2014-01-07 10:16:26 -08:00
Philippe Ajoux 5100923fea Add child argument to AsyncFunctionWaitHandle::onCreate callback.
An AsyncFunctionWaitHandle is only created when an object it `await`s is blocking. Currently these `await` events trigger the `onAwait()` callback. However, the first time an async function awaits is also the first time it actually gets created. Thus, the first actual `await` results in the `onCreate()` callback. This is fine, but right now there is no way to know what `WaitHandle` caused the creation of the AsyncFunctionWaitHandle. This useful to know.

For example, the current implementation of Teak does not, from my experimentation, get the call stack correct because it assumes that `asio_get_current()` is the parent when the `onCreate()` callback is called. However, this is not true. With the addition of the child that caused the creation, this can be fixed.

Reviewed By: @jano

Differential Revision: D1115761
2014-01-07 10:11:52 -08:00
Manish Bajaj e30a20175c Setting a boolean flag in getTyped
Timezone passed is null and doesn't match the class, so exception is thrown.

Reviewed By: @ptarjan

Differential Revision: D1113303
2014-01-07 10:11:48 -08:00
Bert Maher b7f6af03d8 Get rid of unnecessary includes of unit.h
It's pretty big, and it looks like a few of the places it's
included don't actually need it.

Reviewed By: @jdelong

Differential Revision: D1116020
2014-01-07 10:11:44 -08:00
mwilliams 3f867d5b27 Catch jmp/call to zero at translation time
Its much easier to catch such bugs at translation time,
than after we crash with $rip == 0.

Reviewed By: @edwinsmith

Differential Revision: D1114185
2014-01-07 10:11:40 -08:00
Bert Maher b62db208b7 Make expected output of setprofile-this more permissive with paths
This test fails when I run it in repo mode from hphp/, and it
just looks like the expectf pattern is too strict.

Reviewed By: @ptarjan

Differential Revision: D1116012
2014-01-07 10:11:33 -08:00
Sara Golemon a94542e548 Add -mcrc32 to CXX_FLAGS
Fixed build on gcc >= 4.8
2014-01-06 19:02:16 -08:00
Louis Kruger df44326811 Allow ReflectionFunction::getDefaultValue() on some builtin functions
Allow getDefaultValue() to be called on a ReflectionFunction in certain cases (where the default value can be deserialized from the IDL)

Reviewed By: @ptarjan

Differential Revision: D1116436
2014-01-06 11:42:48 -08:00
Behnam Esfahbod 2b6466e70e Use array_merge instead of plus operator
Use array_merge() instead of plus (`+`) operator. Also, add new test file for
the hMSet/hMGet pair of functions/commands.

Working on #3340180, we realized that we do not have any .expect file for the test files in `hphp/test/slow/ext_redis/` so noone is actually able to test the module (besides the fact that we don't have any automated slow-test working since no Redis server is setup during test).

Based on what I can see, most of the tests are working alright right now, but:

1. Redis commands HMSET/HMGET do not have any test files, and looks like HMGET is actually broken, besides the syntax issue mentioned in #3340180.

2. Most test files are looking for obvious cases, but not exceptional cases like non-existing lookup keys.

Reviewed By: @ptarjan

Differential Revision: D1108114
2014-01-06 11:42:48 -08:00
Edwin Smith b48b4e3217 Simplify B|NF flags to B.
NF means No Flag, I should have removed them when adding B.

Reviewed By: @jdelong

Differential Revision: D1116856
2014-01-06 11:42:47 -08:00
Edwin Smith 8c43d7d052 XLS: Use vectors instead of lists for ranges and use-positions
lists are inefficient for the way we use these, vectors are smaller and faster,
enable binary searching (future), and typically short anyway.

Reviewed By: @jdelong

Differential Revision: D1116766
2014-01-06 11:42:47 -08:00
Sara Golemon 3222f6fc15 Add missing includes for OSS build
The removal of base.h includes left some missing
headers scattered around, mostly in util.

Reviewed By: @jdelong

Differential Revision: D1117195
2014-01-06 11:42:36 -08:00
Jordan DeLong 74b1dccab4 Remove base.h includes from runtime/, fix up indirect dependencies
This probably just pushes a bit of it down to
runtime/base/types.h, but at least a few decent-sized includes are out
of every TU now (lexical_cast.hpp, iostream, boost/foreach, and
filesystem.hpp).  Haven't measured impact on build times if any.

Reviewed By: @edwinsmith

Differential Revision: D1115343
2014-01-06 11:42:22 -08:00
Jordan DeLong 0a0712262e Remove #includes of base.h from the headers in util/
And try to fix downstream indirect dependencies to include
what they use (plenty of indirect includes still missing, though).
Most TU's still get this all via the complex-types.h stuff.

Reviewed By: @dariorussi

Differential Revision: D1115342
2014-01-06 11:42:21 -08:00
Jordan DeLong de03fa1f5d Move util/json.h to compiler
It references compiler-specific types like AnalysisResult.
Replace the one live use of the JSON::Escape function from this header
in the runtime with folly call; other use is about to be removed in
another diff from dario.

Reviewed By: @dariorussi

Differential Revision: D1115340
2014-01-06 11:42:20 -08:00
Jordan DeLong 5ba020d800 Move small function objects to their own header.
Reviewed By: @edwinsmith

Differential Revision: D1114045
2014-01-06 11:42:20 -08:00
Jordan DeLong e1631211ad Remove typedef unsigned char uchar
Reviewed By: @edwinsmith

Differential Revision: D1114044
2014-01-06 11:42:19 -08:00
Jordan DeLong 8bbbe52328 Remove dependencies on util/base.h for map helpers
Just use count() for the fooContains ones, mapInsert didn't
do anything, move mapInsertUnique to its only user, use folly's
MapUtil.h versions instead for the other ones.

Reviewed By: @markw65

Differential Revision: D1114043
2014-01-06 11:42:19 -08:00
Jordan DeLong e7f6aa501c Remove some unused, single-use, or excessively trivial helpers
A couple of these are only trivial-seeming because now we
have range-based for or lambdas.

Reviewed By: @markw65

Differential Revision: D1114042
2014-01-06 11:42:18 -08:00
Jordan DeLong 44e0efe2a8 Move hphpiCompat to its only remaining use site
Reviewed By: @markw65

Differential Revision: D1114041
2014-01-06 11:42:18 -08:00
Jordan DeLong 71ae9fbb30 Move safe_cast out into its own header
Reviewed By: @dariorussi

Differential Revision: D1114040
2014-01-06 11:42:18 -08:00
Jordan DeLong 6b411c6072 Remove a few typedefs for stl combinations from util/base.h
Reviewed By: @dariorussi

Differential Revision: D1114039
2014-01-06 11:42:17 -08:00
Jordan DeLong 0418b65a11 Delete some shared_ptr<FILE> stuff
FilePtr seemed strange to define in base.h.  Turned out only
process.cpp uses it.  FileReader at first seemed to be freeing FILE*'s
with delete, but it turned out the instance version of it was dead
code, and the class was really just a function.  The other site was
supposed to be a scope guard.

Reviewed By: @dariorussi

Differential Revision: D1114038
2014-01-06 11:42:17 -08:00
Jordan DeLong 3b1120f190 Deprecate DECLARE_BOOST_TYPES, remove uses outside hphp/compiler
Reviewed By: @markw65

Differential Revision: D1114037
2014-01-06 11:42:16 -08:00
Jordan DeLong 758dbc6cbb Move the hphp_hash_* typedefs to their own header
Reviewed By: @ptarjan

Differential Revision: D1114036
2014-01-06 11:42:16 -08:00
Jordan DeLong e44fab1e77 Don't specialize std::hash for char* in base.h
At least one call site may have been using the custom hash
inadvertently with AtomicHashMap but I preserved the behavior.

It seems like this is a little too dangerous, too.  If any translation
unit in the program uses std::hash<char*> without first including
base.h, we have undefined behavior.  Since we don't control a lot of
the code linked into our binary this seems like a bad idea.

(Plus it's just nicer to be explicit about whether a char* key is
being treated as just a pointer or as a C-style string at a use site
so you can tell what is going on.)

Reviewed By: @edwinsmith

Differential Revision: D1114035
2014-01-06 11:42:15 -08:00
Jordan DeLong 1050dfe523 Don't include via datatype.h or via hphp-value.h
Right now, through this route (among others), nearly every
translation unit in the runtime includes
boost/interprocess/sync/interprocess_upgradable_mutex.hpp ... just in
case you might want to use it.

This diff doesn't solve the problem, it's just a start (all the other
sub-headers for complex-types.h do this same stuff right now).

Reviewed By: @edwinsmith

Differential Revision: D1114034
2014-01-06 11:42:15 -08:00
Edwin Smith ff2d01de93 Prepare for enabling XLS register allocator.
Disable SIMD registers when using packed_tv.

Reviewed By: @jdelong

Differential Revision: D1102996
2014-01-06 11:42:15 -08:00
Edwin Smith 6d10ad646a JmpSwitchDest has no destination tmp.
Fix ir.specification

Reviewed By: @jdelong

Differential Revision: D1116836
2014-01-06 11:42:14 -08:00
Sara Golemon 5454d1e028 Update folly 2014-01-06 11:42:14 -08:00
Sara Golemon 708d7c03f3 Move ext/sockets constants from constants.idl.json to ext_sockets.cpp
Organizationally makes more sense.

Also allows us to set the constant values based on the system defines
rather than hard-coded posix values, and make some conditionally
available constants conditional.

I went through php-src/ext/sockets/sockets.c to match PHP:

Newly added sockets constants:
MSG_CTRUNC
MSG_TRUNC
IP_MULTICAST_IF
IP_MULTICAST_TTL
IP_MULTICAST_LOOP
IPV6_MULTICAST_IF
IPV6_MULTICAST_HOPS
IPV6_MULTICAST_LOOP
IPPROTO_IP
IPPROTO_IPV6
IPV6_UNICAST_HOPS

Existing constants made conditional:
MSG_EOR
MSG_EOF

Newly added conditional constants:
MSG_CONFIRM
MSG_ERRQUEUE
MSG_NOSIGNAL
MSG_DONTWAIT
MSG_MORE
MSG_WAITFORONE
MSG_CMSG_CLOEXEC
SO_REUSEPORT
SO_FAMILY
SO_BINDTODEVICE
TCP_NODELAY

Note: I left out the MCAST_* constants in ext/sockets because
we don't actually have the code to do anything with them.
We can add those in a separate diff.

Reviewed By: @jdelong

Differential Revision: D1116722
2014-01-05 08:59:36 -08:00
Eugene Letuchy b368db8f3e collections: centralize equality in BaseMap
We'll most likely stay with Map's equality semantics for ==,
 but StableMap's equality semantics will likely have a place as a
 user-PHP accessible method on collections.

Reviewed By: @jdelong

Differential Revision: D1116700
2014-01-05 08:59:33 -08:00
Eugene Letuchy 80cffcc72f collections: introduce BaseMap superclass for Map and StableMap
This diff ensures that Map and StableMap have the same
 storage implementation in preparation for:

  - StableMap going away (except, perhaps, for its equality semantics)
  - FrozenMap coming into existence

 Specifically, this diff:

  - introduces a BaseMap superclass
  - makes c_Map inherit from BaseMap
    - renames c_Map::t_xyz to BaseMap::php_xyz
    - make c_Map::t_xyz a thin wrapper over BaseMap::php_xyz
  - makes c_StableMap inherit from BaseMap
    - removes vast majority of old implementation
    - adds c_StableMap::t_xyz as a thin wrapper over BaseMap::php_xyz
    - keeps c_StableMap::equals behavior (order mattering)
    - keeps unserialization behavior (serialize to 'StableMap' class)
  - gets rid of StableMapIterator in favor of a transformed MapIterator that works with any BaseMap

 Apologies to reviewers: this started out as a diff series with
 StableMap extends Map to verify limited number of test failures, and
 git code move detecting wasn't quite good enough to make commit
 rewriting less painful.

Reviewed By: @jdelong

Differential Revision: D1113840
2014-01-05 08:59:30 -08:00
Eugene Letuchy 3f304a7aee collections: macrofy materialization and magic-method declarations ...
... as a direct counterpart to similar macros in the .cpp file

Reviewed By: @jdelong

Differential Revision: D1116696
2014-01-05 08:59:26 -08:00
Edwin Smith 5d2da8095c Fix broken cycle detection in doRegMoves()
It failed to detect a cycle if the path to the cycle started
from a leaf node that wasn't in the cycle.  This diff goes
back to the old algorithm, adapted for PhysReg and PhysReg::Map,
and also goes back to fixed-length arrays to avoid allocations.

Reviewed By: @jdelong

Differential Revision: D1116541
2014-01-05 08:59:23 -08:00
Eugene Letuchy 3b7e172be5 collections: support sorting of Maps
Now that Maps retain insertion order and have an internal
 representation similar to arrays, there's no reason not to implement
 sorting on them. The implementations are largely copy-pasta

Reviewed By: @jdelong

Differential Revision: D1113839
2014-01-05 08:55:50 -08:00
Paul Tarjan 0b8bec7835 import segfaulting tests
The test runner is now much more resiliant than it used to be, so it can endure a segfault or two. Having the tests is better than not.

Reviewed By: @jdelong

Differential Revision: D1116517
2014-01-05 08:55:49 -08:00
Liu Yang bdeab11496 Adding ENT_IGNORE
ENT_IGNORE is added, which will silently discard invalid code unit sequences instead of returning an empty string.
I changed relevant QuoteStyle matching to flag bitmask checking. I kept our previous QuoteStyle method since it's used in many other places.

Reviewed By: @ptarjan

Differential Revision: D1116336
2014-01-05 08:55:49 -08:00
Paul Tarjan 75922a20ca import many tests that used to hang forever
You have no idea how happy this makes me. We are down to 5 perma-hanging tests.

Reviewed By: @JoelMarcey

Differential Revision: D1116535
2014-01-05 08:55:49 -08:00
Paul Tarjan dd4ddd5ee0 re-enable ftp_chmod_basic
The other ftp tests have ben fine since I fixed the port choosing issue upstream.

Reviewed By: @jdelong

Differential Revision: D1116504
2014-01-05 08:55:48 -08:00
Jordan DeLong c3a9cea640 Fix bad_ini_quotes test
Oops.

Reviewed By: @ptarjan

Differential Revision: D1116602
2014-01-05 08:55:48 -08:00
Eugene Letuchy 11bd030e66 emit fatal bytecodes from errors found during trait flattening
An overtly literal person might suspect that ##Compiler::Error## would
involve a compiler spitting out an error message reflected in the
ensuing code. Instead, it turns out that it records the message in a
separate area and blithely **continues onwards** as if the error never
occurred.

In repo mode, traits are imported in the compiler as opposed to at
Class initiation time. My contention is that any fatals/errors
discored during trait flattening should be available at runtime when
an attempt is made to load the file.

This diff introduces the notion of an `AnalysisTimeFatal` to the
compiler and ensures that this fatal propagates (with [analysis] added
to the fatal message). It also ensures that trait flattening and
non-repo trait import share the same error messages, which should make
it possible to eventually stop producing ##.expectf## files that
contain the almost entirely inscrutable ##HPHP Fatal Error: %s##.

Reviewed By: @markw65

Differential Revision: D1112629
2014-01-05 08:55:47 -08:00
Jordan DeLong ac8474cbe9 Add a unit test that aborts with recent ini changes
So that we can test this case before adding it back.

Reviewed By: @ptarjan

Differential Revision: D1116203
2014-01-05 08:55:47 -08:00
Jordan DeLong 8ebc0e6702 Revert "Fixes to parse_ini_(file|string)"
This reverts commit 0d694bcf6c0fa7aa4c15f166d0732ea37c5566d8.
It's causing parse_ini_string to sometimes hit assertions in
StringData::setSize, and behavior issues on the intern tier.  The fix
wasn't completely obvious and there's an open diff relating to
relevant cases (escaped double quotes), so let's just revert until it
can be looked at by emil.

Reviewed By: @markw65

Differential Revision: D1116199
2014-01-05 08:55:47 -08:00
Jordan DeLong 5f2d1b25c4 Revert "INI parser fixes for OSS"
This is required to revert "Fixes to parse_ini_(file|string)"
cleanly.

Reviewed By: @markw65

Differential Revision: D1116195
2014-01-05 08:55:46 -08:00
Paul Tarjan 4620d7a132 delete FastCGIConnection object
This was a leak appearing in @apuckey's valgrind dump. @simpkins said the object should delete itself since either the success or error callbacks will for sure be called for each connection.

Closes #1252

Reviewed By: @scannell

Differential Revision: D1115399
2014-01-05 08:55:01 -08:00
Paul Tarjan 186c74e761 enable TestFastCGIProtocol
The Server tests were the flakey ones, but both got disabled. Lets leave the unit tests around so I don't break stuff.

Reviewed By: @scannell

Differential Revision: D1115879
2014-01-04 12:53:54 -08:00
Paul Tarjan 5fd5b01be3 fixup isDefaultValueAvailable() and isOptional() for builtins
The `Func*` doesn't keep around information about defaults from the IDL so I switched to using the `ClassInfo`. That in turn showed me there was some logic in there that wasn't being used by anything anymore (as there are no values in the IDL's with foo::bar() in them except for `TimeStamp::Current` which is clearly destined for C++). Ripping that out allowed me to kill a helper functions.

I then did the real work that I wanted and marked parameters with `internal` and don't say there is a default value for those and throw the same exception that zend does.

Reviewed By: @markw65

Differential Revision: D1054845
2014-01-04 12:53:51 -08:00
Zach Wasserman d302ddd725 Fixed xmlwriter null prefix bug
HPHP was inconsistent with Zend PHP in its rendering of the XMLWriter
startElementNS method. This diff brings better consistency with Zend for the
case of null prefix string or empty prefix string.

Reviewed By: @ptarjan

Differential Revision: D1114272
2014-01-04 12:53:47 -08:00
Eugene Letuchy 5cf6d04a90 add interfaces to whole program (repo mode) trait flattening
anietoro added the 'trait T implements I' syntax, but not support for it in repo mode.

Reviewed By: @markw65

Differential Revision: D1111927
2014-01-04 12:53:44 -08:00
Diego Giagio 5e8bc5a19e Add more stream_wrapper functions used in Drupal
According to some users, Drupal 7 uses public:// and
temporary:// to store and move files around by using stream_wrappers.
Some functions of stream_wrappers weren't implemented. This patch adds
the following missing functions:

unlink
rename
mkdir (recursive or not)
rmdir

Closes #1474

Reviewed By: @ptarjan

Differential Revision: D1115507

Pulled By: @scannell
2014-01-04 12:53:40 -08:00
Antony Puckey f0c74f27df Allow transport to override SERVER_ headers
Uses the following headers from the transport (for fastcgi)
instead of the local config if they exist:

SERVER_NAME
SERVER_ADDR
SERVER_PORT

Closes #1445

Reviewed By: @ptarjan

Differential Revision: D1114969

Pulled By: @scannell
2014-01-04 12:53:36 -08:00
Elliot Lynde 7236226b4a See if HasGeneratorAsBody is used
Sean thought maybe not since it's not clear where it's set

Reviewed By: @jano

Differential Revision: D1113304
2014-01-04 12:53:33 -08:00
Bert Maher 57e32a8985 Put demangled symbols in perf map
It's easier to read perf output with demangled symbols

Reviewed By: @markw65

Differential Revision: D1114722
2014-01-04 12:53:29 -08:00
Bert Maher 05a30a5ce4 Move isConvIntOrPtrToBool close to its one use
It's a single use function so make it a lambda close to the use

Reviewed By: @jdelong

Differential Revision: D1114902
2014-01-04 12:53:25 -08:00
Edwin Smith a6cebd362c Remove dead code in checkTmpsSpanningCalls()
Left over from the recent rewrite.

Reviewed By: @scannell

Differential Revision: D1115439
2014-01-04 12:53:21 -08:00
Dario Russi d8313742e1 Allow indirect calls via emitCall with CppCall support
Extend CppCall to support a call indirect (via register) style and implement a call to a Variant destructor via the indirect call instead of helper

Reviewed By: @ottoni

Differential Revision: D1090464
2014-01-04 12:53:18 -08:00
Daniel Sloof fe62948b58 fix stream_get_contents without specified offset
File does its own internal buffering and uses m_readpos, m_writepos,
m_position for the purpose of keeping track of file offsets. This means
that current (PHP) position is not in sync with the underlying file
descriptor (m_fd).

This works fine, were it not for the fact that ext_stream calls directly
into pure virtual method readImpl that generally lives in PlainFile
and works directly on the file descriptor that might contain an
invalid (buffered-ahead) position.

This pull request does several things:
- Remove default value 0 for File::read(int64_t length), since that
  implementation returns earlier for 0 values anyway.
- Implement an overloaded method File::read() that reads the remainder
  of the file (until EOF) by using proper File::m_* properties.
- Make ext_stream call into File::read instead of PlainFile::readImpl.

Closes #1333

Reviewed By: @ptarjan

Differential Revision: D1091550

Pulled By: @scannell
2014-01-04 12:53:14 -08:00
Benjamin Zikarsky bd636b9f39 Fixes "false" hashbang interpretation
- Lexer now only interprets "#!" as a line-1-hashbang
- Added tests for a leading line with both "#test" and a real hash-bang
like "#!hashbang"

Closes #1396
Closes #1465

Reviewed By: @ptarjan

Differential Revision: D1114361

Pulled By: @scannell
2014-01-04 12:53:13 -08:00
Guilherme Ottoni b8ca92a08c Don't emit type predictions in TransOptimize mode
I noticed that the region translator was emitting type checks for
values that were both predicted (via the interpreter type profiler)
and inferred (via the front-end).  This is a result of the type
profiler annotating the output of the instructions while the front-end
annotates the instruction inputs.  Therefore, we ended up generating a
CheckStk instruction and then an AssertStk instruction.  The AssertStk
instruction is then simplified away (since it's asserting a type that
is already known due to the previous CheckStk), and the CheckStk
remains. The tracelet translator avoids this problem by looking ahead
in the chain of NormalizedInstructions (via getOutputUsage) to
determine that the prediction is unecessary.

I PGO mode, we don't really need the values coming from the
interpreter type profiler.  TransProfile translations end whenever
there's a side-exit, and type predictions incur side-exits.  And when
we stitch multiple TransProfile translations together to for a
hottrace region (in TransOptimize mode), the guard for the top of the
stack essentially does the role of type prediction.  And, if the value
is also inferred, then the guard is omitted and the AssertStk is
emitted and not eliminated (since there's not previous CheckStk).

Note that this diff only solves the problem for regions formed via PGO
(hottrace only).  Fixing the problem for other region selectors is
going to be more involved and I tasked to do it separately.

Reviewed By: @swtaarrs

Differential Revision: D1112059
2014-01-02 20:05:07 -08:00
Sean Cannella 142c8dc839 Fix spurious conversion notice in method_exists
Arrays can't possibly pass a method/class check as they convert
to array (a reserved keyword) so don't bother toString-ing in that case.

Closes #1475

Reviewed By: @ptarjan

Differential Revision: D1114192
2014-01-02 20:05:04 -08:00
javer efaf782ccc Fix memory leak in pdo_parse_params
Fixed memory leak after executing PDOStatement::execute() with bound parameters. Also removed unnecessary copying of result query string.

Test case (I don't know whether it can be tested with Travis because it requires MySQL connection):

<?php
$pdo = new PDO('mysql:dbname=test;host=localhost', 'root', '');
$data = str_repeat('a', 1000000);

for ($n = 0; $n < 50; $n++) {
    $stmt = $pdo->prepare('SELECT :data = 1');
    $stmt->bindValue(':data', $data);
    $stmt->execute();
    $stmt = null;
    echo sprintf("%dM\n", memory_get_usage(true) / 1048576);
}

Closes #1459

Reviewed By: @ptarjan

Differential Revision: D1113187

Pulled By: @scannell
2014-01-02 20:05:01 -08:00
javer a02ae44cd4 apc_inc/dec should return false on failure
Return false instead of 0 when failure occured while calling
apc_inc or apc_dec.

Closes #1472
Closes #1473

Reviewed By: @dariorussi

Differential Revision: D1114169

Pulled By: @scannell
2014-01-02 20:04:57 -08:00
Jordan DeLong 2c7fcd7ba3 If HttpServer can't bind ports, go directly to _Exit(1)
Apparently this code was just returning while leaving a bunch
of threads running, which is pretty bad.

Reviewed By: @markw65

Differential Revision: D1111881
2014-01-02 20:04:54 -08:00
Dominic Luechinger 971a4c35cd In FastCGI the server address could not be set
Due to a bug in the FastCGI server the start up of the server with
a specific IP address was not possible.
Example:
hhvm --config /etc/hhvm/server.hdf -m server -vServer.Type=fastcgi -vServer.IP=127.0.0.1 -vServer.Port=9100

Before bugfix:

netstat -tulpen|grep 9100
> tcp6       0      0 :::9100                 :::*                    LISTEN
After bugfix:

netstat -tulpen|grep 9100
> tcp        0      0 127.0.0.1:9100          0.0.0.0:*               LISTEN

Closes #1467

Reviewed By: @ptarjan

Differential Revision: D1114159

Pulled By: @scannell
2014-01-02 20:04:51 -08:00
Brandon Wamboldt 1161d81be3 Fix preg_quote not escaping dashes
Fix preg_quote not escaping dashes

Closes #1440
Closes #1441

Reviewed By: @elgenie

Differential Revision: D1111976

Pulled By: @scannell
2014-01-02 20:04:47 -08:00
Jim Radford b87deae51e VirtualHost.<name>.Pattern matches host not paths
This allows Patterns with a leading ^ to match.

Pattern ^www.example.com$

Closes #1463

Reviewed By: @markw65

Differential Revision: D1114114

Pulled By: @scannell
2014-01-02 20:04:44 -08:00
Edwin Smith 212f4a726d Remove TakeStack instructions after optimizeRefcounts()
They are essentially Nops, inserted to preserve information
from the simplify pass.  They aren't needed anymore after
refcount optimizations; convert them to Nop so dce cleans
them up.

Reviewed By: @swtaarrs

Differential Revision: D1114262
2014-01-02 20:04:40 -08:00
Edwin Smith d5a96369ac Strengthen checkTmpsSpanningCalls()
Replace preorder walk over dom tree with bottom-up postorder walk,
and merge state along edges.  This catches more violations.
Also, add ContEnter, ignore TakeStack, and StkPtr-typed tmps.

Reviewed By: @swtaarrs

Differential Revision: D1114191
2014-01-02 20:04:37 -08:00
Jordan DeLong 88389ab7d8 Minor refactor of how non-constant hhbbc options are set
The only option that's actually runtime settable right now is
the list of fb_intercept-able functions.  I'm going to want more of
these soon, but the way it was set up was slightly annoying.

This isn't great still---it just moves the place we propagate options
closer to compiler_main.  We don't want these options to actually
exist in Compiler::Option because otherwise we'd have to merge
libhhbbc.a with libhphp_analysis.a, and they don't really fit in
RuntimeOption either.  (Eventually I'd like to just have another
main() for hhbbc with its own option parser---this would also make it
easy to repeatedly run hhbbc on a repo while developing, without
redoing the rest of the production build.)

Reviewed By: @dariorussi

Differential Revision: D1113886
2014-01-02 20:04:33 -08:00
Bert Maher b0d11cf284 Use PRId64 instead of ld for uint64_t
Building on OSX warns about ld

Reviewed By: @edwinsmith

Differential Revision: D1109785
2014-01-02 20:04:30 -08:00
Bert Maher 9852392fe1 Don't redefine ENABLE_GD_TTF if defined
Squashes a warning when building on OSX

Reviewed By: @ptarjan

Differential Revision: D1109786
2014-01-02 20:04:26 -08:00
mwilliams 9a29b5d027 Slightly better code gen in a couple of places
I noticed while debugging a production crash that

  testq -1, MemRef

is 3 bytes bigger than

  cmpq 0, MemRef

and is typically interchangable.

While looking for test*s to change, I noticed that we always
do ConvObjToBool, even when we know the Class statically, and know
that the result is going to be true. So added a case to the simplifier.

Reviewed By: @elgenie

Differential Revision: D1109374
2014-01-02 20:04:23 -08:00
Jordan DeLong a78e186d54 Fix a reference counting bug in emitFPushCufOp
If you have a non-persistent class in this code path, we
generate code that fails the reference count validator.  It IncRefs
the $this pointer before generating the conditional branch to the exit
trace for the class not being defined.

Reviewed By: @edwinsmith

Differential Revision: D1113826
2014-01-02 20:04:19 -08:00
Eugene Letuchy a836bb0f86 boost::{enable|disable}_if_c => std::enable_if
apparently std::enable_if is the new C++11 hotness

Reviewed By: @alexmalyshev

Differential Revision: D1112652
2014-01-02 20:04:09 -08:00
Chengyan Fu 7c29a08796 revert some unesessary change in D1110769
I revert some change will block my task in coldstage which
be brought into the master by arc land. This diff is to revert that
and local changes.

Reviewed By: @ptarjan

Differential Revision: D1113815
2014-01-02 20:04:05 -08:00
Chengyan Fu e0de978c02 Fix Curl Upload Failure
hhvm will callback the compiled php read function to parse the
file to be uploaded. During this process, a file instead of a file
descriptor id should be passed into the hphp VM.
The error is caused by sending file->fb() rather than file itself into
the callback function. The actual hphp fread library try to make a dummy
resource after receiving an integer when a ResourceData is excepted.
The dummy resource file then causes a bunch of error which ends up in
the "read function returned funny value".

Reviewed By: @ptarjan

Differential Revision: D1110769
2014-01-02 20:04:02 -08:00
Sara Golemon 93d0137393 Prune dead code from compiler/option
Came across this option while cleaning up HPHP_HOME,
looks to be completely dead.

Reviewed By: @ptarjan

Differential Revision: D1111937
2014-01-02 20:03:58 -08:00
Sean Cannella 78929051ef hhprof should only collect profiles when profiling
HHProf should only collect profiles when profiling instead of
proactively and then only reporting when profiling as this incurs a huge
amount of runtime overhead by default with the runtime option enabled.

Reviewed By: @dariorussi

Differential Revision: D1112865
2014-01-02 20:03:54 -08:00
Brandon Wamboldt bf73fae1f2 Already declared constants should cause a notice
Zend will throw a PHP Notice if you try to re-declare a
constant that has already been declared, but HipHop was throwing a PHP
Warning.

Closes #1456

Reviewed By: @jdelong

Differential Revision: D1112973

Pulled By: @scannell
2014-01-02 20:03:50 -08:00
Sara Golemon 39416ccbdc Run a double-quoted json scalar string through the parser
The non-JSON fallback for quoted string values
should still respect JSON string encoding rules like
unicode, and printf-style escape sequences.

Reviewed By: @scannell

Differential Revision: D1112801
2013-12-30 12:05:06 -08:00
Sara Golemon 370b2b8cb2 Clean json_last_error() when parsing non-objects
JSON_parse() regards scalars as a syntax error,
but we have explicit checks for null, true, false,
numerics, and strings.  Clear the error when we return these.

Reviewed By: @scannell

Differential Revision: D1112796
2013-12-30 12:05:03 -08:00
Dario Russi a8dbb3b8ad Separate bits for "non ref count" and "static" types.
Use different bits for static type and ref counted types. Every static type is not ref counted however we want to introduce the concept of a non static type that does not need ref counting.

Reviewed By: @markw65

Differential Revision: D1090994
2013-12-30 12:05:00 -08:00
Dario Russi 89e54f5186 Change hasInternalReference to DataWalker and track more info of the object graph
Change, centralized and abstracted data graph walker to collect some info on the data graph for APC

Reviewed By: @jdelong

Differential Revision: D1098889
2013-12-30 12:04:56 -08:00
Simon Welsh aba50a36f4 Add Array to string conversion notice
Add Array to string conversion notice (and RaiseNotice IR
instruction needed to do so when using the JIT)

Closes #1314

Reviewed By: @alexmalyshev

Differential Revision: D1080985

Pulled By: @scannell
2013-12-30 12:04:52 -08:00
Brandon Wamboldt d26429c53d Fix preg_match_all requiring three parameters
preg_match_all's third parameter ($matches) should be an optional parameter.

Closes #1451

Reviewed By: @alexmalyshev

Differential Revision: D1112209

Pulled By: @scannell
2013-12-30 12:04:49 -08:00
javer 17fb5c2cce str_replace with empty array should return array
Handle empty array in str_replace like Zend and return an empty
array instead of null.

Closes #1452

Reviewed By: @alexmalyshev

Differential Revision: D1112243

Pulled By: @scannell
2013-12-30 12:04:45 -08:00
Sara Golemon 641b6bc9e0 Fix generation of parsers/scanners 2013-12-28 17:45:02 -08:00
Alex Malyshev 06f4711821 Fix callable typehint
The lexer and parser didn't know anything about the callable keyword,
and it was causing typehint errors when callable was being used inside a
namespace N, and the resulting typehint turned into "N\callable". Add
T_CALLABLE token to match zend, and fix TypeConstraint to respect it.

Reviewed By: @elgenie

Differential Revision: D1112493
2013-12-28 17:43:13 -08:00
Alex Malyshev ae9c577e7f Actually implement imagefilter()
imagefilter was using a function table filled with functions that just
threw NotSupportedException. Fixed them.

Reviewed By: @elgenie

Differential Revision: D1111814
2013-12-28 17:35:12 -08:00
Edwin Smith 4508e223f0 Visit all blocks when splitting critical edges.
Before we only were looking at blocks on the main trace.  This diff
removes the trace dependency, but still adds the middle-blocks to the
trace that owns the from-block.

Reviewed By: @ottoni

Differential Revision: D1111948
2013-12-28 17:35:08 -08:00
Edwin Smith f4d4b5110c Ignore traces in optimizeCondTraceExit
Same pattern as optimizeSideExitCheck.

Reviewed By: @ottoni

Differential Revision: D1111457
2013-12-28 17:35:05 -08:00
Jordan DeLong aab12b76e2 Filter systemlib-like units out of hhbbc for now
Reviewed By: @elgenie

Differential Revision: D1111801
2013-12-28 17:35:02 -08:00
Edwin Smith 21b7fcd24a Ignore traces in optimizeSideExitCheck()
Refactor optimizeSideExitCheck() into the postorder walk.  We were
visiting every instruction before, we really only need to visit
the last instruction of each block, and we can do it in the same
walk as the other jump optimizations.

Reviewed By: @ottoni

Differential Revision: D1111447
2013-12-28 17:34:58 -08:00
Edwin Smith 8036bfa80f Ignore traces in optimizeSideExitJccs()
Refactor optimizeSideExitJcc into the postorderWalk traversal.
We don't need to look at traces at all for this to work.

Reviewed By: @jdelong

Differential Revision: D1111176
2013-12-28 17:34:55 -08:00
Edwin Smith d819232fbb Ignore traces in eliminateUnconditionalJump()
This lays the groundwork for general jump optimizations and removes
the IRTrace dependency from eliminateUnconditionalJump().  Now we
traverse all blocks in postorder; two blocks joined by a trivial Jmp
can coalesced together.

Reviewed By: @ottoni

Differential Revision: D1111166
2013-12-28 17:34:52 -08:00
Alex Malyshev dc46425005 Don't expose doc comments of builtins through Reflection
Zend doesn't have doc comments for its builtins, so
Reflection{Method,Function,Class,Property}::getDocComment() will just
return false, but we have doc comments in systemlib/php and we return
those. Turns out this breaks Symfony, as they parse their own code and
then try to match their doc comments with those of Reflection, but throw
an exception when they fly up the interfaces on one of their classes and
hit ArrayAccess, which they never parsed doc comments for.

Reviewed By: @ptarjan

Differential Revision: D1106653
2013-12-27 21:58:45 -08:00
Eugene Letuchy bfa0c01f69 move trait alias modifier validation to parser ...
* remove a few places where we were attempting to do a modifier check
   at trait flattening time (badly?) and at class* time (waaay too late)
 * fix the glaring hole where 'visibility' modifier was interpreted as
   'not `static`' as opposed to ##public|private|protected|final## due to the way
   hphp.y happened to reuse modifiers

Reviewed By: @ottoni

Differential Revision: D1111920
2013-12-27 21:58:42 -08:00
Abel Nieto 25ad388943 Move FrozenSet to the HH namespace.
As per the title.

Reviewed By: @elgenie

Differential Revision: D1105025
2013-12-27 21:58:38 -08:00
Patryk Pomykalski 0f3e58f8ff Fix OOM while compiling mongo extension
gcc using all memory when compiling mongo/cursor.cpp

Closes #1414
Closes #1427

Reviewed By: @elgenie

Differential Revision: D1110301

Pulled By: @scannell
2013-12-27 21:58:35 -08:00
Sean Cannella a0a2fce43a Fix INI file typo
Fix INI file typo

Closes #1450

Reviewed By: @alexmalyshev

Differential Revision: D1112190
2013-12-27 21:58:31 -08:00
Brandon Wamboldt d0b98ce43d Fix preg_match returning false instead of null
preg_match/preg_match_all should return NULL not FALSE when invalid flags are passed.

Closes #1442

Reviewed By: @alexmalyshev

Differential Revision: D1111983

Pulled By: @scannell
2013-12-27 21:58:27 -08:00
Herman Venter 279a61338c Fix bugs in serialization of HHVM parse trees as PHP Code Model.
Remove left parentheses that survived edits and evolution. Fix the serialization of a simple function call to use the original function name. Make printExpressionVector treat a null list as an empty list. Use the original (scanned) string value when serializing scalar values. Make StaticClassName::outputCodeModel produce properly serialized strings (i.e. with headers). Use printStatementVector instead of just serializing each element of the vector in sequence. Adjust property counts to take into account null values. Tweak serialization of if statements to better deal with empty true blocks.

Reviewed By: duv

Differential Revision: D1097296
2013-12-27 21:58:23 -08:00
Paul Tarjan 77c6b843e1 actually send the response code
Closes #1416

Reviewed By: @sgolemon

Differential Revision: D1111910
2013-12-27 21:58:19 -08:00
Andre Costa b5d79c182e Fix redis' zRange and zRevRange
The commands zRange and zRevRange on redis weren't working. Since its
arguments are being passed to the command as an array, we must call
`processArrayCommand()` instead of `processCommand()`.

Reviewed By: @ptarjan

Differential Revision: D1111425
2013-12-27 21:58:16 -08:00
Edwin Smith 31e44e76af Move next edge from Block to IRInstruction
It's more precise to put the next edge on IRInstrution than on Block.
The current setup made it easier to add edges into the IR in general,
but this finally puts them where they should go.  This diff also
cleans a few things up: Edge now has an instruction field, which
avoids the need to set Edge.m_from whenever an instruction's block
changes; Edges are allocated separately, and only for instructions
that need them, which reduces sizeof IRInstruction by 16 bytes.
Every block must now end with a control flow instruction, even if it's
just a jmp to a next block.  Unnecessary jumps should already be
removed at code-gen time.

This diff also adds a Branch flag.  Any instruction that could have
an edge must have either the Branch flag or MayRaiseError flag, in
which case m_edges is never null (but Edge::to could be null).
Other instructions must have m_edges == null.  Because of this, it
was necessary to factor the compare instructions into the ones that
throw, with MayRaiseError set plus a catch edge, and ones that don't,
with no edges.

Reviewed By: @jdelong

Differential Revision: D1109820
2013-12-27 21:57:55 -08:00
Guilherme Ottoni a212a099b4 Only consider classes that are final for specialization
That's a requirement from how we generate specialized guards, so don't
even let non-final classes enter into the type system.

Reviewed By: aravind

Differential Revision: D1109309
2013-12-27 21:52:39 -08:00
Guilherme Ottoni d2651ac64b Only generate profiling translations after JitProfileRequests for functions that are already being profiled
Otherwise, for functions that we never saw during the first
Eval.JitProfileRequest requests, we'll generate profiling translations
that never get retranslated.

Reviewed By: aravind

Differential Revision: D1104276
2013-12-27 21:52:36 -08:00
Sara Golemon 33a1bfa3ed Refactor ext icu a bit
* Reduce copypasta by inheriting from a common IntlRequestData
  * Move some stuff into headers for interop between intl components

Reviewed By: @ptarjan

Differential Revision: D1107269
2013-12-27 03:58:24 -08:00
Paul Tarjan 705fa52c49 use writeBE instead of append for fastcgi
Reviewed By: @simpkins

Differential Revision: D1111292
2013-12-27 03:57:16 -08:00
Eugene Letuchy 76991160ef trait requires: check trait constraints on recursive traits [4/4]
traits should be able to state what they require of their
 subclasses:

  require implements SomeInterface
  require extends SuperClass

 This will aid hack in being able to typecheck trait bodies as
 well as allowing more disciplined trait coding (tying traits to
 class hierarchies, as happens in practice).

 This diff checks implements and extends requirements on recusively
 used traits (class uses trait that itself uses another trait that has
 requirements). The approach chosen is to walk the trait hierarchy for
 each Class instantiation; an alternative approach would be to keep a
 list of requirements in each trait Class and add to it.

 Note that nothing is done in repo mode, since traits end up flattened
 into using classes.

Reviewed By: @jdelong

Differential Revision: D1101640
2013-12-27 03:57:12 -08:00
Eugene Letuchy 3f608b310e trait requires: check traits constraints at use time [3/4]
traits should be able to state what they require of their
 subclasses:

  require implements SomeInterface
  require extends SuperClass

 This will aid hack in being able to typecheck trait bodies as well as
 allowing more disciplined trait coding (tying traits to class
 hierarchies, as happens in practice).

 This diff introduces the checking of implements and extends
 constraints on the using class, and (less importantly) enforces that
 we're dealing with the right kind of class on traits.

Reviewed By: @jdelong

Differential Revision: D1101637
2013-12-27 03:57:09 -08:00
Eugene Letuchy affb8f79da trait requires: thread into preclass [2/4]
traits should be able to state what they require of their
 subclasses:

  require implements SomeInterface
  require extends SuperClass

 This will aid hack in being able to typecheck trait bodies as well as
 allowing more disciplined trait coding (tying traits to class
 hierarchies, as happens in practice).

 This diff moves the trait requirement declarations into the preClass,
 but doesn't yet check them

Reviewed By: @jdelong

Differential Revision: D1101621
2013-12-27 03:57:05 -08:00
Jordan DeLong 926cac6f07 Default StatCache to off
We're turning it off in all of our configs, but we left it on
in the example OSS configs.  There's some sort of race-issue reported
on github, so let's turn the default to the tested configuration.

Closes #1402 (not the underlying problem, but we're not really
planning to make StatCache better any time soon).

Reviewed By: @edwinsmith

Differential Revision: D1108713
2013-12-27 03:57:02 -08:00
Guilherme Ottoni f5acb51e97 Teach prediction optimization about no-dest IncRefs
The type prediction optimization checks for a specific pattern, which
changed once we dropped the dest operand of IncRefs.  This diff fixes
it.

Reviewed By: @jdelong

Differential Revision: D1110700
2013-12-27 03:56:58 -08:00
Jordan DeLong b1d75c750e Fix bugs relating to Uninits in the control-flow local type updates
locAsCell behaves like CGetL: it returns a subtype of
TInitCell (uninits become init nulls, and it dereferences TRef).
Since in these grouping functions we're about to set the loc back
"unchanged", we want something that does the deref but not the
conversion of uninit to init.

Reviewed By: @edwinsmith

Differential Revision: D1109766
2013-12-27 03:56:55 -08:00
Jordan DeLong 68b8e71a15 Hook Op::JmpNS up to pass through in HHBBC
For now did it the easy way.

Reviewed By: @edwinsmith

Differential Revision: D1103613
2013-12-27 03:56:52 -08:00
Jordan DeLong 1e0b802984 Replace NoSurprise metadata with a JmpNS instruction
Just is easier to manipulate bytecode than metadata.  This
doesn't hook it up in hhbbc yet.  Also I removed surprise flag checks
from IterBreak: they aren't ever going to jump to loop heads.

Reviewed By: @markw65

Differential Revision: D1103402
2013-12-27 03:56:48 -08:00
Alex Malyshev 3ba683b441 Replace macros in Simplifier with templates
Replaces SIMPLIFY_{CONST,COMMUTATIVE,DISTRIBUTIVE} with templated
functions instead.

Reviewed By: @jdelong

Differential Revision: D1104151
2013-12-27 03:56:41 -08:00
Sara Golemon 7f2b1ced80 Remove the need to export HPHP_HOME when building
"Detect" HPHP_HOME as the location of the main CMakeLists.txt
file and plumb it through to child scripts from there.
2013-12-27 03:10:16 -08:00
Sara Golemon 209927b104 Some spring cleaning for the cmake file
Don't even check USE_HHVM/USE_HPHPC, hphpc died months ago.
HHVM_BINARY and HHVM_LIB_PATH_DEFAULT defines are no longer used.
HHVM_PATH is specific to test.
2013-12-27 03:10:16 -08:00
Sara Golemon d74565b37e Rename CMake LibUODBC module.
Oops.  I misnamed it.
2013-12-27 03:10:15 -08:00
Sara Golemon ff58f003aa Be honest, we're just not going to support 32bit.
The JIT specifically emits 64-bit x86 and will do so for
the forseeable future.
2013-12-27 03:10:15 -08:00
Sara Golemon 579fb44d4b Strip generator's path info out of generated ini-parser file 2013-12-27 03:10:15 -08:00
Guilherme Ottoni 0799ab3745 Change eliminateRefcounts to convert instructions to Nops instead of erasing them
Otherwise the block may become empty and validation passes start to
complain.  It's simpler to just convert the instructions to Nop and
let DCE take care of cleaning things up.

Reviewed By: aravind

Differential Revision: D1109291
2013-12-26 11:02:01 -08:00
Sean Cannella be7fb2055d Fix ASAN tests
Fix use-after-free with imported systemlib module names

Reviewed By: @jdelong

Differential Revision: D1111011
2013-12-26 11:01:58 -08:00
Jordan DeLong 622b5c09a4 Update NEWS for Appleseed
Reviewed By: @scannell

Differential Revision: D1110400
2013-12-26 11:01:55 -08:00
reeze 4e697550da Fix ReflectionClass::implementsInterface with \
Fixed ReflectionClass::implementsInterface() with black slash
prefixed interface name

Closes #1424
Closes #1430

Reviewed By: @ptarjan

Differential Revision: D1110811

Pulled By: @scannell
2013-12-26 11:01:51 -08:00
Brandon Wamboldt fa60b79bd3 Fix SplDoublyLinkedList when using array syntax
If you append items to a SplDoublyLinkedList using array syntax
($foo[] = 'bar'), the tail would not be updated.

Example:

<?php
$stack = new SplStack();

$stack[] = "var1";
$stack[] = "var2";
$stack[] = "var3";

foreach ($stack as $var) {
    echo $var . "\n";
}

HHVM Output:

    var1

Correct Output:

    var3
    var2
    var1

Closes #1415
Closes #1421

Reviewed By: @alexmalyshev

Differential Revision: D1110142

Pulled By: @scannell
2013-12-26 11:01:48 -08:00
Sam Boyer 447f17f1e2 SplObjectStorage mutation fix
The current reimplementation of SplObjectStorage does not allow mutation
of "info" values attached to object keys in the case where the object is
already present in the object. This is inconsistent with PHP's behavior.

Closes #1388

Reviewed By: @ptarjan

Differential Revision: D1108349

Pulled By: @scannell
2013-12-26 11:01:44 -08:00
Patryk Pomykalski 7a7b09894a Fixed setIteratorMode() in SplStack and SplQueue
setIteratorMode in SplStack didn't throw exception when mode
was invalid.

Closes #1426

Reviewed By: @alexmalyshev

Differential Revision: D1110182

Pulled By: @scannell
2013-12-26 11:01:41 -08:00
Brandon DuRette 365c56fdc4 Make strrchr more compatible with Zend
The contract for strrchr is "If needle contains more than one character,
only the first is used". The implementation was using strrpos which
scans for the entire string, not just the first character, resulting in
an incompatibility. This PR request resolves that incompatibility.

Also, for the purposes of strrchr, zend treats the empty string as a NUL
character. This happens because the empty string is (apparently) handled
by the second rule for needle: "If needle is not a string, it is
converted to an integer and applied as the ordinal value of a
character."

Closes #1394

Reviewed By: @JoelMarcey

Differential Revision: D1108545

Pulled By: @scannell
2013-12-26 11:01:38 -08:00
Simon Welsh a24d2c619a Add ZendParamModeFalse
Add ZendParamModeFalse for chdir-like functions

Reviewed By: @ptarjan

Differential Revision: D1108735

Pulled By: @scannell
2013-12-26 11:01:34 -08:00
Sean Cannella 9b1c9e5e08 Change error exit code to be consistent with Zend
Errors now return -1 like PHP does.

Closes #1350
Closes #1405

Reviewed By: @ptarjan

Differential Revision: D1108693
2013-12-26 11:01:31 -08:00
Simon Welsh 4f5a3795b8 Pass along error number when handling a fatal error
As no error number was being passed when a fatal error occurred, error_get_last() in a shutdown handler wasn't able to check if the error was fatal.

Closes #1408

Reviewed By: @alexmalyshev

Differential Revision: D1110032

Pulled By: @scannell
2013-12-26 11:01:27 -08:00
Brandon DuRette 90e2969feb Zend compatibility - stripslashes
Zend's implementation of stripslashes removes a trailing
backslash in a string, except in the empty string it is replaced by a
NUL. Prior to this PR, HHVM's implementation always replaced the
trailing backslash with a NUL. The reason is, HHVM unconditionally
appended the character following a backslash. When the string ends in
backslash, the following character is the null-terminator of the
underlying C-string.

This was identified because of a failing test in the WordPress test
suite.

Closes #1423

Reviewed By: @alexmalyshev

Differential Revision: D1110135

Pulled By: @scannell
2013-12-26 11:01:24 -08:00
Simon Welsh 08395de8ca fix ob_get_contents return value
ob_get_contents returns false if not currently buffering output

Closes #1429

Reviewed By: @alexmalyshev

Differential Revision: D1110757

Pulled By: @scannell
2013-12-26 11:01:20 -08:00
Sean Cannella deb0b232e2 Fix test runner
Fix test runner

Reviewed By: @edwinsmith

Differential Revision: D1110872
2013-12-24 14:11:04 -08:00
Benjamin Zikarsky d469cde767 Reestablished PHP 5.3 compatibility in test runner
Fix compat issues with Zend PHP 5.3

Closes #1420

Reviewed By: @ptarjan

Differential Revision: D1110759

Pulled By: @scannell
2013-12-24 14:11:03 -08:00
Sumeet Ungratwar 23efdd51d7 Made paramater of newInstanceArgs method optional
PHP documentation requires it to be optional, passing no
argument would call the constructor taking no arguments.

Reviewed By: @ptarjan

Differential Revision: D1109795
2013-12-24 14:11:03 -08:00
Paul Tarjan a19766f3de fix DOCUMENT_ROOT for fastcgi
We shouldn't have spcialized code in here for fastcgi, and it didn't even work.

Reviewed By: @markw65

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

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

Reviewed By: @markw65

Differential Revision: D1108017
2013-12-24 14:11:02 -08:00
Jordan DeLong 5d674bb81b Fix an issue with empty async function closures---finishStatement off by one
Also remove a "useless non-terminal" warning (an old rule was
accidentally left in).  This only affected empty async function
closures, since the onClosure itself wasn't off by one, and all
finishStatement does is replace empty statement lists.

Reviewed By: @edwinsmith

Differential Revision: D1109810
2013-12-24 14:11:02 -08:00
Edwin Smith c0995e0acd Fix names of a bunch of opcodes in ir.specification
It looks like someone renamed them in the source code but
forgot to update the spec.

Reviewed By: @jdelong

Differential Revision: D1109814
2013-12-24 14:11:01 -08:00
Sumeet Ungratwar e68e5f08f5 fix ini_get('memory_limit')
No information of input string was stored by ini_set. For e.g.
10K was converted to 10240 which ini_get('memory_limit') returned.
Solution was to store user passed in string and convert it to integer
whenever required

Reviewed By: @ptarjan

Differential Revision: D1109228
2013-12-24 14:11:01 -08:00
mwilliams 8107a50d5f Better type inference for collections
Let type inference know the actual type for T_COLLECTION
expressions. Also mark them "definitely not null".

Reviewed By: @jdelong

Differential Revision: D1109650
2013-12-24 14:11:01 -08:00
Jordan DeLong 0683d2006d Remove various subop static_casts in abstract-interp.cpp
These are no longer needed now that the opcode table knows
about subop types.

Reviewed By: @swtaarrs

Differential Revision: D1102943
2013-12-24 14:11:00 -08:00
Jordan DeLong c02cbd6273 Update local types for the bytecode sequences CGetL; InstanceOfD; Jmp{N,}Z
Reviewed By: @dariorussi

Differential Revision: D1101639
2013-12-24 14:11:00 -08:00
Jordan DeLong 25a3e28b41 Remove simplifySpillStack's attempted dead store elimination
It isn't aware of situations where autoload can clobber stack
slots.

Reviewed By: @ottoni

Differential Revision: D1107251
2013-12-24 14:10:59 -08:00
Jordan DeLong 456d625c0e Fix a bug in FPI region recording for internal async function calls
The FPIRegionRecorder is notoriously easy to misuse.

Reviewed By: @dariorussi

Differential Revision: D1107441
2013-12-24 14:10:59 -08:00
Drew Paroski 254e68c0b0 Lambda syntax
Reviewed By: @jdelong

Differential Revision: D1108850
2013-12-24 14:10:58 -08:00
Eugene Letuchy c82e54b087 trait requires: add basic syntax [1/4]
traits should be able to state what they require of their
 subclasses:

  require implements SomeInterface
  require extends SuperClass

 This will aid hack in being able to typecheck trait bodies as well as
 allowing more disciplined trait coding (tying traits to class
 hierarchies, as happens in practice).

Reviewed By: @jdelong

Differential Revision: D1101619
2013-12-24 14:10:58 -08:00
mwilliams c5746986df Analyze systemlib.php in repo mode
This lets us analyze systemlib.php in wholeprogram mode. It also
analyzes the various extension php files in wholeprogram mode. Previously,
whole program mode was almost entierly unaware of the mini-systemlibs, and
things only really worked by luck, and bugs in the way they were processed.

Reviewed By: @jdelong

Differential Revision: D1099615
2013-12-24 14:10:58 -08:00
Benjamin Zikarsky 22b4777d5c Included ReactPHP and Ratchet to framework runner
Included ReactPHP and Ratchet to framework runner

Closes #1404

Reviewed By: @ptarjan

Differential Revision: D1108669

Pulled By: @scannell
2013-12-24 14:10:57 -08:00
Benjamin Zikarsky 328ca374c7 Add monolog to framework test runner
Adds monolog to framework test runner

Closes #1397

Reviewed By: @ptarjan

Differential Revision: D1108661

Pulled By: @scannell
2013-12-24 14:10:57 -08:00
Paul Tarjan be5279d633 refactor Closure getting ready for bindTo
Reviewed By: @jdelong

Differential Revision: D1106189
2013-12-24 14:10:56 -08:00
Paul Tarjan 812727c240 maybe fix iopCreateCl race
@markw65 purported that maybe this was the cause of the race. I agree it is worth trying

Reviewed By: @markw65

Differential Revision: D1106725
2013-12-24 14:10:56 -08:00
Sean Cannella d93cdc2ca8 Support oniguruma-5.9.4+
Newer versions of oniguruma have a type collision without this define, see https://github.com/javer/gentoo-overlay/pull/3#issuecomment-30758478.

Closes #1400

Reviewed By: @ptarjan

Differential Revision: D1108355
2013-12-24 14:10:56 -08:00
Simon Welsh eebe258165 Add SilverStripe to the test runner
Add SilverStripe to the test runner

Closes #1390

Reviewed By: @ptarjan

Differential Revision: D1107161

Pulled By: @scannell
2013-12-24 14:10:55 -08:00
Abel Nieto ba00db7b3d Migrate FrozenVector to the HH namespace.
As per the title.

Reviewed By: @paroski

Differential Revision: D1091837
2013-12-24 14:10:55 -08:00
Paul Tarjan 39b21a2fd7 filter_var snapshot (take 2)
Unrevert the filter_var diff. Also fix a bug where it isn't snapshotted in the request path.

Reviewed By: @JoelMarcey

Differential Revision: D1104270
2013-12-24 14:10:54 -08:00
Joel Marcey 4b9aec1592 Better match Zend finfo
NULL is allowed for some string parameters in some functions of finfo. In fact, NULL is the default value. e.g., http://php.net/manual/en/function.finfo-open.php

Our current implementation did not allow nullable strings. We would get errors like:

HipHop Fatal error: Argument 1 passed to foo() must be an instance of string, null given in /tmp/strtest.php on line 4

Make these string nullable (e.g. ?string)

phpbb was running into this issue using finfo

Reviewed By: @ptarjan

Differential Revision: D1107796
2013-12-24 14:10:54 -08:00
Abel Nieto 021d6eec40 Migrate Set to the HH namespace.
Move the Set collection class to the HH namespace.

So now get_class(new Set()) === "HH\Set".

The auto-import mechanism in place makes the change transparent most of the
time (e.g. developers can simply use "Set" in their code), but the namespace
shows up in some cases, serialization being a notable one.

Depends on D979471.

Reviewed By: @elgenie

Differential Revision: D1081929
2013-12-24 14:10:54 -08:00
Abhinav Batra 8765e705bf Resource To Array Conversion
Converted resource to an array contatining the resource

Reviewed By: @ptarjan

Differential Revision: D1107620
2013-12-24 14:10:53 -08:00
Brandon DuRette 65bdcabe8e str_replace counts fail to accumulate with arrays
The $count parameter of str_replace is supposed to return the total
number of string replacements performed. This was only working correctly
when both $search and $subject were strings. When either or both are
arrays, the counts need to accumulate across all replacements. The code,
as written, was only returning the replacement count for the last pair
of values.

Closes #1383

Reviewed By: @ptarjan

Differential Revision: D1106935

Pulled By: @scannell
2013-12-24 14:10:53 -08:00
Dario Russi 6c277e96c7 fix leak in iter_next_apc for string keys
We were inc-ref'ing keys one too many

Reviewed By: @jdelong

Differential Revision: D1108033
2013-12-24 14:10:52 -08:00
bsimmers 3a9e0f5e44 Fix LdThis in unbound closure bodies
Loading $this will always fail in these, but we shouldn't dump core
while processing the unreachable code.

Reviewed By: @ottoni

Differential Revision: D1107377
2013-12-24 14:10:52 -08:00
Sara Golemon dcc7e3d788 Make unix_odbc support optional 2013-12-24 14:10:52 -08:00
Pedro Eugenio Rocha Pedreira 8a0e601bf4 hhvm: initial implementation of the php_odbc API
Reviewed By: @ptarjan

Differential Revision: D1058022
2013-12-24 14:10:36 -08:00
Guilherme Ottoni 711851fc71 Trigger Optimize retranslations at all function entries
This diff changes things so that Profile translations for all function
entries (normal entry plus DV funclets) trigger Optimize
retranslations in PGO mode.  This fixes the PGO mechanism for
irregular functions (e.g. array_map) that don't follow the defunct
bytecode rule that DV funclets fall-through one into another and then
into the function's main entry (function base).

Also did a few cleanups along the way.

Reviewed By: @bertmaher

Differential Revision: D1108164
2013-12-24 09:59:19 -08:00
mwilliams 272874f432 Fix crash when a custom init function throws
Classes derived from exception have a custom-instance-init
method which gets called before the constructor. It can throw (eg
if a timeout occurs), so allocObj needs a catch trace, and allocObjFast
shouldn't be called on classes derived from Exception.

Reviewed By: @edwinsmith

Differential Revision: D1107437
2013-12-24 09:59:15 -08:00
Edwin Smith a4c6946652 Allocate intervals individually
Looking at XLS trace dumps, most units have a lot less
intervals than SSATmp ids.  Allocating them separately
should save a bunch of memory, but also avoid any hazards
from std::vector moving them during register allocation.
(which happened to me once, w/out a reserve call).

Reviewed By: @jdelong

Differential Revision: D1107035
2013-12-24 09:59:12 -08:00
Bert Maher d93cf9b2ac Use base 10 for bytecode offsets in CFG printer
Since TRACE=printir uses base 10, I prefer using it here too.
But feel free to veto.

Reviewed By: @ottoni

Differential Revision: D1106785
2013-12-24 09:59:08 -08:00
Chip Turner ded68bbfe7 Properly split host:/path/to/socket strings
We weren't properly splitting the mysql socket form of connect
strings when ipv6 support was added.  The net result was a string of the
form:

localhost:/path/to/socket

was trying to open the socket 'path/to/socket' rather than
'/path/to/socket'

Reviewed By: @ptarjan

Differential Revision: D1107623
2013-12-24 09:59:04 -08:00
bsimmers 1e2a272df5 Add catch trace to RaiseWarning in emitDiv
Anything that can throw must have a catch trace.

Reviewed By: @bertmaher

Differential Revision: D1106629
2013-12-24 09:58:59 -08:00
bsimmers 2973400e8e Loosen assert in emitVerifyParamType
This should unbreak the legacy region selector in opt builds while I
try to figure out why it's firing.

Reviewed By: @edwinsmith

Differential Revision: D1105296
2013-12-24 09:58:55 -08:00
bsimmers 873354334b Misc tweaks/fixes
- aprof needs 6 digits just like a
- return the proper sizes for the admin port check-health command
- make an assert in emitVerifyParamType more useful

Reviewed By: @bertmaher

Differential Revision: D1103500
2013-12-24 09:58:51 -08:00
Herman Venter eb582bd73f Add parser support for language integrated query expressions.
This diff adds syntax to hphp.y, context sensitive keywords to hphp.ll, AST classes, a dummy emitter that just turns a query expression into a serialized CodeModel, as well as several test cases that exercise all options in the syntax and tests that the new keywords can still be used outside of queries.

The PHP syntax is exactly the same as the C# syntax.

There is significant restriction not present in C#, but necessary to get rid of shift reduce conflicts in Bison, namely: a query expression can only appear on the right hand side of an assignment to simple variable and as the expression of a return statement.

The need for making the "from" keyword context sensitive also precludes changing the syntax of "from $row in $table" to a more PHP compatible "from $table as $row", since $row can be any kind of expressions and hence does not provide enough context for the scanner to determine that the from token starts a query.

A query expression compiles to a call looking a bit like
   $rc = $c->executeQuery("serialized ast for normalized query expression", argvector);
   foreach ($rc as $re) { yield some_expression_containing($re); }
The $c is the value of the expression in the first from clause. The serialized ast represent the query expression after all parts of it that can be executed locally have been removed. Argvector is a vector of values that were computed locally. $rc is collection of tuples received from the query engine. The "foreach" turns the tuples into values as specified by the select clause.

This diff does not complete the implementation of code generation for query expressions. Specifically, the ast is not normalized, the argvector is null and the foreach is missing. I would like to get this diff out as is now in order to enable people to write query providers and test them with actual query expressions.

Reviewed By: @paroski

Differential Revision: D1088496
2013-12-24 09:58:51 -08:00
Paul Tarjan 745a3d8e41 fix preg segfault
`php_pcre_replace` isn't guaranteed to return a String or Boolean. Lets just proxy the result back if it isn't a string instead of assuming and segfaulting the async tier.

Reviewed By: @markw65

Differential Revision: D1106633
2013-12-24 09:58:37 -08:00
Edwin Smith 6eb84e4faf Convert XLS m_pending to priority_queue
Simpler than explicitly doing heap operations on a vector.

Reviewed By: @swtaarrs

Differential Revision: D1106561
2013-12-24 09:58:33 -08:00
Sean Cannella 1b389496b4 Merge pull request #1422 from brandonwamboldt/fix-markdown-1
Fix some minor markdown formatting issues
2013-12-23 11:25:44 -08:00
Brandon Wamboldt fb25361d62 Fix some minor markdown formatting issues 2013-12-22 10:16:38 -08:00
Sean Cannella 4df62bd80a Merge pull request #1407 from brandonwamboldt/fix-cmake-priority
Check for 32 bit OS first in the CMake file
2013-12-20 15:16:59 -08:00
Brandon Wamboldt cbd9f4ee37 Check for 32 bit OS first in the CMake file
Otherwise users may waste time installing missing dependencies just to get that error at the end
2013-12-20 15:11:41 -08:00
Sean Cannella ea44e6760d Merge pull request #1403 from javer/cmake-freetype
Fix cmake freetype include directory
2013-12-20 12:34:12 -08:00
javer c3bd6fa66a Fix cmake freetype include directory
Fixed overwriting FREETYPE_INCLUDE_DIRS when freetype located at
non-default path.
2013-12-20 19:32:58 +02:00
Sara Golemon 8525d97318 Add hash_copy()
Missing piece of hash API

Reviewed By: @ptarjan

Differential Revision: D1104737
2013-12-19 12:11:42 -08:00
Bert Maher c407042c11 Remove useHHIR param from TraceletContext::recordRead
It doesn't look like this flag actually has any effects
now... am I missing something?

Reviewed By: @swtaarrs

Differential Revision: D1106158
2013-12-19 12:11:35 -08:00
Bert Maher 686f440b8a More vestigial bits of Mem and Refs flags
Missed these pieces when killing them

Reviewed By: @jdelong

Differential Revision: D1106119
2013-12-19 12:11:28 -08:00
Edwin Smith c962d98717 Remove dead dtorStubs
They were dead code.  After a brief chat on IRC we agreed
to get rid of them.

Reviewed By: @jdelong

Differential Revision: D1104938
2013-12-19 12:11:21 -08:00
Paul Tarjan 9d80cda2cd throw an exception if the DateTime is invalid (take 2)
This reverts commit 14ce743eb5b6f82a411aff93d4129344e3ea02a3.

Reviewed By: @elgenie

Differential Revision: D1073188
2013-12-19 12:11:17 -08:00
Paul Tarjan 50aff1943e Fix Phar's directory detection
I screwed up the prefix check. Something that is a directory has to have a `/` between the prefix and the file, not just any character.

Closes #1334

Reviewed By: @JoelMarcey

Differential Revision: D1104260
2013-12-19 12:10:41 -08:00
Bert Maher 83564f81b1 Remove Mem and Refs flags, because they are dead
These flags aren't used for anything, so it's hard to know
what semantics they're supposed to have.  If we want to add something
similar in the future it will probably be just as easy to reason
through what we want from each opcode instead of trying to use these.

Reviewed By: @jdelong

Differential Revision: D1100600
2013-12-19 12:10:37 -08:00
Owen Yamauchi d8bd94843c ARM codegen for LdStack and DbgAssertRefCount
This was the top punt. Implementing that just moved a bunch of punting
to DbgAssertRefCount, so I implemented that too.

Reviewed By: @edwinsmith

Differential Revision: D1104532
2013-12-19 12:10:33 -08:00
Mike Magruder 45e315e85b Experimental memoization profiler
A small profiler which looks for memoization opprotunities. It's fairly ghetto right now, and dumps its output to stderr, but it's useful as is now so I'm gonna put it in. It's not hooked up anywhere, but if you're interested in how to hook it up, run it, and intrepret the output lemme know.

Reviewed By: @hermanventer

Differential Revision: D1100611
2013-12-19 12:10:29 -08:00
Owen Yamauchi 56509ff711 Put abi-x64.h in X64 namespace
For consistency with abi-arm.h. This doesn't cause too much X64::
line-noise (since files like code-gen-x64.cpp just do `using namespace
X64`), and it shines a light on some spurious platform dependencies,
which are now well-marked for when future ARM codegen stumbles across
them.

Reviewed By: @edwinsmith

Differential Revision: D1104447
2013-12-19 12:10:25 -08:00
Sara Golemon d8496058f7 Merge pull request #1381 from PocketRent/find-libs
Improve detection on FindLibs
2013-12-19 10:38:58 -08:00
James Miller 684fe9dcf8 Improve detection on FindLibs 2013-12-19 11:39:40 +13:00
Alex Malyshev b3640c2a87 Only save SessionRequestData's default module once
It was getting overrwritten every time session_set_save_handler() was
being called.

Also ext_session_request_shutdown() was calling close() on the session
module twice, fix that.

Reviewed By: @ptarjan

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

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

Closes #1345

Reviewed By: @markw65

Differential Revision: D1098327

Pulled By: @scannell
2013-12-18 11:42:05 -08:00
Edwin Smith a06ee23b39 Rename EvalHHIRAllocXMMRegs to EvalHHIRAllocSIMDRegs
Now the option name isn't arch-specific.

Reviewed By: @bertmaher

Differential Revision: D1104420
2013-12-18 11:42:01 -08:00
Patrick Dowell d1ff787b46 fix to allow proc_open() to accept php://stdin as stdin
I added some code to the openFile function in runtime/ext/ext_process.cpp that accounts for the case when the user calls proc_open() using
php://stdin as stdin for the process spawned.

Reviewed By: @ptarjan

Differential Revision: D1094713
2013-12-18 11:41:58 -08:00
Max Wang 1a1789fa85 Implement replace{C,TV} on VM stack
These are just wrappers for the behavior of pop{C,TV}() and pushFoo(),
but without the inc/dec.

Reviewed By: @jano

Differential Revision: D1100964
2013-12-18 11:41:54 -08:00
mwilliams ba14fac25d Include template functions in perf-pid.map
Template symbols are tagged WEAK, and neither
LOCAL nor GLOBAL. We need to include those in perf-pid.map
though.

Reviewed By: @ottoni

Differential Revision: D1103103
2013-12-18 11:41:51 -08:00
mwilliams 3da6f82fd4 Don't warn for system functions that aren't known at static analysis time
The c++ implementation of array_filter was recently removed,
and static analysis doesn't see .hhas files, so is now unaware of the
function, and so spits out UnknownFunction warnings. In addition, until
D1099615 lands, functions defined in mini-systemlibs aren't known either,
and so result in similar warnings.

This is a quick hack to eliminate those, so we can hotfix it to rc. I'll
do a better diff on master on top of D1099615.

Reviewed By: @ptarjan

Differential Revision: D1103230
2013-12-18 11:41:47 -08:00
Sean Cannella 8decf913ca Reduce hhprof crashes
- Memory profiling should not result in allocations and VM re-entry if we're crashing
- Fix call fixup in function prologue

Reviewed By: @jdelong

Differential Revision: D1102730
2013-12-18 11:41:43 -08:00
bsimmers ed492718fd Disable flaky zend test
Reviewed By: @jdelong

Differential Revision: D1103516
2013-12-18 11:41:36 -08:00
bsimmers 87c71e05a2 Revert "make filter_var snapshot the variables at request start"
This reverts commit de0579e00c94928357588ceb2796294be9110178. It broke
test/quick/debugger/flow.php

Reviewed By: @ptarjan
2013-12-18 11:41:32 -08:00
Jordan DeLong 686b040e70 Several type system bug fixes, and improve inference on jmpType for IsTypeL
Several of the functions relating to option types were wrong
if the option type had data (e.g. types like ?SStr="foo").  It's
easier to get everything right after adding TOptC{Str,Arr} types,
although I don't think they should happen much, so I added those.
Also, update IsTypeL; Jmp cases to do as good as the CGetL; Jmp cases
do with optional object subtypes.

Reviewed By: @edwinsmith

Differential Revision: D1099593
2013-12-18 11:41:29 -08:00
Jordan DeLong fe90718182 Fix some reflection under hhbbc, and for HNI functions after "refactor func.h"
The hhbbc case was a bug---for HNI it is a change in behavior
that looks unintentional, but I sorta doubt anything relies on the old
behavior.  Also remove the StringData* overload so you can't
accidentally call the wrong function, and add documentation.

Reviewed By: @alokmenghrajani

Differential Revision: D1099590
2013-12-18 11:41:25 -08:00
Jordan DeLong 80a34a78eb Update the types of locals when conditionally branching on their types
This makes some of the common patterns of user-level explicit
type tests update the types of locals on each side of the conditional
branch.

I thought a bit about how to do this without just pattern matching on
common bytecode pairs, but this seems the simplest way to get what we
want for now.  One other idea basically would involve a whole pass to
figure out which stack slots have the same types as which locals
(taking into account things that kill that relationship), which seemed
like it was unlikely to get any more types (although it would be "more
general").

Still a TODO is instanceof + jmp.

Reviewed By: @edwinsmith

Differential Revision: D1093057
2013-12-18 11:41:21 -08:00
Jordan DeLong 93733eed2d Fix a bug in preOptimizeStLoc
With the control-flow sensitive local type inference in
hhbbc, a local was being asserted as Type::Null.  Because
isKnownDataType returned true, preOptimizeStLoc decided that
converting that local from KindOfUninit (the actual live type) to
KindOfNull did not require storing a new m_type value, leading to a
crash down the line in the next translation.  I tried cleaning up
isKnownDataType but too many things depend on it (also it's a little
conceptually shaky because of how we deal with Str), so for now tasked
and just fixed this function.

Reviewed By: @swtaarrs

Differential Revision: D1099460
2013-12-18 11:41:17 -08:00
Guilherme Ottoni ca5dfe2457 Fix bugs in SetOpL
I ran into these while trying a perf diff that didn't turn out to help perf.

Reviewed By: @swtaarrs

Differential Revision: D1102269
2013-12-18 11:41:13 -08:00
Paul Tarjan 9ea6701165 make filter_var snapshot the variables at request start
I made an extensible way for extensions to run some code at the start of every request.

Reviewed By: @alexmalyshev

Differential Revision: D1101191
2013-12-18 11:41:10 -08:00
Paul Tarjan 8ab4b9f75b Revert "[ext_asio] Process ready wait handles in LIFO rather than FIFO order"
This reverts commit ff25227dea707166baf9fcb14a4940d503252e5f.

This has been reverted in 4 releases. That is just unacceptable. Please don't commit this until it can go out with a release.

Reviewed By: @jano

Differential Revision: D1102064
2013-12-18 11:41:06 -08:00
Jordan DeLong 1d936c49f5 Hackathon: initial version of php-to-hhas printer
Reviewed By: @edwinsmith

Differential Revision: D1099109
2013-12-18 11:41:02 -08:00
Jordan DeLong 67ab891ef6 Make OA arguments carry type information in the opcode table
Use this to unify all our to/from string functions for OA
arguments.  Also removes some of the remaining casting to/from
unsigned char.

Reviewed By: @swtaarrs

Differential Revision: D1098649
2013-12-17 13:59:07 -08:00
Jordan DeLong a5b1a0eb6b Turn IncDecOp/SetOpOP into enum classes and add hhas support for them
I'm planning to make the opcode table support strongly-typed
OA args, so I'll convert the remaining OA's to have enum classes.
After this diff, only BareThis uses an OA arg without an associated
enum class (I'll change that if making OA take a type argument turns
out to be good).

Reviewed By: @swtaarrs

Differential Revision: D1097329
2013-12-17 13:59:06 -08:00
Paul Tarjan 55289dc16f Make FastCGI less magical for headers
When I changed `getHeaders()` to be the same for fastcgi as all the other transports I didn't notice julk has put in special rules to deal with the fact they weren't the same. Rip that out.

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

Reviewed By: @sgolemon

Differential Revision: D1100779
2013-12-17 13:59:06 -08:00
Owen Yamauchi d2e18efee7 Get rid of x64-ARM register mapping
This gets ARM register allocation to use XLS properly.

- x2a is now just a type conversion function. This is the smoothest way
  of getting around the PhysReg::operator[] problem. I don't think this
  is the ideal way forward because it means the ARM backend is still a
  second-class citizen in a way. Any thoughts on how this should be
  done? I have a few, none of them appealing.

- Another problem I encountered is stuff within the jit (check.cpp and
  linear-scan.cpp) treating rVmSp and rVmFp specially, even though these
  are x64-specific. I want to try putting those in the X64 namespace,
  so that genuinely x64-specific usage sites have to be explicit about
  it, and then having runtime-populated rVmFp and rVmSp globals that
  depend on the current arch() for usage sites that don't care about
  platform.

- Made the IR printing stuff able to pretty-print ARM regs.

Reviewed By: @edwinsmith

Differential Revision: D1100519
2013-12-17 13:59:06 -08:00
Abel Nieto a1693289e2 Improve warning message in Set::toArray()
Array has a weird behaviour where string keys that can be represented
as ints are automagically converted to ints. From the manual:

  A key may be either an integer or a string. If a key is the standard
  representation of an integer, it will be interpreted as such (i.e.
  "8" will be interpreted as 8, while "08" will be interpreted as "08").

Since Set can contain both ints and strings, we could have e.g.

  $s = Set {1, '1'}

Calling $s->toArray() gives back then a 1-element array.

We were previously raising a warning in this case, but the warning didn't
specify what was the value of the "duplicate" key. Do so.

Reviewed By: @jdelong

Differential Revision: D1096274
2013-12-17 13:59:05 -08:00
Alexander d91fae6ae5 Add second parameter to nl2br
Adds the optional second `is_html` boolean parameter to match the Zend
implementation. The nl2br function still needs some work to have full
parity with zend, so the zend testcases aren't moved from bad to good
yet.

Reviewed By: @JoelMarcey

Differential Revision: D1101855

Pulled By: @scannell
2013-12-17 13:59:05 -08:00
Eugene Letuchy b8071aa339 add try/finally to NEWS
... it was the last major missing piece for 5.5 compat

Reviewed By: @ptarjan

Differential Revision: D1100828
2013-12-17 13:59:04 -08:00
bsimmers 666f330228 Kill MISOFF, rename HHIR_MISOFF to MISOFF
Reviewed By: @bertmaher

Differential Revision: D1100593
2013-12-17 13:59:04 -08:00
Rohit Bhoj 6f3c8c46b2 Modified findSingleTraitWithMethod so that it raises an error when there is trait collision for a trait alias
Modified findSingleTraitWithMethod so that it raises an error when there is trait collision for a trait alias

Reviewed By: @jdelong

Differential Revision: D1098140
2013-12-17 13:59:04 -08:00
Eugene Letuchy c1c06452a7 object data clone flags: handle c++ clone + php __clone
subclasses of c++ builtins (aka datetime) need to execute
 both the builtin's clone *and* whatever the PHP classes' __clone is.
 This unbreaks three datetime related test failures (my bad).

Reviewed By: @sgolemon

Differential Revision: D1102148
2013-12-17 13:59:03 -08:00
Eugene Letuchy c8605fa906 get rid of ObjectData::HasCppClone flag...
... by replacing it with the combination of IsCppBuiltin and
 HasClone. This frees up an ObjectData flags slot.

Reviewed By: @jdelong

Differential Revision: D1100574
2013-12-17 13:57:08 -08:00
Owen Yamauchi 86f5c0d1a6 Change vixl's internal stack pointer constant
This was a little tricky. On ARM machines, register number 31 is the
stack pointer. However, in some encodings, register number 31 refers to
a virtual "zero" register (basically the /dev/zero of registers). To
make sure that you don't accidentally use the wrong one with the wrong
encoding, vixl uses register number 63 to identify the stack pointer
(does not exist in hardware) and converts it to 31 while assembling.

This means that vixl uses 33 different register codes, so I'm changing
PhysReg to reflect this. This means we can now only represent 31 SIMD
register on ARM. I think this is preferable over losing the stack
pointer / zero register distinction in vixl.

Reviewed By: @edwinsmith

Differential Revision: D1100167
2013-12-17 10:30:30 -08:00
bsimmers 5a6d2d5254 Eliminate a couple linear searches in PGO mode
Instead of walking the entire list of profiling translations, keep
sets keyed on FuncID.

Default to JitRegionSelector=hottrace when JitPGO=true.

Reviewed By: aravind

Differential Revision: D1101198
2013-12-17 10:30:30 -08:00
Guilherme Ottoni 39800bb2bd Stop generating profiling translations after a threshold
This limits the duration of profiling, and skips PGO on functions
that aren't really hot.

Reuses the request count used to control the interpreter warmup
requests.

Reviewed By: @bertmaher

Differential Revision: D1095115
2013-12-17 10:30:29 -08:00
Drew Paroski d0a1138dfc Fix a typo in Map::differenceByKey()
Thanks to @Alite404Exception for catching this.

Reviewed By: @ptarjan

Differential Revision: D1101336
2013-12-17 10:30:29 -08:00
Bert Maher 3a79ee09a7 Changing some identifiers to make more sense.
Some trivial cleanup; it's pretty confusing to have a Value
named "state" when there is also a "struct State" in this file.

Reviewed By: @swtaarrs

Differential Revision: D1091303
2013-12-17 10:30:29 -08:00
Joel Marcey 8aef29cfcd Revisit how we handle post test information
All of our current local cronjob problems (not sure about chronos) are coming from corrupted .stat files. This is because the way we handled the gathering and printing of post test error information and stats were not 100% correct.

This diff hopefully helps fix this such that our local cronjob won't fail any longer.

Reviewed By: @ptarjan

Differential Revision: D1100647
2013-12-17 10:30:28 -08:00
Drew Paroski 352f5e479b Refactor bytecode emitter support for try/finally
This diff refactors the bytecode emitter support for try/finally. I re-
worked the algorithms to be written in an iterative manner (before they
were recursive) and fixed two small bugs, but aside from that I tried to
preserve the existing algorithms for now and mainly focus on moving the
code around and simplifying the structure a bit.

A lot of the emission logic for supporting try/finally was in separate
classes instead of EmitterVisitor which made things a bit unwieldy. This
diff takes most of the logic from FinallyRouter and FinallyRouterEntry and
moves it to EmitterVisitor, which helped simplify things and better fits
the style of the rest of the emitter. I got rid of the FinallyRouter class
and moved its fields to EmitterVisitor, and I renamed FinallyRouterEntry
and Action to "Region" and "ControlTarget" respectively. I also refactored
things a bit to reduce the amount of code that needs to deal with Regions.
Finally, I fixed a small bug where Region::getCaseCount() was double
counting the number of continue cases, and I improved the emitter to avoid
emitting a jump after the body of a try block when its not needed.

Ideas for future improvements: (1) simplify the algorithms and data
structures, (2) clean up how regions are created, entered, and left,
(3) merge the "Region" abstraction together with other region-like
concepts ("ForeachIterGuard", "FPIRegion", etc).

Reviewed By: @hermanventer

Differential Revision: D1099687
2013-12-17 10:30:28 -08:00
Drew Paroski 48580b3c5d Update NEWS file for the "Burrito" release
Reviewed By: @ptarjan

Differential Revision: D1100955
2013-12-17 10:30:27 -08:00
Eugene Letuchy 47a6dc08ab collections: unify collection object data flags
... the flags should all be the same. Fixes an inline issue
where FrozenSet was not marked as having a Clone function,
and *Vector and *Set were not marked as `IsCppBuiltin`.

Reviewed By: @jdelong

Differential Revision: D1100505
2013-12-17 09:37:15 -08:00
bsimmers 55d0bc9c50 Remove a couple 'using namespace' declarations from headers
Reviewed By: @ptarjan

Differential Revision: D1100100
2013-12-17 09:37:07 -08:00
bsimmers 03c020278d Don't put null/false in the json we pass to the test runner
It doesn't like that. It's going to be fixed to not barf on None, but
this will make things strictly better.

Reviewed By: @ptarjan

Differential Revision: D1100177
2013-12-17 09:37:03 -08:00
Sara Golemon 3dbe686d5a Add INI generator and generated files
Differential Revision: D1100639
2013-12-16 14:52:14 -08:00
Paul Tarjan d5deb150f4 make valgrind work
It doesn't always give us 4 bit aligned memory

Reviewed By: @edwinsmith

Differential Revision: D1060964
2013-12-16 13:03:11 -08:00
Edwin Smith 2e7414f1cb Fix RegSet::size() so it counts all the bits
builtin_popcount() silently truncated to int.

Reviewed By: @oyamauchi

Differential Revision: D1100154
2013-12-16 13:03:07 -08:00
bsimmers ac954c4d74 Disable flaky zend test
Reviewed By: @bertmaher

Differential Revision: D1100222
2013-12-16 13:03:04 -08:00
Emil Hesslow c8001cc9ed Fixes to parse_ini_(file|string)
Do a bunch of fixes in the parse_ini lexer and parser

Closes: #1320
Closes: #825
Closes: #838

Reviewed By: @ptarjan

Differential Revision: D970513
2013-12-16 13:03:01 -08:00
Paul Tarjan 782913bb47 fastcgi headers need unmangling
Headers as mangled in the FastCGI protocol, but the `getHeader()` method on `Transport` assumed the header was the original value.

Closes #1359

Reviewed By: @alexmalyshev

Differential Revision: D1098954
2013-12-16 13:02:57 -08:00
bsimmers e39ab52b12 Fold HPHP::Transl's contents into HPHP::JIT
Reviewed By: @ptarjan

Differential Revision: D1099088
2013-12-16 13:02:53 -08:00
Drew Paroski d926bdf746 Fix how the bytecode emitter handles foreach loops inside fault funclets
The bytecode emitter had a bug where it wasn't properly keeping track of
which iterators were live at a fault funclet's entry point. When emitting
a foreach loop inside the body of a fault funclet, the bytecode emitter in
some cases would erroneously use an iterator variable ID that was already
live.

This diff fixes the bug by updating the bytecode emitter to keep track of
which iterators were live at a fault funclet's entry point, and by updating
the logic for allocating iterator variable IDs to correctly handle foreach
loops inside fault funclets.

Reviewed By: @jdelong

Differential Revision: D1099508
2013-12-16 13:02:49 -08:00
Drew Paroski 1610575159 Improve c_Map::reserve
This diff tightens up the logic in c_Map::reserve to be more careful when
mixing signed and unsigned integers and when mixing 32-bit and 64-bit
integers.

This diff also removes a bogus assert, adds some more (non-bogus) asserts,
and adds some comments.

Reviewed By: anietoro

Differential Revision: D1097684
2013-12-16 13:02:46 -08:00
Jordan DeLong 780baaf33e Minor const correctness fix in hhbc.{h,cpp}
Reviewed By: @alexmalyshev

Differential Revision: D1094436
2013-12-16 13:02:42 -08:00
Jordan DeLong fec7562974 Make IterRange work with range-based for
Give it a begin() and end() function.

Reviewed By: @edwinsmith

Differential Revision: D1093982
2013-12-16 13:02:38 -08:00
Jordan DeLong c6c2ad63a2 Fix a bug in return type inference: ctors can be inherited from abstract classes
I think I was thinking that since interfaces can't declare
__construct methods, abstract classes probably couldn't either.
Actually not true.

Reviewed By: @dariorussi

Differential Revision: D1092876
2013-12-16 13:02:35 -08:00
bsimmers 29d0171824 Disable flaky zend test
Reviewed By: @jdelong

Differential Revision: D1099379
2013-12-16 13:02:31 -08:00
bsimmers f65f1d3b8a chmod -x runtime/vm/jit/*.{cpp,h}
I don't know why this keeps happening.

Reviewed By: @jdelong

Differential Revision: D1098912
2013-12-14 13:19:42 -08:00
Jan Oravec bcc10cbd48 Pass inGenerator flag in RetCtrl and FunctionExitSurpriseHook
Code gen for FunctionExitSurpriseHook and refcount optimization RetCtrl
opcode processing needs to know whether these opcodes were used inside a
generator. They currently obtain this information thru curFunc(). This
information is known statically, so pass it explicitly.

Needed for unified inner/outer generator functions.

Reviewed By: @jdelong

Differential Revision: D1095196
2013-12-14 13:19:39 -08:00
Owen Yamauchi 28149540e1 Make PhysReg able to represent 64 registers
Finally. PhysReg can now represent 32 GP regs and 32 SIMD regs.

Having the arch() dependency inside PhysReg feels a little strange, but
(a) Map really does need to behave differently depending on the
architecture, and (b) it's really convenient to have Map defined inside
PhysReg. I think it's an okay tradeoff.

In a followup diff, I'll get rid of x2a and have PhysRegs with ARM
register numbers flowing through XLS. It's still going to be a bit messy
because both codegen backends use the operator[] trick to create memory
references from register + offset. The ARM backend uses
vixl::Register::operator[], but the x64 backend uses
PhysReg::operator[]. I'm not yet sure how I'll reconcile this.

Reviewed By: @ottoni

Differential Revision: D1097959
2013-12-14 13:19:36 -08:00
Joel Marcey 68a39435b6 Make the user run command output better
The way I was generating the "RUN TEST FILE" commands at the end of the script run or within .errors/.fatals files was not the best. This improves that.

Reviewed By: @ptarjan

Differential Revision: D1098631
2013-12-14 13:19:32 -08:00
Joel Marcey 4350e9f04c Sigh. More post test warning fun for yii.
I love yii. I love yii. I love yii.

Need to check for another type of post test warning, that includes a PHPUnit Exception.

Reviewed By: @ptarjan

Differential Revision: D1098761
2013-12-14 13:19:29 -08:00
Alok Menghrajani 9f38afda2a Refactor func.h
Reviewed By: @paroski

Differential Revision: D1075910
2013-12-14 13:19:25 -08:00
Joel Marcey d3b2dfed63 Check for post test warnings too.
It looks like we fixed the post test fatal problem that joomla was having, but now yii may have post test warnings. For example,

/data/users/ptarjan/fbcode/hphp/test/frameworks/frameworks/yii/tests/./
framework/web/auth/CWebUserTest.php
HipHop Warning: Constant PHPUNIT_COMPOSER_INSTALL already defined in ve
ndor/phpunit/phpunit/composer/bin/phpunit on line 49

Let's see if this can fix that.

Reviewed By: @alexmalyshev

Differential Revision: D1098415
2013-12-14 13:19:22 -08:00
aravind 0d47329a8a Add support for IsScalar
Add support for IsScalar in IsType instruction.

Reviewed By: @ptarjan

Differential Revision: D1087810
2013-12-14 13:19:18 -08:00
Owen Yamauchi a54339ed27 Delete PhysReg::operator int()
With this, I think the dependency is broken, and we can start using
PhysReg to represent different register sets smoothly, without wrecking
anything.

Reviewed By: @edwinsmith

Differential Revision: D1096506
2013-12-14 13:19:14 -08:00
Abel Nieto bc922ca72a Move collections into their own namespace (Vector)
We want external developers to be able to use their own collection classes (e.g. Vector, Map, etc.) without colliding with HHVM's native versions.

This diffs moves the Vector class to the HH namespace.

It uses the "autoimport" mechanism in the parser so that the change is mostly transparent to PHP-land, and also modifies the IDL compiler so that class names (in the IDL) can contain namespaces.

i.e. for Vector, we change the class name in the IDL from "Vector" to "HH_Vector", which later gets exported as "HH\Vector" in PHP-land.

Reviewed By: @paroski

Differential Revision: D979471
2013-12-14 13:19:11 -08:00
Owen Yamauchi b9332084ff Make PhysReg(int) private to RegSet
The two register allocators had some remaining offenders. XLS was really
easy to fix (and in fact it made the code nicer), whereas LinearScan
didn't want to go quietly.

There is one substantive difference: in the stress mode where LS has a
reduced number of free registers, the ones at the beginning of the
sequence will be reserved instead of at the end. I could have avoided
that by giving PhysReg::Map a reverse iterator, but I don't think it
matters that much.

Up next: remove PhysReg::operator int().

Reviewed By: @edwinsmith

Differential Revision: D1096303
2013-12-14 13:19:07 -08:00
Sara Golemon 03e0826d77 Add ICU's IntlTimeZone and IntlIterator classes
Per zend implementation

Reviewed By: @ptarjan

Differential Revision: D1085605
2013-12-13 12:39:28 -08:00
Sara Golemon 1ba8fe784a Use ZendParamMode for all HNI methods
Removes method prologue as unnecessary since
we're coercing types during the call anyway.

Fixes fileinfo's HNI declarations to use nullable types.

Reviewed By: @ptarjan

Differential Revision: D1096599
2013-12-13 12:39:27 -08:00
Sean Cannella deb7d47f38 Fix Redis typo
Fix redis typo

Closes #1341

Reviewed By: @JoelMarcey

Differential Revision: D1097766
2013-12-13 12:39:27 -08:00
Joel Marcey d7ff0c33fa Append to the _script.errors file during a run of the script
Append to _script.errors during a single run of the script in case different frameworks have script errors during an --all run, for example.

Reviewed By: @ptarjan

Differential Revision: D1097486
2013-12-13 12:39:27 -08:00
Joel Marcey f620c88d24 Avoid post test fatals from getting in the way of stats
This diff should hopefully help the cronjob run better.

The cronjob and my local runs were getting errors like this:

The stats file for joomla is corrupt! It should only have test names and statuses in it.

We were getting this because of hhvm cleanup core dumps, etc. after a test was run. Instead of printing stats in the stats file, we were printing this fatal information, which corrupted the stats file.

So, I captured this fatal information and directed it to the fatals file instead.

Reviewed By: @ptarjan

Differential Revision: D1097602
2013-12-13 12:39:26 -08:00
Owen Yamauchi c6b4136ac7 Rewrite reg-algorithms.h to not use PhysReg(int)
I'm trying to break dependencies on PhysReg's internal representation
(regnum for GP regs; regnum + constant offset for SIMD regs). This is
necessary to use it for ARM registers. This means forbidding direct
conversion between int and PhysReg, and this file is one of the worst
offenders.

I rewrote it to use PhysRegs everywhere (this doesn't ruin the compiled
code; PhysReg's only member is an int so passing it around by value
and copying it isn't a big deal), and in the process introduced
PhysReg::Map, which uses the convenient underlying representation to be
compact, but hides that detail behind an STL-like container interface.

The next step will be to flush out other places where implicit
int-PhysReg conversion happens, and squish it. Once it's all gone, we
can freely mess around with the internal representation of PhysReg, and
it will all be contained in PhysReg, PhysReg::Map, and RegSet.

Reviewed By: @edwinsmith

Differential Revision: D1095930
2013-12-13 12:39:26 -08:00
mwilliams 6b84e33b74 Fix bug in side exit code
The code to detect a side exit to the first instruction in the
tracelet was broken for inlining, if the offset of the side-exiting
instruction just happened to be the same as the offset of the start
of the tracelet.

If we're inlining, we know they're not the same though, so skip the
check in that case.

Reviewed By: @jdelong

Differential Revision: D1096829
2013-12-13 12:39:25 -08:00
Alok Menghrajani 3ab63633b8 Always log soft/nullable type failures.
At this point, we want a way to always log these type warnings in the runtime (instead of the current 1/100 sampling). The next
step is to convert the nullable warnings into exceptions (see 83c970e1d8c01fd6e20c2cdb32d6a047c79edc4d).

Reviewed By: @paroski

Differential Revision: D1068880
2013-12-13 12:39:25 -08:00
Alex Malyshev ad81b7fe09 Fix incorrect condition in libmagic
File::seek returns true/false as a success status, so don't compare it
against a size_t.

Clang also doesn't like using an assignment in the condition of a
for-loop, wrapping it in parens silences the warning.

Reviewed By: @scannell

Differential Revision: D1096987
2013-12-13 12:39:25 -08:00
Alex Malyshev 312908509d Account for other libelf implementations
Turns out that there's at least two implementations of libelf,
one at http://www.mr511.de/software/english.html, and the other at
https://fedorahosted.org/elfutils/. One of them has elf_getshstrndx
return 0 on success, and the other returns 1.

Reviewed By: @scannell

Differential Revision: D1095441
2013-12-13 12:39:24 -08:00
Sean Cannella 5f739556de Add request-based override for HHProf profile mode
Adds the ability to override the runtime option specifying
allocation vs. heap profile on a per-request basis by adding profileType=foo to
the query string specified in the HHProf start request.

Reviewed By: @edwinsmith

Differential Revision: D1096216
2013-12-13 12:39:24 -08:00
Alex Malyshev d3946cdd14 Mark variable as unused
It's even called _unused...

Reviewed By: @jdelong

Differential Revision: D1096686
2013-12-13 12:39:23 -08:00
Edwin Smith a3c8c88b16 XLS support for SIMD registers.
Adds a simd field to Abi, plus code to have allow & prefer
sets for each interval.  We try to allocate from the prefer
set, but always at least take from the allow set.  Doubles
always prefer simd.  In addition, instructions that load and
store Cells, prefer simd.  This mimics the existing policy in
linear-scan.cpp.

Also changes linear-scan.cpp to not prefer GPRs for a tmp
that is an XMM candidate but which crosses a native call,
when HHIREnableCalleeSavedOpt==false (since prefering GPRs
in that case is part of the optimization).

Add support for XMM registers to PhysRegSaver.  If we had
a live XMM (double or TypedValue) that spanned a call, it
wasn't getting saved.

Reviewed By: @ottoni

Differential Revision: D1091845
2013-12-13 12:39:23 -08:00
bsimmers 40d446b9ce Misc cleanup
Simplify some IRTrace creation logic and clean up some type
smart::unique_ptr code now that we're on gcc >=4.7.

Reviewed By: @jdelong

Differential Revision: D1079241
2013-12-13 12:39:23 -08:00
Drew Paroski 2d7d6ccbe3 Fix bogus asserts in c_Map's implementation
There were two erroneous asserts in c_Map's implementation that were failing
in some cases when elements in a Map were unset. This diff removes the bogus
asserts.

Reviewed By: @dariorussi

Differential Revision: D1096926
2013-12-13 12:39:22 -08:00
Herman Venter f7fe29dcaf The PHP code model uses sourceLocation rather than location for the name of the source location property
Fixed the VM AST to Code Model serializer to use "sourceLocation" rather than "location". Also fixed the serialization of constant expressions to use "variableName" rather than just name and to use the original name field for its value. Also fixed serialization of closure expressions to check for the case where there are no captured variables.

Reviewed By: duv

Differential Revision: D1095904
2013-12-13 12:39:22 -08:00
Joel Marcey 15db67d0bc Stop being an error() clown.
@ptarjan's cronjob brought about an error that looked like this:

HipHop Warning: error() expects exactly 1 parameter, 0 given in /data/users/ptarjan/fbcode/hphp/tools/command_line_lib.php on line 16
HipHop Fatal error: Argument 1 passed to error() must be an instance of string, null given in /data/users/ptarjan/fbcode/hphp/tools/command_line_lib.php on line 16

Well, that is because error() requires a string as a parameter and there were cases in --csv where I called error() without a string.

Why the error is happening, we can hopefully find out after this fix too.

Fixed that. Actually re-did the erorr handling just a tad.

Reviewed By: @alexmalyshev

Differential Revision: D1096625
2013-12-13 12:39:21 -08:00
Guilherme Ottoni 36b0ee227a Always spill the stack before conditional jumps
This enables more opportunities to smash the jump in 'a', thus
avoiding going through astubs.

Reviewed By: @swtaarrs

Differential Revision: D1095483
2013-12-13 12:39:21 -08:00
Abel Nieto fb5de5ea8b Add unimplemented collection functions
There were a bunch of collection-related functions (e.g. collectionSet()) that
FrozenVector didn't implement. Fix that.

Reviewed By: @paroski

Differential Revision: D1066321
2013-12-13 12:39:21 -08:00
Guilherme Ottoni 354f0bdcfd Reduce JitPGOThreshold to 4
This seems to avoid some of the overhead for profiling and
retranslating in perflab.  It's possible that we can benefit from
additional profiling data, but this lower threshold seems to be the
best for perflab right now.  We can revisit it once we can increase
perflab warmup.

Reviewed By: aravind

Differential Revision: D1093148
2013-12-13 12:39:20 -08:00
Alex Malyshev 25f3c76b2a Fix errors reported by clang-3.4
Fix ArrayData's protected member m_kind being accessed incorrectly

Clang didn't like having a static_assert in an anonymous struct in
an anonymous union.

Seems like objects that use the new member initialization syntax are
required to have a user defined ctor, at least that's what the error
was...

Reviewed By: @jdelong

Differential Revision: D1093761
2013-12-13 12:39:20 -08:00
Alex Agape 7f31c17ea9 empty product return 1
Changed the return from 0 to 1.

Reviewed By: @ptarjan

Differential Revision: D1079222
2013-12-13 12:39:20 -08:00
Paul Tarjan cd4748908e fix a bunch of output buffering things
phpmyadmin (ab)uses this quite a bit and we are grossly incompatible. Either PHP has changed a bunch since 5.2 or the original author didn't test it thoroughly.

Reviewed By: @alexmalyshev

Differential Revision: D1095350
2013-12-13 12:39:19 -08:00
Alex Malyshev 4b032a8df6 Replace typeof with decltype
typeof is a GCC extension but decltype is part of the standard

Reviewed By: @jdelong

Differential Revision: D1095111
2013-12-13 12:39:19 -08:00
Alex Malyshev ddb294278b Remove unused function.
There's a dupe of this function in ext_mysql.cpp, but that one
actually gets used.

Reviewed By: @ptarjan

Differential Revision: D1095189
2013-12-13 12:39:18 -08:00
Sandeep Bindal bd6e62bee1 Namespaces should complain on double use
Fixed the double use problem

Reviewed By: @ptarjan

Differential Revision: D1091074
2013-12-13 12:39:18 -08:00
Drew Paroski fdc5e1b903 Update Map to use HphpArray-like data structure
This updates Map to use an HphpArray-like data structure instead of the old
data structure it was using. As a consequence Maps will now retain insertion
order.

With this change, Map performance stayed the same or improved on several
micro-benchmarks that test out different aspects of Map performance (such
as foreach, creating lots of small maps, building large maps, accessing
using "$c[$k]" syntax, etc).

Reviewed By: anietoro

Differential Revision: D1085607
2013-12-13 12:39:18 -08:00
Alex Malyshev e09620554c Fix unused variable
Actually use it instead.

Reviewed By: @jdelong

Differential Revision: D1094345
2013-12-13 12:39:17 -08:00
Herman Venter ee89706f31 Eliminate dead code from parser
The parser has a mechanism for creating a list of statements that are prepended to the next statement added to the main list of statements. This code is completely dead and serves only to confuse the reader.

Reviewed By: @jdelong

Differential Revision: D1093564
2013-12-13 12:39:17 -08:00
Alex Malyshev 7923afb3ed Fix uninit variable
All in the title.

Reviewed By: @jdelong

Differential Revision: D1094123
2013-12-13 12:39:16 -08:00
Alex Malyshev 4fcfb3a0de Call uninit_null() instead of using it as a fn pointer
This doesn't return an uninit null, it casts the function
pointer 'uninit_null' to a bool, which then gets cast
to a Variant "true". Don't you just love PHP I mean C++.

Reviewed By: @jdelong

Differential Revision: D1093730
2013-12-13 12:39:16 -08:00
bsimmers aa51a2837c Properly loosen refcount opts assert
My previous attempt at this solved the specific problem I was looking
at but accidentally tightened up the assert in a place it shouldn't be
checking. This diff fixes that and improves the stacktrace file for one of the
failure cases.

Reviewed By: @ptarjan

Differential Revision: D1093847
2013-12-13 12:39:16 -08:00
Alex Malyshev bcdfa958c3 Handle 'encoding' argument for get_html_translation_table
We were ignoring it previously, and just using the default encoding.

Reviewed By: @ptarjan

Differential Revision: D1092741
2013-12-13 12:39:15 -08:00
Abel Nieto 1a8a4e2f1b Make FrozenSet a collection.
Flip the switch and make FrozenSet a full-blown collection.

This wires up support for literal syntax, casting to bool,
and materialization and magic methods.

Reviewed By: @elgenie

Differential Revision: D1060075
2013-12-13 12:39:15 -08:00
Paul Tarjan 6e2310dfd7 import skipif sections from zend tests
We've been working around various issues (the win32 tests, many of the blacklists) where the tests were actually telling us in what cases they shouldn't be run.

Very few tests actually pass now but I think this is the right thing to do

Reviewed By: @alexmalyshev

Differential Revision: D983880
2013-12-13 12:39:06 -08:00
Jan Oravec 82eebe1104 Fix warning with tvSet(make_tv<KindOfNull>(), dst)
make_tv<KindOfNull>() creates a temporary TypedValue with uninitialized
m_data field. Using this temporary together with tvSet() results in a
warning, as the uninitialized value is assigned the destination's m_data
field.

Introduce tvSetNull() that avoids touching m_data.

Reviewed By: @jdelong

Differential Revision: D1090898
2013-12-13 11:21:04 -08:00
Paul Tarjan 2d4f9ee46b use same PHP Object for the same xmlNode
Instead of using the `_private` like zend does, I'll just have a thread local map on the side. I'm a bit worried that `_private` is used by other places so this seems safer and easier to reason about.

Reviewed By: @alexmalyshev

Differential Revision: D1071499
2013-12-13 11:20:59 -08:00
Paul Tarjan 3c97357707 blacklist bug36999
Broken on travis witha  SoapFault which I know nothing about.

Reviewed By: @scannell

Differential Revision: D1093510
2013-12-13 11:20:54 -08:00
Edwin Smith 5ff2e63748 Convert IRTrace::m_blocks from std::list to smart::vector
Use smart::vector instead of std::list in IRTrace

Reviewed By: @swtaarrs

Differential Revision: D1077237
2013-12-13 11:20:49 -08:00
Sara Golemon 965441c12e Ignore this test in the OSS build (for now) 2013-12-12 20:03:28 -08:00
Sara Golemon 2084216639 Skip tests when we don't have enough gd support
Also enable imagerotate() in OSS build.
2013-12-12 20:03:28 -08:00
Sara Golemon 52158dfb0c No longer look for GD, it's now bundled.
Instead look for its optional dependencies
* libfreetype
* libjpeg
* libpng
* libvpx
2013-12-12 20:03:28 -08:00
Owen Yamauchi bbbd10db4f Massage vixl's register abstractions into shape
The thesis of this diff is to introduce implicit conversions between
vixl::CPURegister and PhysReg, the same way we have for the x64 register
classes.

- I removed the concept of "no register" from vixl. It overlaps with
  "invalid register" and was kind of confusing.

- constexpr all the things

- Add the implicit constructor and conversion operator to PhysReg

I considered making the vixl abstractions mirror the asm-x64
abstractions exactly -- i.e. get rid of the class hierarchy -- but that
would be too disruptive. I think this is all we'll need to do.

I also haven't made implicit conversions between PhysReg and
vixl::FPRegister yet. We still need to sort out the way PhysReg
represents SIMD registers internally (changing the number of GP regs
isn't as simple as changing that constant) but that can be done in a
future diff.

Reviewed By: @edwinsmith

Differential Revision: D1091795
2013-12-12 20:03:28 -08:00
Edwin Smith f893fa2f14 Rename XMM to SIMD in a bunch of places to remove x86 smell
Trying to limit the term XMM to x86-specific code.  Everywhere
else we'll refer to SIMD registers.

Reviewed By: @ottoni

Differential Revision: D1091895
2013-12-12 20:03:28 -08:00
Drew Paroski 7193f48b48 Change the HHBC spec as needed to support the mechanics of try/finally
Reviewed By: @edwinsmith

Differential Revision: D1092390
2013-12-12 20:03:28 -08:00
mwilliams 1159ed5044 Generate a pid.map file when we unmap parts of the text section
The perf tool won't lookup symbols for parts of the binary
that aren't file mapped, so provide a perf-pid.map file when we
do that.

Reviewed By: @bertmaher

Differential Revision: D1091918
2013-12-12 20:03:28 -08:00
Paul Tarjan c825b734c6 ini_get('date.timezone') shouldn't guess
It should only return the timezone that was expclitily set.

Reviewed By: @JoelMarcey

Differential Revision: D1091812
2013-12-12 20:03:27 -08:00
Paul Tarjan 00ca68a715 import libgd from zend
I tried puling in the real `libgd` but it turns out php-src forked the library pretty hard and didn't contribute back. Instead I'll just pull in their fork.

This is a straight copy and then I fixed all the stupid C -> C++ stuff and wrote the `php_compat.h` to shim.

Reviewed By: @alexmalyshev

Differential Revision: D1083759
2013-12-12 20:03:27 -08:00
Paul Tarjan 668d434066 Fill out NEWS for some old releases a bit
I went throught the tasks for the last few releases and put down some things. Can anyone else notice other big things in your releases? I still have to fill out all the OSS stuff in Mark's but they are all on stickeys at the office.

Reviewed By: @jdelong

Differential Revision: D1091115
2013-12-12 20:03:27 -08:00
Max Wang 0301cbc29c Push KindOfStaticString TV in String opcode
Currently, we're pushing a KindOfString static StringData TV; let's use
KindOfStaticString instead.

Reviewed By: @jano

Differential Revision: D1090934
2013-12-12 20:03:27 -08:00
Guilherme Ottoni 82e971d73c Simplify instructions before looking them up in the CSE hashtables
I noticed some cases where CSE was missing opportunities because we
were first checking the CSE hashtable, then simplifying the
instruction (when missing in the CSE hashtable), and finally inserting
it into the CSE hashtable.  For instructions that actually got
simplified, this ordering caused redudant instructions to miss in the
CSE hashtable.  This diff fixes the problem by changing the order so
that instructions are first simplified, and then inserted in the
hashtable.

Reviewed By: @edwinsmith

Differential Revision: D1086429
2013-12-12 20:03:27 -08:00
Guilherme Ottoni 42be9c5853 Add contbuild config to run tests with hottrace regions
That's it.

Reviewed By: @swtaarrs

Differential Revision: D1086968
2013-12-12 20:03:27 -08:00
Guilherme Ottoni b2a9c02f22 Disable specialized type guards when guard relaxation is off
Otherwise we end up specializing way too many things, most for no use.

Reviewed By: @swtaarrs

Differential Revision: D1088082
2013-12-12 20:03:27 -08:00
Paul Tarjan 48c5e8cbbf sometimes the random variance is high
I've seen this test fail a few times since the variance on the random number generator is pretty high. Add some wiggle room.

Reviewed By: @jdelong

Differential Revision: D1091124
2013-12-12 20:03:26 -08:00
ptarjan 0a0b16c564 bump version for next dev release 2013-12-12 15:26:23 -08:00
Paul Tarjan 050c081b0e make rename_variation parallelizaable
Reviewed By: @JoelMarcey

Differential Revision: D1091010
2013-12-10 17:39:34 -08:00
Paul Tarjan f60871951a fix afile
Reviewed By: @andralex

Differential Revision: D1091032
2013-12-10 17:39:30 -08:00
Alex Malyshev 3ea5f063f1 Implement GlobIterator
Required changing the behavior of DirectoryIterator and
FilesystemIterator. DirectoryIterator should iterate through the base
names of files, but FilesystemIterator iterates through full
pathnames.

Fix a bug in RecursiveIteratorIterator along the way

Reviewed By: @ptarjan

Differential Revision: D1034196
2013-12-10 17:39:29 -08:00
Paul Tarjan 6650bf347b fix more vfprintf
Reviewed By: @JoelMarcey

Differential Revision: D1091125
2013-12-10 17:39:25 -08:00
Alex Malyshev a732e038ed Add the Reflection class
We never defined the actual Reflection class, which just has two
static methods in it.

Appeases yii, which has a requirements check that determines whether
the Reflection extension is enabled by searching for this class.

Reviewed By: @ptarjan

Differential Revision: D1086615
2013-12-10 12:13:55 -08:00
Edwin Smith 024ef0aa29 Fix up the const-to-variant code
Several cases were doing it wrong.  Found them while auditing
implicit Variant constructors.

Reviewed By: @jdelong

Differential Revision: D1077928
2013-12-10 12:13:48 -08:00
Jan Oravec aa4cd4f6ad Use std::atomic<> for condition flags
Convert atomic_acquire_load and __sync_fetch_and_{and,or} on condition
flags to std::atomic<>.{load,fetch{and,or}}.

Reviewed By: @jdelong

Differential Revision: D1084266
2013-12-10 12:13:45 -08:00
Jan Oravec a100e2c3af Use std::atomic<> in TreadHashMap
Convert TreadHashMap from atomic_{acquire_load,release_store} to
std::atomic<>.{load,store}.

Reviewed By: @jdelong

Differential Revision: D1084196
2013-12-10 12:13:41 -08:00
bsimmers 75b2da18c1 Loosen refcount verifier on DefLabels
Sometimes we end up with a DefLabel that defines a value with type
Cell, but only has one incoming value with an uncounted type. The Cell dest of
the label won't have any tracked references since it's always uncounted, so
recognize that situation and don't abort.

Reviewed By: @ptarjan

Differential Revision: D1090701
2013-12-10 12:13:33 -08:00
Paul Tarjan 928cf31b83 remove unused code
Reviewed By: @alexmalyshev

Differential Revision: D1090454
2013-12-10 12:13:29 -08:00
mwilliams aa602c715c Fix read past end of buffer in IpBlockMap
The code used to allow a read of the bit immediately past
the end of the buffer - and since both children should be nullptr
in that case, the value doesn't matter. But its still an illegal
read, and the ASAN build was catching it.

Reviewed By: @edwinsmith

Differential Revision: D1089631
2013-12-10 09:33:01 -08:00
Paul Tarjan 05c3fa5efe fixup yaml to be c++ compliant
`fpermissive` is bad and we shouldn't set it

Reviewed By: @scannell

Differential Revision: D962946
2013-12-10 09:33:00 -08:00
Andreas Fischer a7146f2010 Typo: compatability -> compatibility (II)
Typo: compatability -> compatibility (src)

Closes #1328

Reviewed By: @edwinsmith

Differential Revision: D1089152

Pulled By: @scannell
2013-12-10 09:33:00 -08:00
Jordan DeLong f8e0acd947 Improve printing of ?Obj types
Reviewed By: @edwinsmith

Differential Revision: D1088697
2013-12-10 09:33:00 -08:00
Jordan DeLong 3304d86ba1 Relax bytecode invariants about DV initializers
DV initializers had some rules about fallthrough, jumps to
the main entry point, and a requirement that they each only be a basic
block.  We violate these rules in array_filter.hhas and
array_map.hhas, and they currently don't seem to be needed.  This
changes the spec so they are just alternative entry points based on
argument count, and updates hhbbc to not assume those things.  We
still have a few reasonable rules about where the entry points can be
(they must be in the primary function body, and cannot be in the
middle of an FPI region).

Reviewed By: @edwinsmith

Differential Revision: D1088641
2013-12-10 09:32:59 -08:00
Jordan DeLong 0ca9862bd9 Add an hhas test case for DV initializers with fault/catch regions
From what I can tell, nothing rules this out in the bytecode
spec.  Wrote this to see if it actually worked, which it seems to.

Reviewed By: @edwinsmith

Differential Revision: D1010605
2013-12-10 09:32:59 -08:00
Jordan DeLong 4e97ca67fb Propagate states across factored edges mid member-instruction
Member instructions are fairly unusual in that they can throw
with a state reflecting changes in the middle of their execution.  The
normal model in HHBBC for PEIs (potentially exception-throwing
instructions) is to propagate the state before the instruction has
begun execution, so these need to be handled specially by explicitly
propagating the states before each dim.

Reviewed By: @edwinsmith

Differential Revision: D1088633
2013-12-10 09:32:58 -08:00
Jordan DeLong 168d6fc15b Use getScalarValue instead of ad hoc cases for scalar array pairs
Reviewed By: @markw65

Differential Revision: D1024221
2013-12-10 09:32:58 -08:00
Owen Yamauchi 6f98d64c3c Speed up simulator's register-smashing code
I feel bad, because I wrote this originally. perf showed that this code
was really hot, so I rewrote it much simpler. I also fixed some mistakes
in the register-convention constants provided by vixl. This seems a
little wtf, but what they had there before definitely doesn't agree with
the documentation, as well as the implementation of
vixl::CPURegList::GetCallerSaved.

Reviewed By: @jdelong

Differential Revision: D1087062
2013-12-10 09:32:58 -08:00
Chip Turner b20473bf84 Re-introduce MySQL 5.6 client
This reverts e5cdbb1a67f28f94d43c83ff2627fd3eff8b3646 which
reverted the original 5.6 client update based on the issue from 3340526.
With third-party patched with D1088527 fixing the double-close, this
diff restores 5.6 to fbcode.

Original 5.6 diff: D1058111
Reverted in: D1087701
MySQL fixed in: D1088426
third-party patched in: D1088527

Reviewed By: jicongrui

Differential Revision: D1088758
2013-12-10 09:32:57 -08:00
Ryan Skidmore 078f8473b2 Fix typos (src)
Fix typos (src)

Closes #1329

Reviewed By: @edwinsmith

Differential Revision: D1089170

Pulled By: @scannell
2013-12-10 09:32:57 -08:00
Edwin Smith 132526bdc3 Parameterize XLS with a register abi descriptor.
Create an Abi POD struct that encapsulates details about the
ABI that the register allocator needs to know.  For now, it's
just what register are available to be allocated and which
ones are callee-saved registers.

Reviewed By: @jdelong

Differential Revision: D1088590
2013-12-10 09:32:57 -08:00
Simon Welsh 05650dc744 Pass the length along when outputting from printf
If there's no length, the result is treated as a
null-terminated string which means that null characters incorrectly stop
the output.

Closes #1322

Reviewed By: @ptarjan

Differential Revision: D1087212

Pulled By: @scannell
2013-12-10 09:32:56 -08:00
Paul Tarjan 37034dd221 Hook IniSetting::Bind to ini_get()
This started as a small diff to get `date.timezone` working and escalated to this.

I did it as a small change with just adding a get callback to the bind call and used it during the get. I debated having a side-index of everything that has been set so far and echo it back, but the setting might muck with the data before saving so I think this is more generic.

I think in a perfect world you could just register their name, type, and an optional validator, but that's for later when this gets cumbersome.

Reviewed By: @sgolemon

Differential Revision: D1088980
2013-12-10 09:32:56 -08:00
Paul Tarjan f745001876 update PCRE_VERSION
Stop lying. Symfony checks this and throws a warning saying we are too old when we aren't.

Reviewed By: @sgolemon

Differential Revision: D1088930
2013-12-10 09:32:56 -08:00
Paul Tarjan 35d153b6cd mark systemlib classses as \!isUserDefined()
I can't beleive we lived this long with this `if (false)`

Reviewed By: @alexmalyshev

Differential Revision: D1088081
2013-12-10 09:32:55 -08:00
Paul Tarjan f02ebaeb3c remove functions we don't implement
These fly completly in the face of the `function_exists` detection that you are supposed to use. The worse offender was a completly unimplement extension of image magic.

I ran `git grep` in `runtime/ext`

Reviewed By: @sgolemon

Differential Revision: D1088798
2013-12-10 09:32:55 -08:00
Paul Tarjan 1563cfd1d1 import files even if they have an ini section
I was lying a little bit and not importing these tests since they have no chance of passing since our INI story sucks. I think we shouldn't be cheating with our numbers and instead should have these and be able to work towards them passing.

Reviewed By: @JoelMarcey

Differential Revision: D1082559
2013-12-10 09:32:35 -08:00
Paul Tarjan 8bc5d66a14 ext_zend_compat improvements
These were brought on by importing `fileinfo`. I ended up doing it natively in HHVM, but these bugfixes are still useful. The worst part is the preg stuff since our code diverged so much from zend I had to just copy theirs. Some day we hopefully can reconcile them.

Reviewed By: @paroski

Differential Revision: D1025745
2013-12-09 18:44:01 -08:00
Ryan Skidmore 2ff6d3ca00 Fixed typos
Summary: Fixed typos

Reviewed By: @scannell

Pulled By: @scannell

Test Plan:
 - php -l and checkModule
 -
2013-12-09 07:22:23 -08:00
Andreas Fischer 7aee17cb65 Typo: compatability -> compatibility (I)
Summary: Typo: compatability -> compatibility (cmake)

Reviewed By: @scannell

Pulled By: @scannell
2013-12-09 07:01:50 -08:00
mwilliams beb2c83548 Don't eagerly start threads after warmup
If we've requested a warmup phase, we limit the number
of threads initially, and then allocate more after a suitable
warmup period.

We don't need to eagerly alloate them though - we can stick with the
existing code which only allocates as necessary.

Reviewed By: @jdelong

Differential Revision: D1087578
2013-12-08 10:33:28 -08:00
Jordan DeLong 4668713374 Disable some zend tests that are failing on master
Reviewed By: @dariorussi

Differential Revision: D1088692
2013-12-08 10:33:09 -08:00
Jordan DeLong b245336ea3 Taskify some TODOs for hhbbc
Made tasks; removed some comments.

Reviewed By: @edwinsmith

Differential Revision: D1088620
2013-12-08 10:30:18 -08:00
Jordan DeLong 67e991b0af There's no "if for" statement
This is for @alexmalyshev.

Reviewed By: @alexmalyshev

Differential Revision: D1088412
2013-12-08 10:30:15 -08:00
Jordan DeLong 4fa789a460 Fix a bug I had in AsyncAwait's hhbbc implementation
AsyncAwait pushes an HHBC "Cell" flavor, which corresponds to
the TInitCell type in HHBBC (it can't be KindOfUninit).  Oops.

Reviewed By: aravind

Differential Revision: D1088391
2013-12-08 10:30:12 -08:00
Jordan DeLong eabd6792b6 Update HHBBC fault funclet assumptions for try/finally changes
The main change is that fault funclets now can be coverted by
protected regions.  There were also some issues with having multiple
protected regions pointing to the same fault funclet, even though I'd
already updated the spec to make that legal.  This diff also changes
things to find funclet handler extents using the same logic as the
verifier (relying on funclet bodies being contiguous), since it's
easier to do than forward propagating in RPO until you find an Unwind
now that there can be try/catch blocks inside the funclets.

Reviewed By: @edwinsmith

Differential Revision: D1088288
2013-12-08 10:30:08 -08:00
Jordan DeLong 72a60e57d8 Replace some CHECK/DCHECK macros with {always_,}assert
Facebook: OSS warnings are ok.

Reviewed By: @ptarjan

Differential Revision: D1084382
2013-12-08 10:30:05 -08:00
Jordan DeLong f66acb92f6 Add smart_new and smart_delete
Instead of manually calling placement new or destructors with
smart_malloc and smart_free.  Since these are type-aware, they also
can easily use smartMallocSize/smartFreeSize to make a smaller
allocation.

Reviewed By: @swtaarrs

Differential Revision: D1084270
2013-12-08 10:30:02 -08:00
Jordan DeLong a1c36a0663 Clean up and fix some bugs in setOpProp and incDecProp
These functions were a bit hard to understand, and both
contained a reference leak in cases involving magic getters.  There
were also some behavioral differences from zend with protected
properties that are fixed.  It's very tempting to try to template this
and combine the two functions---they're almost the same, but just
barely not quite, so I'm leaving them separate for now.

Reviewed By: @dariorussi

Differential Revision: D1084236
2013-12-08 10:29:59 -08:00
Jordan DeLong 90302d9b12 Fix a reference leak in setop
I think there are a couple others relating to dynamic
properties and magic methods, but this one is independent enough for
its own diff.

Reviewed By: @swtaarrs

Differential Revision: D1084106
2013-12-08 10:29:56 -08:00
Jordan DeLong ad522a5d12 Allow magic property methods to be entered recursively
Common idioms in php require magic methods to be allowed to
be entered recursively.  This diff makes hhvm mostly match zend on the
behavior here: recursion is allowed until it hits the same magic
method for the same property on the same instance.  For now there are
still some slight divergences in cases where there are also declared
protected properties with the same name (and we'll differ for now in
some cases where zend SEGVs).

There are a few things still here that look like bugs in some object
property reference counting (at least one case with setop of an object
prop seems to leak a reference).  I've tasked them to look at later so
we can get this in, though.  (They aren't all related to magic
methods.)

Reviewed By: @swtaarrs

Differential Revision: D1083309
2013-12-08 10:29:53 -08:00
Jordan DeLong 0aa65af3d7 Improve assertion for pmethodCacheMissPath---update write lease comments
Reviewed By: @bertmaher

Differential Revision: D1083718
2013-12-08 10:29:49 -08:00
Jordan DeLong e380d389b8 Stop dumping HNI extension bytecode in Eval.DumpBytecode=1
This just needs to mask out the low bit the way normal
systemlib works.  If you want to print the extension bytecodes, you
can set Eval.DumpBytecode=3.

Reviewed By: @markw65

Differential Revision: D1087356
2013-12-08 10:29:46 -08:00
Chip Turner 5838ed9cd6 Revert "Switch to the MySQL 5.6 client"
Dragon has encountered an issue with double close()'s, which is
an issue in the underlyng libmysqlclient library.

This reverts commit 9e5a733ca19b8a199eb7742f90e6c80e46860d1d.

Reviewed By: @tudor

Differential Revision: D1087701
2013-12-08 10:29:42 -08:00
Sara Golemon fc37017a7e Allow building ext_zend_compat extensions
By default, zend source compatability remains disabled,
however you can now explicitly request compilation of the
infrastructure and the extensions it supports via:

  cmake -DENABLE_ZEND_COMPAT=ON .

Note that CMake caches -D defines between runs, so a later call
without ENABLE_ZEND_COMPAT will still retain the option enabled.
Either explicitly set it to OFF, or delete CMakeCache.txt if
switching between the two.
2013-12-07 08:43:32 -08:00
Paul Tarjan 57ff7e8300 record filter test with parameterization
This shouldn't require you to be in the root when running.

Reviewed By: aravind

Differential Revision: D1087979
2013-12-06 16:01:24 -08:00
mwilliams 392322f9c0 Fix cpu identification
I broke this when cleaning up some -fstrict-alias warnings.

Reviewed By: @jdelong

Differential Revision: D1087374
2013-12-06 16:01:21 -08:00
Tianjiao Yin 67b1e660db filter_input_array behaves differently from stock php
fix `filter_input_array(INPUT_SERVER, FILTER_UNSAFE_RAW)`

Reviewed By: @ptarjan

Differential Revision: D1081292
2013-12-06 16:01:15 -08:00
Tianjiao Yin 9fa72145f0 Set json_last_error + message from json_encode
Currently json_last_error and json_last_error_msg only return meaningful values after json_decode, which is confusing since the functions are defined and at first seem like they are fully implemented.

Reviewed By: @ptarjan

Differential Revision: D1078012
2013-12-06 16:01:11 -08:00
Paul Tarjan 110f0c8fe7 fix fprintf flakeyness
I love zend

Reviewed By: @alexmalyshev

Differential Revision: D1087430
2013-12-06 13:40:26 -08:00
Paul Tarjan a906928aff Revert "Add support for IsScalar"
This reverts commit 68bef5478c2495c8328b68b94f687edf4e52b9ae.

Reviewed By: aravind

Differential Revision: D1087216
2013-12-06 13:40:20 -08:00
Owen Yamauchi 9b02b7a35d Disable inlining in ARM mode
It's not the ARM part that kills us here, but the interp-everything
part. The inlining code fails in a couple of different ways if the
instruction that pushes the ActRec is interped. We don't really have a
way to cleanly bail out of inlining if we discover that it's impossible
below the IRTranslator level.

Rather than put in a bunch of effort to sort out that situation,
I'm opting to punt until we get proper ARM codegen for FPush* and FCall,
at which point we should be able to turn on inlining without trouble.
I've tasked it so we don't forget.

Reviewed By: @jdelong

Differential Revision: D1085589
2013-12-06 10:15:57 -08:00
Dario Russi e24812581f Adding a possible cache for enum values based on static arrays
When defining an enum it is useful to have the values cached in a static array given Enum don't change value

Reviewed By: @markw65

Differential Revision: D1086167
2013-12-06 10:15:57 -08:00
Joel Marcey ea78e22439 Make the "Run Test File" command better.
Make the "Run Test File" command for tests that don't have an expected status beter for frameworks that don't run in parallel. For those frameworks, the test run command does not contain the individual test. And currently we can't run the individual test that is not behaving as expected without jumping through a few manual hoops. Turns out there is access to the test name while we are running, even serially. Use it.

Reviewed By: @alexmalyshev

Differential Revision: D1085298
2013-12-06 10:15:57 -08:00
Alex Malyshev 82c048f161 Correctly set connection fields in PDOMySqlStatement
PDOStatements have a field for their PDOConnection. Turns out
PDOMySqlStatements have an extra field that stores their
PDOMySqlConnection, which they use instead. Synchronize the two,
as currently it's not possible to run pdo_handle_error without
hitting throw_null_pointer_exception().

Reviewed By: @ptarjan

Differential Revision: D1084318
2013-12-06 10:15:56 -08:00
Owen Yamauchi 6daaa7c767 Stop VIXL from creating this vixl_stats.csv file
This file gets created unconditionally, for stats logging, even if you
don't have logging turned on. This is annoying. I'm removing that code
from the simulator; if you want stats logging, it's easy enough to add
it yourself by creating vixl::Instrument and adding it as a decoder
visitor (like I do with PrintDisassembler in enterTC).

Reviewed By: @swtaarrs

Differential Revision: D1084658
2013-12-06 10:15:56 -08:00
Owen Yamauchi a06c1ac005 Implement reusable service requests for ARM
While doing this, I made CodeCursor not depend on X64Assembler and moved
it into a different file.

Reviewed By: @jdelong

Differential Revision: D1083358
2013-12-06 10:15:56 -08:00
Jordan DeLong ad8dfe4d6d Replace unused ObjectData::HasCallStatic with ObjectData::HasClone, use it
A measurable percentage of L1 dcache misses in production are
coming from lookups of the __clone function in ObjectData::cloneImpl.
If a decent number of them don't have custom __clone functions, we can
just check an o_attributes bit (which we just checked in ::clone, so
it should still be in dcache).  (This diff doesn't avoid the redundant
load of o_attributes, though.)

Reviewed By: @ptarjan

Differential Revision: D1070758
2013-12-06 10:15:55 -08:00
Enis Rifat Sert 0e7c2522af preg_replace error return values
Fixed preg_replace error return values

Reviewed By: @ptarjan

Differential Revision: D1077072
2013-12-06 10:15:55 -08:00
Joel Marcey 6bacabaccf Remove --no-edit from pull requests
--no-edit for pull requests was causing issues on Ubuntu 12.04 running the script.

Error was: error: unknown option `no-edit'

Took it out. Things ran fine. Pull requests still worked for doctrine and pear.

Reviewed By: @alexmalyshev

Differential Revision: D1084828
2013-12-06 10:15:55 -08:00
Joel Marcey 7042330fa0 Create php symlink for OSS
We don't have a php symlink to the hhvm executable in oss land. Create one so Pear can work correctly. Otherwise we will literally have 0% for Pear.

Reviewed By: @ptarjan

Differential Revision: D1084685
2013-12-06 10:15:55 -08:00
Sara Golemon 1d5f027b1f Refactor intl subcomponents into the intl extension
Mostly organizational frufaru
This moves us away from having multiple icu_* extensions
and closer to having a single 'intl' extension
similar to Zend.  icu_ucnv and icu_uspoof will be
folded in when they are converted to HNI.

Future intl classes (DateFormatter) will be added here.

Reviewed By: @ptarjan

Differential Revision: D1083189
2013-12-06 10:15:48 -08:00
Emil Hesslow 6fc1f1eb3f Some changes to Zend test importer
- Make it not fatal if the zend path don't contain a / in the end
- Better error message when using --only and it doesn't match any files

Reviewed By: @ptarjan

Differential Revision: D1083278
2013-12-06 09:14:22 -08:00
Paul Tarjan f34b3e2218 remove __tmp_oo_rename3
this test didn't clean up after itself

Reviewed By: enis

Differential Revision: D1084661
2013-12-06 09:13:31 -08:00
Bert Maher fb151725d2 Improve FPushCuf -> FPushObjMethod transformation
The previous version of this optimization was a bit too picky
about where it found the object input to the FPushCuf.  This fixes it
up so it catches most of the hot cases in www.

Reviewed By: @swtaarrs

Differential Revision: D1054142
2013-12-05 12:03:41 -08:00
Jordan DeLong 881604d2c0 Rename ObjectData::HasClone to HasCppClone
This means the ObjectData has a C++-level clone
implementation.  Also clean up some duplicate specifications of the
template parameters for ExtObjectDataFlags.

Reviewed By: @edwinsmith

Differential Revision: D1070691
2013-12-05 12:03:40 -08:00
bsimmers 7bc30bf3a4 Runtime option to limit the amount of code we translate
This allows us to stop translating gracefully once we've emitted a
certain amount of code to a. I also fixed the names of the RuntimeOption
members to match the config options they map to.

Reviewed By: @ottoni

Differential Revision: D1081564
2013-12-05 12:03:40 -08:00
Paul Tarjan 92346aa00d handle running the script from any dir
I shouldn't require you cd to `hphp`

Reviewed By: @jdelong

Differential Revision: D1083592
2013-12-05 12:03:40 -08:00
Guilherme Ottoni 614a8fed9d Get tests passing again with the region JIT
Some of the work during lockdown exposed a few issues with the region
JIT enabled.  Most of the issues were because jump optimizations was
mutating an instruction into another one with a different number of
dests, including SideExitJCCs and SideExitGuardLoc.  These were fixed
by making these instructions have the similar dests as their
corresponding instructions.  For the JCCs, ideally we should get rid
of their None dests. I tried that, but unfortunately it's not that
simple and will require changes to the simplifier at least.  To
unblock work on the region JIT, I'm taking the simplest approach here
by making SideExitJCCs have a dest too, and I'll task cleaning up the
dests of all these instructions.

Reviewed By: @swtaarrs

Differential Revision: D1082383
2013-12-05 12:03:39 -08:00
Joel Marcey 6d5b5126a0 Fix get runtime executable for oss
The check for the hhvm runtime build in oss land was wrong. This attempts to fix that. Also, we have no "php" symlink to hhvm in oss world, so I removed that check.

Reviewed By: @sgolemon

Differential Revision: D1083192
2013-12-05 12:03:39 -08:00
aravind 0770b4d28d Add support for IsScalar
Add support for IsScalar in IsType instruction.

Reviewed By: @ottoni

Differential Revision: D1045411
2013-12-05 12:03:39 -08:00
Joel Marcey 878ceb348c Update Pear hash
The Pear folks have accepted my pull request. Use the pear git source again. We are actually losing 2.5% on Pear for some reason, but this is happening with the current hash (as shown in our graph) or with this new hash. So that is a wash. Use the newer hash.

Reviewed By: @alexmalyshev

Differential Revision: D1082918
2013-12-05 12:03:38 -08:00
Sara Golemon f240dfe091 Allow loading of named mini-systemlibs
The Intl extension is massive and is best
organized into multiple sub-extensions (icu_ucnv, icu_locale,
icu_num_fmt, icu_date_fmt, etc...).

Extending the loadSystemlib() helper to load from multiple
systemlibs allows us to follow this pattern in the intl module:

  void moduleInit() override {
    BindIntlFuncs();
    loadSystemlib(); // loads intl's main mini-systemlib
    BindLocaleFuncs();
    loadSystemlib('icu_locale');
    BindUCnvFuncs();
    loadSystemlib('icu_ucnv');
    // etc...
  }

Reviewed By: @ptarjan

Differential Revision: D1081324
2013-12-05 12:03:38 -08:00
Sara Golemon 43a407c5c4 Add ICU Locale class
More intl implementations

Reviewed By: @ptarjan

Differential Revision: D1081026
Differential Revision: D1083822
2013-12-05 12:03:38 -08:00
Paul Tarjan a810b449ee re-import php-src tests
Now that lockdown is done we are at 50.77%. This is from the newest 5.5
branch. 18b7875fab791bb88d73df360fd91f1ace70c5b3 to be exact.

The following tests were added to the bad directory. All of them for 2
reasons. Some date format thing changed (years are now 2 digits) and
they now are setting a constant as case-insensitive which we emit a
warning for so it breaks the test.

* test/zend/bad/ext/date/tests/DateTime_format_basic2.php
* test/zend/bad/ext/date/tests/date_constants.php
* test/zend/bad/ext/date/tests/gmdate_variation13.php
* test/zend/bad/ext/standard/tests/file/file_get_contents_basic.php
* test/zend/bad/ext/standard/tests/file/file_get_contents_file_put_contents_basic.php
* test/zend/bad/ext/standard/tests/file/file_get_contents_file_put_contents_variation1.php
* test/zend/bad/ext/standard/tests/file/file_get_contents_file_put_contents_variation2.php

The following tests failed in repo mode, so I made them `.norepo`:

* test/zend/good/Zend/tests/bug47593.php
* test/zend/good/Zend/tests/bug60771.php
* test/zend/good/Zend/tests/error_reporting03.php
* test/zend/good/Zend/tests/error_reporting08.php
* test/zend/good/Zend/tests/halt_compiler2.php
* test/zend/good/ext/exif/tests/bug62523_1.php
* test/zend/good/ext/exif/tests/bug62523_2.php
* test/zend/good/ext/exif/tests/bug62523_3.php
* test/zend/good/ext/exif/tests/exif_encoding_crash.php
* test/zend/good/ext/sqlite3/tests/sqlite3_23_escape_string.php
* test/zend/good/ext/standard/tests/array/sizeof_variation4.php
* test/zend/good/ext/standard/tests/file/bug30362.php
* test/zend/good/ext/standard/tests/file/readfile_variation6.php
* test/zend/good/ext/standard/tests/streams/stream_resolve_include_path.php
* test/zend/good/ext/standard/tests/strings/wordwrap.php
* test/zend/good/ext/standard/tests/url/parse_url_basic_001.php
* test/zend/good/ext/zlib/tests/gzcompress_variation1.php
* test/zend/good/ext/zlib/tests/gzdeflate_basic1.php
* test/zend/good/ext/zlib/tests/gzdeflate_variation1.php
* test/zend/good/ext/zlib/tests/gzencode_variation1-win32.php
* test/zend/good/ext/zlib/tests/gzencode_variation1.php
* test/zend/good/ext/zlib/tests/gzuncompress_basic1.php
* test/zend/good/tests/classes/unset_properties.php
* test/zend/good/tests/lang/include_variation3.php

Reviewed By: @JoelMarcey

Differential Revision: D1081723
2013-12-05 12:03:26 -08:00
seanc f32b9e6b15 Further split Travis test matrix
Summary: Travis tests are still timing out, split them up as much as
possible to see if we can get more reliable results.
2013-12-05 07:42:44 -08:00
Joel Marcey c0199e49a9 Update phpbb3 hash
I hope they accept my pull request, but for now let's just use my repo.

https://github.com/phpbb/phpbb/pull/1908

Reviewed By: @alexmalyshev

Differential Revision: D1081325
2013-12-04 14:30:58 -08:00
Abel Nieto 200d343729 Change the way in which objects are tagged as collections.
With the introduction of FrozenSet in D1060075, we ran out of bits
in o_attributes to represent new collection types.

This diff changes things so that we only store a 1-bit attribute
IsCollection in o_attributes, indicating (suprise suprise) whether
a particular ObjectData  is a collection or not.

If IsCollection is set, then the precise collection type
(which remains an element of Collection::Type) can be found in
o_subclassData.u16.

Reviewed By: @paroski

Differential Revision: D1070558
2013-12-04 14:30:58 -08:00
Owen Yamauchi ddc04e1a84 Add build flag for ARM mode default
Reviewed By: @swtaarrs

Differential Revision: D1081124
2013-12-04 14:30:57 -08:00
Sean Cannella 51a06f9806 $_SESSION should start uninitialized
$_SESSION should start uninitialized on each request

Reviewed By: @swtaarrs

Differential Revision: D1080275
2013-12-04 14:30:57 -08:00
Max Wang c78a16e0c8 Forgot IOP_ARGS in doFPushCuf declaration
Reviewed By: @jano

Differential Revision: D1081437
2013-12-04 14:30:57 -08:00
Abel Nieto f18e7f4b0e Fix bugs in Set::map
There were two problems with Set::map():

  * the return type of the callback was not being checked, so we could
    end up with a Set of a type other than int or string.

  * we also weren't checking for duplicates -- so, for instance, calling
    map with a constant function (constant in the mathematical sense)
    would give us back a set with repeated elements.

Fix the two points above by making Set::map() use the regular add()
operation (which automagically takes care of everything).

Reviewed By: @paroski

Differential Revision: D1069261
2013-12-04 14:30:56 -08:00
Jordan DeLong b63bf51723 Give a better error message when hhas systemlib is broken
Reviewed By: @alexmalyshev

Differential Revision: D1079598
2013-12-04 14:30:56 -08:00
Alan Frindell caf64ec978 Remove extra realloc/NULL termination from LibEventTransport
All callers of getPostData use the size arg correctly.  I tried searching the git history for why this was ever done, and it goes back to before when hphp was moved from svn to git in 2008.

Reviewed By: @markw65

Differential Revision: D1073159
2013-12-04 14:30:56 -08:00
Alex Malyshev 47863c8add Stop invalid Pipe objects from always asserting in dtor
Pipe::closeImpl did not have a good check for whether the pipe needed
closing. Fix that, and add the warning that zend prints on invalid args
to popen()

Closes #1313

Reviewed By: @scannell

Differential Revision: D1079485
2013-12-04 14:30:56 -08:00
Andrei Alexandrescu d9b4ee6947 Fix for code smell reported by Robert Henry
Robert, an old friend, found a bug in our code.

Reviewed By: @markw65

Differential Revision: D1080348
2013-12-04 14:30:55 -08:00
Owen Yamauchi 05cc1a7862 Put HHVM_ARCH in $_ENV, use it to skip strtotime_leak.php
In the interest of maintaining by sanity by getting automated testing
for ARM mode set up ASAP, I'm putting off (and tasking) figuring out
what's going on with strtotime_leak.php in ARM mode. I added something
to $_ENV that allows PHP code to check what arch it's running as, and
we'll skip strtotime_leak.php if we're in ARM mode.

As part of this, I pulled arch() into its own header file to avoid
including translator-inline.h from the files where the env vars are set
up (it didn't seem right).

Reviewed By: @jdelong

Differential Revision: D1080752
2013-12-04 14:30:55 -08:00
Owen Yamauchi 4fd0be47e6 Get ARM mode passing again
quick, slow, and zend/good almost all pass with this diff, after a bunch of
lockdown breakage. I say "almost" because strtotime_leak.php still
fails. I believe that's a consequence of interp'ing everything, although
there may be a real memory leak there. I'll deal with that in an
upcoming diff.

- Since InterpOne has catch traces now, we can't punt on BeginCatch and
  EndCatch anymore. It seems that for the time being, we can skate by
  without actually implementing catch traces, though. The stack is
  always spilled before InterpOne, and because everything is InterpOne'd
  we're not actually holding anything in registers (so we don't need to
  restore them).

- NewStructArray wasn't accounted for in all places in translator.cpp.

- I reduced the amount of work that mixedbag.php does, so that it
  completes in a reasonable amount of time in ARM mode. It's still
  executing all the same code, just fewer times.

Reviewed By: @jdelong

Differential Revision: D1080648
2013-12-04 14:30:55 -08:00
Jordan DeLong 5acc30fd93 Reorder IsTypeL arguments to match other LA,OA pairs
It's arguable that maybe OA,LA would be a nicer order, but
all the other opcodes that have both subops and a LA take them in the
LA,OA order.  (In general, it appears OA always comes last unless
there is an MA, right now.)  Also remove unused isTypePred thing.

Reviewed By: @swtaarrs

Differential Revision: D1079371
2013-12-04 14:30:54 -08:00
Jordan DeLong ecd4a82dd5 Update hhbbc for the IsType subobcode change
Just adds a function mapping from IsTypeOp to the type
opcodes.

Reviewed By: aravind

Differential Revision: D1079276
2013-12-04 14:30:54 -08:00
Jordan DeLong 7e112d6f81 Convert IsTypeOp to an enum class
Also name the types more like other type names (in both
JIT::Type and HHBBC) for macro-friendliness, and remove default cases
from switches so we'll find places that need to be updated when we add
new cases to the enum.

Reviewed By: aravind

Differential Revision: D1079271
2013-12-04 14:30:54 -08:00
Max Wang 1ca0022e67 Use macros in place of explicit iop*() arguments
This allows us to easily (and conditionally) add additional arguments.

Reviewed By: @jano

Differential Revision: D1075399
2013-12-04 14:30:53 -08:00
James Miller c2c98a584c Implement password extension
This uses @ircmaxell's password_compat library to implement the
password extension on top of the underlying crypt functions.

Closes #992
Closes #1303

Reviewed By: @ptarjan

Differential Revision: D1078315

Pulled By: @scannell
2013-12-04 14:30:14 -08:00
Philippe Ajoux 11a48c87a2 Add PageletServerTaskEvent.
Move PageletTransport definition in pagelet-server.h and create PageletServerTaskEvent to be used for integration with Asio.

Reviewed By: @jano

Differential Revision: D1069174
2013-12-04 11:38:25 -08:00
Alex Malyshev 97240eb364 ReflectionParameter works with parameters index instead of name
So it turns out ReflectionParameter::__construct(string, string) can
also be written as ReflectionParameter::__construct(array, string) and
the now supported ReflectionParameter::__construct(array, int).

Reviewed By: @ptarjan

Differential Revision: D1068773
2013-12-04 11:38:14 -08:00
Alex Malyshev 8f2addf3a4 Reimplement str_getcsv in C++
I originally wrote a hacky str_getcsv with that used fgetcsv() + temp
files in PHP to stop fatals in open source land. This fixes the perf
issues with the old implementation by not using files at all.

Closes #1079

Reviewed By: @scannell

Differential Revision: D999569
2013-12-04 11:38:08 -08:00
mwilliams 49c5186e54 Only enable ahot in RepoAuthoritative mode
In sandbox mode, files change, and we could translate
potentially unlimited numbers of functions into ahot.

Reviewed By: @swtaarrs

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

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

Reviewed By: @swtaarrs

Differential Revision: D1078789
2013-12-03 09:30:30 -08:00
Sean Cannella f81e40505e Fix OS X segfault on startup
Fix crash due to maybePop() call reading garbage out of the freelist the first time it is accessed.

Closes #1300

Reviewed By: @jdelong

Differential Revision: D1078982
2013-12-03 09:30:26 -08:00
Sean Cannella 37bc5974f7 Fix OSX warning
Fix OSX warning due to mismatched printf type

Reviewed By: @alexmalyshev

Differential Revision: D1078484
2013-12-03 09:30:22 -08:00
Surupa Biswas 1369b333d6 Parse fatal for Interface method bodies
Generate a parse-time fatal for interface methods with method bodies.

Reviewed By: @hermanventer

Differential Revision: D1062389
2013-12-03 09:30:14 -08:00
Drew Paroski 044ff2e0d0 Move Collection interface to the HH namespace
Closes #1003
https://github.com/facebook/hhvm/issues/1003

Reviewed By: anietoro

Differential Revision: D1079642
2013-12-03 09:30:10 -08:00
Guilherme Ottoni ec2813cf50 Move unique stubs to 'a'
Some of these may actually be hot, and they're small enough that
putting them in 'a' shouldn't hurt.

Reviewed By: @jdelong

Differential Revision: D1069482
2013-12-03 09:30:05 -08:00
Drew Paroski 2880070953 Avoid calling smart_malloc() to allocate 0 bytes in Vector
Some of the logic in the Vector implementation was unnecessarily calling
into smart_malloc() to allocate 0 bytes, which is wasteful. This diff fixes
the issue appropriately.

Reviewed By: anietoro

Differential Revision: D1079298
2013-12-03 09:30:01 -08:00
mwilliams 1cc4324ff7 Don't translate idx when JitEnableRenameFunctions is set
Users are supposed to be able to override idx with
their own version - but that doesn't work if we translate it
during bytecode emission.

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

Reviewed By: @dariorussi

Differential Revision: D1078332
2013-12-03 09:29:52 -08:00
Sara Golemon 3d242a6d9d Bump CMake required version to 2.8.7
Mini-systemlib embedding uses string(MD5 ...)
which is only available in CMake 2.8.7 or later.

Closes #1306
2013-12-03 09:28:05 -08:00
Chip Turner f6413a9d4c Switch to the MySQL 5.6 client
Due to the interdependencies between libraries, converting
portions of the codebase to the 5.6 client independently is not an
option.  This diff moves all of fbcode to 5.6 as well as updates the
async_mysql client to the newer, slightly modified async api.

This diff brings with it the new features in the 5.6 client, most
notably ipv6 support.  It also adds ipv6 support to the php mysql
connect api in the form of '[addr]:port' in addition to the previous
'host:port' syntax for ipv4 addresses.

Reviewed By: agallagher

Differential Revision: D1058111
2013-12-02 13:27:17 -08:00
Owen Yamauchi f18a8fac9f Add default arguments to some zip functions
This was causing a hilarious failure mode in debug builds where
unzipping this data would return the compressed data, because the flags
argument was 0x7a7a7a..., meaning the zip library thought the
FL_COMPRESSED flag (meaning return the compressed data) was set.

The problem was only showing up in interp mode, because I guess interp
mode passes arguments to native functions differently such that it was
picking up dead stack cells. Also, the test wasn't catching it because
both calls returned the same incorrect thing. I edited the test to be
more robust (and fix a variable-name type while I'm at it).

Reviewed By: ptarjan

Differential Revision: D1070357
2013-12-02 13:27:17 -08:00
Owen Yamauchi bf1c17d7e2 Fix type logic of VGetL (and VGetN while I'm at it)
VGetL has an effect on the local: it gets boxed. This was causing us
trouble in interp-everything mode when a local got boxed by being passed
by ref to a builtin and then consumed. (The builtin means the tracelet
won't be broken in between.) This was failing an ext_openssl test.

It hurts to be messing with this old code, especially since we've gotten
this far with this bug always present and it hasn't given us any
trouble. When can we kill it?

Reviewed By: @edwinsmith

Differential Revision: D1071404
2013-12-02 13:27:17 -08:00
mwilliams 4de7c49be1 Fix race in pmethodCacheMissPath
pmethodCacheMissPath smashes code under the write lease,
but there's nothing to prevent two threads going through it in
sequence - resulting in a double free of the pdata.

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

Reviewed By: @edwinsmith

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

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