632 Commits

Autor SHA1 Mensagem Data
ptarjan f951cb8d88 bump version to 2.3.2 2013-12-23 12:51:42 -08:00
Paul Tarjan 2a3225ecd0 fix DOCUMENT_ROOT for fastcgi
We shouldn't have spcialized code in here for fastcgi, and it didn't even work.

Reviewed By: @markw65

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

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

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

Closes #1334

Reviewed By: @JoelMarcey

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

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

Closes #1345

Reviewed By: @markw65

Differential Revision: D1098327

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

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

Reviewed By: @sgolemon

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

Closes #1359

Reviewed By: @alexmalyshev

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

Reviewed By: @bertmaher

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

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

Reviewed By: @jdelong

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

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

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

Reviewed By: @swtaarrs

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

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

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

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

Reviewed By: @dariorussi

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

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

Reviewed By: @edwinsmith

Differential Revision: D1078180
2013-12-12 15:10:56 -08:00
mwilliams b806c0345f optimize fast path to idx() (take 2)
This reverts commit 9ee6e1013b786b280090a052861e708e7c3fe4c0.

I was not having a good day. The crashes were caused by generating
the bytecode with one version of hhvm, and running it with another
(using HHVM_REPO_SCHEMA to shoot myself in the foot), while trying
to debug the asio issue.

Reviewed By: @dariorussi

Differential Revision: D1078072
2013-12-02 13:27:17 -08:00
mwilliams 36a8ca9f7d Revert "Turn off HHIRRefcountOpts by default"
This reverts commit f5f2fc6faa38098ce95dd509f3b33891ed7b4746.

My base rev was broken when I was testing this - there wasn't really
a problem with the RefcoutOpts.

Reviewed By: @edwinsmith

Differential Revision: D1078057
2013-12-02 13:27:17 -08:00
mwilliams c24b5b05d9 Fix crash in WaitHandle::join
It seems that continuations can complete during the "retry"
step, so we should check for that case.

Reviewed By: jan

Differential Revision: D1078010
2013-12-02 13:27:17 -08:00
Edwin Smith 147e1b43a0 Make VarNR become a KindOfStaticString
Reviewed By: mwilliams

Differential Revision: D1077814
2013-12-02 13:27:16 -08:00
mwilliams 783e2b3604 Turn off HHIRRefcountOpts by default
Getting a lot of crashes in production with it
turned on.

Reviewed By: @dariorussi

Differential Revision: D1077935
2013-12-02 13:27:16 -08:00
mwilliams 87d925f0e0 Revert "optimize fast path to idx()"
This reverts commit 7b38c2fbc414274cd22be32548b6cc86cc9d260a.

It crashes a lot in production.

Reviewed By: @dariorussi

Differential Revision: D1077893
2013-12-02 13:27:16 -08:00
mwilliams ca7ddfefe6 Fix memory leak in HPHP::Socket
Socket and SSLSocket are allocated via ::operator new,
so they need to take care of freeing their own memory when they
are swept.

This was showing up as a gradual leak if Socket's were held until
the end of the request.

Reviewed By: @andralex

Differential Revision: D1077472
2013-12-02 13:27:16 -08:00
Edwin Smith 14eb8f7152 Fix one bug, and some formatting, in new APC code
I noticed this while auditing uses of Variant(bool)

Reviewed By: mwilliams

Differential Revision: D1077812
2013-12-02 13:27:16 -08:00
aravind c3985e8354 Use fewer opcodes for Is* instructions
We are running out of opcode space (>256 opcodes).

Reviewed By: @edwinsmith

Differential Revision: D1075626
2013-12-02 13:27:16 -08:00
seanc f9e9b406c0 Add -Wno-deprecated-declarations
Summary: sbrk() has no equivalent how we use it and we use finite() for
parity with the reference implementation so these are not helpful
warnings.

Reviewed By: @sgolemon
2013-12-02 11:15:33 -08:00
Sara Golemon 7cc068e4c8 Don't rewrite license headers in submodules 2013-12-02 10:31:14 -08:00
Drew Paroski aae55a19c1 Update array_filter() to support collections
Updates array_filter() to support collections, and removes the old C++
implementation of array_filter() which is no longer used. This diff also
updates "foreach ($x as $k => $v)" for Set and FrozenSet so that the
current value is assigned into both $k and $v.

Reviewed By: @dariorussi

Differential Revision: D1071459
2013-12-02 10:31:14 -08:00
Julius Kopczewski f8f9284238 Finally statement support for HHVM.
Finally logic is handled by a new component: FinallyRouter.
The approach taken essentially constructs a simple finite
state automaton that decides which action to take next, once
the control reaches the end of a finally block. The
automaton uses an unnamed local variable "state". It also
uses an additional unnamed local to stash result between the
point of actually returning from a function and invoking
return. In order to minimize perf impact, two copies of
finally blocka are in fact emitted. The first copy ends with
a switch statement and is part of the automaton. The second
copy handles exceptional situations exclusively and ends
with Unwind. When multiple nested finallies exist, multiple
copies of a fault funclet corresponding to the inner finally
will be emitted in order to correctly handle chaining.
Exception chaining is handled using an extended set of
members in Fault (m_raiseLevel, m_raiseFrame,
m_raiseNesting). These values are used to decide whether two
exceptions stored on the top of the m_faults stack should be
chained already, or not yet. Additionally, changes have been
made to grammar files and AST in order to give the emitter
more information about the scope of goto labels. This is
used in order to handle goto from try finally block
correctly. No jumps into try finally are allowed, since
reference implementation (Zend) fatals in this case.

Reviewed By: @paroski

Differential Revision: D1058497
2013-12-02 10:31:14 -08:00
Kun Chen 7e6d9aefc3 ReflectionMethod supports getPrototype
ReflectionMethod will support method getPrototype().

**Please note I added an extra field "originalClass" to class ReflectionMethod because the exception message in ReflectionMethod::getPrototype() needs the original class name. (To be compatible with Zend)**

For example:

  class Base { public function test() {} }
  class Child extends Base {}
  $rf=ReflectionMethod('Child', 'test')

Then $rf->class will be "Base" while $rf->originalClass will be "Child".

The implementation for Func* is coming from https://github.com/php/php-src/blob/0d7a6388663b76ebed6585ac92dfca5ef65fa7af/ext/reflection/php_reflection.c (using Func->baseCls). The difference is that we need to deal with interfaces because Func->baseCls didn't consider interfaces.

For builtin classes, because MethodInfo* doesn't contain baseCls information, so we need to implement the logic from scratch.

Reviewed By: @ptarjan

Differential Revision: D1048239
2013-12-02 10:31:14 -08:00
Paul Tarjan f334742e1f actually fix DateTime on travis
sadpanda

https://travis-ci.org/facebook/hhvm/jobs/14586597

Reviewed By: @markw65

Differential Revision: D1076759
2013-12-02 10:31:14 -08:00
Edwin Smith 982408740a Add test case for unset-last-element followed by append
This demonstrates that the 'next-int-key' state of the array
is not modified by unset, even for the last element.
(php 5.3 and 5.5 do the same thing).

Reviewed By: @ptarjan

Differential Revision: D1074810
2013-12-02 10:31:13 -08:00
mwilliams e432eadd42 Fix invalid Func free
Generators that aren't closures still need to subtract
one pointer's worth from the Func* to get the address of the memory
to free.

Reviewed By: @jano

Differential Revision: D1075816
2013-12-02 10:31:13 -08:00
Dario Russi b110ec08fb Shortcircuit the check for an empty ini file and do nothing if empty
when ini file in runtime config is empty we want to do nothing. Literally nothing

Reviewed By: @markw65

Differential Revision: D1075478
2013-12-02 10:31:13 -08:00
Sean Cannella 88df7ab1a4 Merge pull request #1311 from demon/submodule-syntax
Suggest less typing for submodule setup
2013-12-02 10:16:44 -08:00
Sean Cannella ae16505782 Merge pull request #1304 from TsukasaUjiie/master
Fixed path to hhvm in doc makefile
2013-12-02 10:16:20 -08:00
Sean Cannella 4996c55227 Merge pull request #1310 from demon/libzip-ignore
Ignore libzip.dylib from being checked in
2013-12-02 08:12:31 -08:00
Drew Paroski 1a92fed987 Update README.md 2013-11-30 22:45:05 -08:00
Chad Horohoe 2084060478 Suggest less typing for submodule setup 2013-11-27 14:43:26 -08:00
Sara Golemon 44b47c4b43 Don't modify libmagic files 2013-11-26 21:14:20 -08:00
Drew Paroski 0304e80fb0 Update array_map() to support collections
Updates the C++ impl of array_map() to support collections, and updates
array_map.hhas to call the C++ impl when the second parameter is not an
array.

Reviewed By: @dariorussi

Differential Revision: D1071632
2013-11-26 21:14:20 -08:00
Edwin Smith efdfc6183b Fixed the JIT signature for c_StaticExceptionWaitHandle::CreateFromVM
Passing an ObjectData* as TV was working by accident, should be SSA.

Reviewed By: @markw65

Differential Revision: D1074657
2013-11-26 21:14:20 -08:00
Drew Paroski ffca8933eb Unbreak the debug build
Reviewed By: @elgenie

Differential Revision: D1075465
2013-11-26 21:14:19 -08:00
Drew Paroski 59ef8ddd15 Update call_user_func_array() to support collections
Updates call_user_func_array() to support collections for the second
parameter. Also update call_user_method_array(), hphp_create_object(),
hphp_invoke(), and hphp_invoke_method() to support collections.

In the course of implementing this, I fixed a bug with invokeFunc where it
would pass along the arg array to __call() and __callStatic() methods
without checking to make sure the arg array had integers keys 0 thru n-1.

Reviewed By: @dariorussi

Differential Revision: D1071732
2013-11-26 21:14:19 -08:00
Drew Paroski 7a0b149536 Support "C::{<expr>}()" style method calls
PHP 5.4 added support for "C::{<expr>}()" style method calls. This diff
updates HHVM to support them as well.

Closes #1292
https://github.com/facebook/hhvm/issues/1292

Reviewed By: @scannell

Differential Revision: D1071647
2013-11-26 21:14:19 -08:00
Eugene Letuchy f3d90340a4 reflection parity: default constructor with args is exception
conforms to the docs for http://www.php.net/manual/en/reflectionclass.newinstance.php
 as well as Zend

Reviewed By: @alexmalyshev

Differential Revision: D1070609
2013-11-26 21:14:18 -08:00
Joel Marcey 4cb5b74ff5 Refactor the script. Make finding and executing the framework tests better.
This is phase 1 (the biggest) of a refactoring of the test script. I have broken run.php into 3 areas of focus: the original run.php, the test finder, and other utils.

You can now run the script with the --byfile or --bysingletest option. The --byfile options lets you run the tests by test file name. This is faster. The --bysingletest options lets you run the tests by each single individual test of a framework. This is slower, but let's us support a good --filter option down the road.

Reviewed By: @ptarjan

Differential Revision: D1073658
2013-11-26 21:14:18 -08:00
Alan Frindell 5b856eecf8 wait for servers to finish on exit
The Server::stop() API claims to be asynchronous, but bad things happen if Server::stop() does not synchronously stop the VM as LibEventServer does.  Essentially the main thread can exit and leave the VM threads flapping in the breeze.  Call waitForEnd() on the servers before exiting.

Reviewed By: @markw65

Differential Revision: D1056280
2013-11-26 21:14:18 -08:00
Paul Tarjan b3f6b0cf5c don't require the timezone
travis might run on machines all over the world https://travis-ci.org/facebook/hhvm/jobs/14389509

Reviewed By: @JoelMarcey

Differential Revision: D1073832
2013-11-26 21:14:17 -08:00
Herman Venter afbde6181a Provide a way to serialize the compiler's AST in the form of a PHP Code Model.
The AST classes now have an additional visitor that can serialize the AST in the format expected by the unserialize function. The concrete classes to be produced by the unserialize function can be controlled by passing in a prefix argument to the visitor.

Facebook only:

Also added is an extension function fb_serialize_code_model_for(codeobject, prefix) that takes a string as its first argument, prefixes it with "<?php " and then parses it as if it were an eval string and then returns the serialized AST.

Reviewed By: @paroski

Differential Revision: D1027004
2013-11-26 21:14:17 -08:00
Jordan DeLong 9a48ffa372 Mark ZendObjectData as CPPClass, shrink the handle field
Workaround for #3235411.  These changes are needed so we
can shrink ObjectData without crashing entirely.

Reviewed By: @ptarjan

Differential Revision: D1072781
2013-11-26 21:14:17 -08:00
Paul Tarjan 6830d5dce8 update hash
they took my upstreams

Reviewed By: @JoelMarcey

Differential Revision: D1071534
2013-11-26 21:14:17 -08:00
Bert Maher 59b7c54be7 Improve bstrcaseeq
We can make bstrcaseeq a little bit faster by:
- Bailing out early if the pointers are equal
- Using an 8x unrolled case-sensitive comparison (with 8-byte
  compares) to speed the common case where the strings are the same
  including case
- Using the original version of bstrcaseeq to implement bstrcasestr,
  since there the common case is *not* equal strings.

Reviewed By: @jdelong

Differential Revision: D1069607
2013-11-26 21:14:16 -08:00
Dario Russi a9ed2b4abd optimize fast path to idx()
Inline call to idx against arrays with an int or string key into the caller

Reviewed By: @jdelong

Differential Revision: D1043782
2013-11-26 21:14:16 -08:00
Jan Oravec 69600b269e Move virtual barrier from WaitHandle to WaitableWaitHandle
Make WaitHandle, StaticResultWaitHandle and StaticExceptionWaitHandle
non-virtual. Move the virtual barrier to WaitableWaitHandle.

Reviewed By: @jdelong

Differential Revision: D1070819
2013-11-26 21:14:15 -08:00
Edwin Smith 91bc823b83 Use std::string instead of static StringData for array literals
It's a waste of memory to put the serialized array string in
the static string table, because we only need it when loading
or storing units in the HHBC repo.

Reviewed By: @jdelong

Differential Revision: D1070745
2013-11-26 21:14:15 -08:00
Edwin Smith 44c0c1acce Create NewStructArray opcode for array initialization
Many arrays are created with name/value pair syntax, with all
static string names and no repeat keys; aka "struct-like".  This
diff adds a new opcode to support that pattern.

Reviewed By: @jdelong

Differential Revision: D947681
2013-11-26 21:14:15 -08:00
Jan Oravec 5685a2bfdd Native VM support for wrapping exceptions into StaticExceptionWaitHandle
Replace StaticExceptionWaitHandle::create() extension call with AsyncWrapException opcode.

Reviewed By: @jdelong

Differential Revision: D1045649
2013-11-26 21:14:14 -08:00
Jan Oravec 81ee37e99b Native VM support for wrapping results into StaticResultWaitHandle
Do not use emit StaticResultWaitHandle::create() extension call for
every return from eagerly executed async function. Instead, use
AsyncWrapResult opcode that takes care of wrapping the result into
StaticResultWaitHandle object and returning it to the caller.

Reviewed By: @jdelong

Differential Revision: D1045994
2013-11-26 21:14:14 -08:00
Joel Marcey 7e9bceb27f Fix preg_replace /e functionality for $this style calls
preg_replace /e was failing for $this->foo() style replacements. We were returning $this is null. That was wrong.

Reviewed By: @ptarjan

Differential Revision: D1069658
2013-11-26 21:14:14 -08:00
bsimmers 7b40ccec1e Add ahot and aprof sizes to check-health admin command
Facebook: I also cleaned up and compacted the formatting in a couple scripts.

Reviewed By: @jdelong

Differential Revision: D1070834
2013-11-26 21:14:13 -08:00
Paul Tarjan 6039d0fbef make isInstantiable right
@dariorussi brought this up on the other ctor diff. I think it is a big enough change to do on its own.

Reviewed By: @dariorussi

Differential Revision: D1070445
2013-11-26 21:14:13 -08:00
Paul Tarjan 8fd0510528 fix seialization of protected members when there is a __sleep
I don't know why all this code is copy-pasted, but they forgot a case.

Reviewed By: @alexmalyshev

Differential Revision: D1070176
2013-11-26 21:14:13 -08:00
Eugene Letuchy 94dbd3e5bd jit: make obj-to-bool collection conversion check cheaper
@paroski made the change that moved the size of
 collections to a fixed offset, but didn't go further to actually take
 advantage of that with an assembly version of ##isCollection()##.

Reviewed By: @oyamauchi

Differential Revision: D1067752
2013-11-26 21:14:12 -08:00
Jan Oravec 5cd4f28120 Combine CreateAsync + getWaitHandle() into AsyncESuspend
CreateAsync opcode creates a Continuation object that is wrapped into
AsyncFunctionWaitHandle object by ->getWaitHandle() call. Let's merge
these operations into AsyncESuspend that produces
AsyncFunctionWaitHandle and kill Awaitable/getWaitHandle() API from
Continuations.

AsyncFunctionWaitHandle internally still uses Continuations.

Partially based on Mirek Klimos's summer internship work.

Reviewed By: @jdelong

Differential Revision: D1069759
2013-11-26 21:14:12 -08:00
Jan Oravec 0fbd048228 Remove m_origFunc from c_Continuation
m_origFunc is used only to obtain a name of the enclosing function and a
number of original arguments to locate Closure object (which stores
static locals).

If a Func is a generator, allocate extra pointer size to store a pointer
to the original function. Populate this pointer from getGeneratorFunc()
(i.e. when Create{Async,Cont} is interpreted or compiled).

Reviewed By: @jdelong

Differential Revision: D1067622
2013-11-26 21:14:12 -08:00
Sean Cannella 2b7d62d917 Fix ini parsing leak
Right now we don't clean up the YY_BUFFER_STATE created by the Bison parser after we scan a string -- we simply ignore the return of yy_scan_string and it never gets cleaned up (since yy_switch_buffer on a subsequent call won't delete anything.) Fix that.

Closes #733

Reviewed By: @elgenie

Differential Revision: D1069986
2013-11-26 21:14:11 -08:00
Joel Marcey 22722e81ed Don't commit the md5 file to git
Just keep the md5 file local to your machine. No need to gitify it.

Reviewed By: @alexmalyshev

Differential Revision: D1070836
2013-11-26 21:14:11 -08:00
Joel Marcey e23c9609d6 Came to my senses and fixed the composer.json clowntown check
@elgenie made me come to my senses. New check for composer.json changes.

Reviewed By: @alexmalyshev

Differential Revision: D1070788
2013-11-26 21:14:11 -08:00
Jordan DeLong 0cdfbbd340 Flatten APCObject
Put the property vector immediate following APCObject in
memory.

Reviewed By: @edwinsmith

Differential Revision: D1070249
2013-11-26 21:14:10 -08:00
Jordan DeLong 2cd9ea58b5 Reduce string hashes and class lookups in APCObject::getObject
A good chunk of the calls to hash_string_i in production are
coming from looking up classes while converting APCObjects into
ObjectData.  If the Classes are persistent, we can have them already
looked up.  We can also avoid creating an array just to call
o_setArray.

Reviewed By: @dariorussi

Differential Revision: D1067486
2013-11-26 21:14:10 -08:00
Jordan DeLong 9599b72663 Some improvements to the iter_next "cold" path
Most of the time when we go to the cold path, it's because
we're iterating an APCLocalArray.  Add a specialized version for that.
We were also always going to cold by first going to a function that
checked for various collection types (with very big code)---change
this to a quick check at the front of iter_next_cold that then tail
calls to a function that code collection dispatch on the already
loaded type (compiles as a jump table).  We also bailed for releasing
the array which is easy enough to handle.

Reviewed By: @bertmaher

Differential Revision: D1067317
2013-11-26 21:14:10 -08:00
Joel Marcey 6607d6dca4 Make sure our phpunit binary is the one with our hhvm fix + upstream changes to frameworks
Our vendor/bin/phpunit did not contain our PHP_BINARY fix. So I updated composer to get that version, with a hack to make sure that your runs actually get the latest too. I will remove that Hack later and come up with a better way.

Plus I fixed Symfony to support HHVM (PHP_BINARY) too: https://github.com/JoelMarcey/symfony/commit/eba220f998ed994900e0324d1a8dd54b9656ae37

Symfony is above 97% now.

I will upstream that.

The nothing to do errors are gone from yii now, but didn't help the percentage that much. I updated to their latest master hash anyway.

Reviewed By: @alexmalyshev

Differential Revision: D1070555
2013-11-26 21:14:09 -08:00
Jan Oravec ccd469ca37 Move closure check from run time to compile time
When async functions and continuations are used with closures inside
methods, their generator body needs to be cloned into the enclosing
class. This is currently done in run time, but there is nothing
preventing us to do it in compile time, so let's do it.

Reviewed By: @jdelong

Differential Revision: D1067501
2013-11-26 21:14:09 -08:00
Jan Oravec 66b98ad061 Store name of generator body function in the outer Func
Bind inner and outer generator functions, do not pass the name of inner
function thru CreateCont/CreateAsync immediates.

Reviewed By: @jdelong

Differential Revision: D1067483
2013-11-26 21:14:09 -08:00
Julius Kopczewski 96959f0e28 Closing connection on invalid record in FastCGI.
Changed FastCGI behaviour to close the connection when an
invalid record has been received instead of aborting.

Reviewed By: @ptarjan

Differential Revision: D1061545
2013-11-26 21:14:08 -08:00
Paul Tarjan fa4d66125f ReflectionClass->newInstance() should respect privacy
Reviewed By: @alexmalyshev

Differential Revision: D1069688
2013-11-26 21:14:08 -08:00
Paul Tarjan 9181f5fc6a move MW hash back
the newer version is broken somehow and I don't have time to figure out why

Reviewed By: @JoelMarcey

Differential Revision: D1070426
2013-11-26 21:14:08 -08:00
mwilliams 01ff4de5d0 Fix async functions with statics
We were double adding the statics, which resulted in
an assert in dbg builds, and random crashes in release.

Reviewed By: @jdelong

Differential Revision: D1070112
2013-11-26 21:14:07 -08:00
bsimmers c7f62b6076 Add type prediction bytecodes
This diff adds PredictTL and PredictTStk, which are similar to
AssertTL and AssertTStk but for predictions instead of known types. They're
mostly intended for debugging right now, to help reproduce issues that depend
on certain type predictions being present. In the future we could start
emitting them instead of metadata entries.

Reviewed By: @jdelong

Differential Revision: D1069999
2013-11-26 21:14:07 -08:00
Alex Malyshev c9073fd81f Have hphp_get_method_info check superinterfaces of interfaces
If a method doesn't exist in an interface, then we need to check
all interfaces that it inherits from as well.

Reviewed By: @JoelMarcey

Differential Revision: D1068583
2013-11-26 21:14:06 -08:00
Alex Malyshev 7ceb298849 Enable the bzip2 extension
We already had it implemented, but extension_loaded('bz2') would return
false.

Reviewed By: @ptarjan

Differential Revision: D1069567
2013-11-26 21:14:06 -08:00
Sean Cannella 9a9b42e361 Use CPU time instead of wall time for time limit
Zend PHP does not count in sleeping time into scripts time
limit, HHVM does. Change that for parity reasons.

Closes #1279
Closes #1287

Reviewed By: @markw65

Differential Revision: D1066797
2013-11-26 21:14:06 -08:00
Dario Russi 0b04c8ff0f Introducing APCHandle as a replacement of APCVariant (aka SharedVariant)
Every APC object (aka shared object) now has an APCHandle field used by the concurrent storage. No indirection any longer from APCVariant to the object data (string, object, array)

Reviewed By: @jdelong

Differential Revision: D1023419
2013-11-26 21:13:40 -08:00
Paul Tarjan c6d99f1e8e re-use c_DOMNode for xmlNodePtr
This is how zend does it. They shove the container object into the _private part of the dom node and then re-use it. A test in drupal depends on this and it seems correct for the elements to `===` the same if they really have the same underlying node.

Does this introduce a memory leak? I'm not increffing anything so I think the smart pointer wrapping the `ObjectData*` is keeping the `ObjectData*` alive at all times already, this is just a cache of the pointer.

Reviewed By: @markw65

Differential Revision: D1065371

Revert "re-use c_DOMNode for xmlNodePtr"

This reverts the important part of commit 7f8617bd2895e9a802f0efd219390e9b40a8b41d.

I originally thought that the use of `_private` was a problem so I tried using a thread-local map but that didn't do anything.

While I figure out how to do this properly, just revert so our graphs aren't 22%.

Reviewed By: @JoelMarcey

Differential Revision: D1073217
2013-11-26 21:13:27 -08:00
bsimmers 280f307d34 Properly support $this pointers in refcounting opts
The refcounting optimization now understands the flow of values throw
SpillFrames while inlining. This diff is aimed at fixing correctness issues;
there may be more opportunities for optimization we're missing around inlined
calls.

Reviewed By: @ottoni

Differential Revision: D1063557
Differential Revision: D1075908
2013-11-26 21:13:12 -08:00
bsimmers 255b8b4ed6 Clean up inlining frame elision
The code to eliminate unused inline frames was broken for a few
superficial reasons. Once I fixed those, I found and fixed a few larger issues,
mostly having to do with stack offsets for ReDefSP and DecRef (see the code for
details in comments). Unfortunately I'm going to have to check this in disabled
for now since there's at least one crash remaining and I need to move onto
other things for the moment.

check.cpp now enforces that any instruction that can throw must have a catch
block attached, since a number of optimizations rely on that for
correctness. This exposed a number of old issues, the biggest of which was that
LdClsMethodCache and LdClsMethodFCache had a taken label for a slow exit and
can also throw. Since they need a catch trace to be able to throw correctly, I
split them up into smaller instructions to expose more of the control flow at
the IR level.

Reviewed By: @jdelong

Differential Revision: D1060374
2013-11-26 18:33:26 -08:00
Paul Tarjan 947e16cfbb use my MW upstream
They will pull it, just they are slow.

Reviewed By: @JoelMarcey

Differential Revision: D1070132
2013-11-26 18:23:57 -08:00
Eugene Letuchy a759101869 frameworks runner: support notices
... I'd argue that this should be the default
 and tests that depend on not having notices should not work

Reviewed By: @ptarjan

Differential Revision: D1069033
2013-11-26 18:23:52 -08:00
Joel Pobar c57a6a2828 DatePeriod support
Adds most of DatePeriod support for CodeIgniter unit test

Reviewed By: @JoelMarcey

Differential Revision: D1069304
2013-11-26 18:23:47 -08:00
Joel Marcey 01d5384547 Add some includes upstream to phpbb3
Some tests need some additional includes in order to be run as a single test file. Added them. https://github.com/phpbb/phpbb/pull/1888

Reviewed By: @ptarjan

Differential Revision: D1069949
2013-11-26 18:23:42 -08:00
Owen Yamauchi c7d175ec1d Fix ARM exception crash, add --arm option to test/run
The fakeAR thing isn't necessary now that we have a special fixup
implementation for simulator mode. Combined with @markw65' changes to
functionEnterHelper etc., everything's pretty clean, and function
interception works properly (it didn't before lockdown).

Reviewed By: @edwinsmith

Differential Revision: D1069589
2013-11-26 18:23:36 -08:00
Chad Horohoe 965a70f8dd Ignore libzip.dylib from being checked in 2013-11-26 16:17:41 -08:00
Benjamin Roberts 0cf0624bcf Fixed path to hhvm in doc makefile 2013-11-26 16:01:08 +11:00
Joel Marcey 4ef45eb36d Go to the latest github hash for phpbb3 and get the tests to behave
We were failing many tests in phpbb3 because there was globals clowniness when trying to run their tests with filenames. I sent a pull request up to fix that. In the meantime, use my fork.

Reviewed By: @elgenie

Differential Revision: D1069881
2013-11-22 09:49:17 -08:00
Eugene Letuchy b53c43ec9f frameworks: use branch with joomla sort order
... also rerecorded the .expect

Reviewed By: @JoelMarcey

Differential Revision: D1069868
2013-11-22 09:49:13 -08:00
mwilliams bba9d63c4c Don't pass the wrong type to dom error handlers
The error handler takes an arbitrary "context" pointer.
In our handler, if the pointer is not null, we assume its an
xmlParserCtxtPtr, but there were a few places where we passed
in a different type.

Just pass in nullptr instead.

Reviewed By: @edwinsmith

Differential Revision: D1069579
2013-11-22 09:49:09 -08:00
Paul Tarjan 0c165f824d random test runner fixes
stuff i needed while debugging doctrine

Reviewed By: @JoelMarcey

Differential Revision: D1069627
2013-11-22 09:49:05 -08:00
Joel Marcey 536036ee32 Make Zf2 use the latest dev of PHPUnit with our PHP_BINARY fix
To avoid the dreaded "Nothing to do" error, we need PHPUnit to check for our PHP_BINARY env variable. We had that pull requested accepted by PHPUnit. Now the framework vendor dirs need that version. Start with zf2.

Reviewed By: @ptarjan

Differential Revision: D1069559
2013-11-22 09:49:01 -08:00
Owen Yamauchi e4d019d6c4 Fix ARM mode bustage that occurred during lockdown
- At some point, the order of arguments to InterpOne got switched
  around for no apparent reason in the refcount optimization diff.

- My fix to poly-torture.php got accidentally pseudo-reverted, also in
  the refcount optimization diff.

- The type effects of an interped PushL wasn't accounted for properly.

There are still a few more quick tests that crash. Based on their file
names, I think it's all a single root cause. I'll look at those next.

Reviewed By: @jdelong

Differential Revision: D1068766
2013-11-22 09:48:57 -08:00
Paul Tarjan 8d601df707 assetic is being difficult
Something needs to be done but while we bicker just use this

Reviewed By: @JoelMarcey

Differential Revision: D1069051
2013-11-22 09:48:53 -08:00
Paul Tarjan 926f16e6e4 remove 'now' case from test/slow/datetime/compare.php
This is a bit flakey since the 1 second boundary can tick inbetween the `null` and `"now"` case. That isn't even the main point of this test.

Reviewed By: @markw65

Differential Revision: D1069019
2013-11-22 09:48:49 -08:00
mwilliams 236d270b52 Don't let debug_backtrace read a freed ExtraArgs during unwinding
thats it

Reviewed By: @jdelong

Differential Revision: D1068339
2013-11-22 09:48:41 -08:00
Joel Marcey 8505e3f06e stream_resolve_include_path needs to return false on failure, not null
stream_resolve_include_path() was returning null for invalidity instead of false. Make it so.

Reviewed By: @ptarjan

Differential Revision: D1068148
2013-11-22 09:48:37 -08:00
Paul Tarjan 540e98f962 add pull request
Slim isn't being responsive

Reviewed By: @JoelMarcey

Differential Revision: D1068996
2013-11-22 09:48:29 -08:00
Joel Marcey 270761effb Add phpunit config file support to script test command
Add -c support to the test command for running phpunit from our script.

Reviewed By: @ptarjan

Differential Revision: D1068614
2013-11-22 09:48:17 -08:00
Sean Cannella dfab83ed50 Split HHProf into compile plus runtime options
This splits HHProf (heap profiling) into two different knobs --
one is compile time, because of the overhead in the memory-manager smart
malloc functions, and the other is a runtime option that controls actual
tracking of data. This gets us the ability to have no impact when
compiling without the flag and minimal impact (within 1%) of impact when
compiling with the flag but with the runtime option turned off.

Reviewed By: @mikemag

Differential Revision: D1068213
2013-11-22 09:47:49 -08:00
Paul Tarjan 883456c911 warn on null file to fopen
Without this we hapilly put the `cwd` infront and open a directory. mediawiki has a test failing because of it. This felt like the best place to put it.

Reviewed By: @alexmalyshev

Differential Revision: D1067777
2013-11-22 09:47:45 -08:00
Yermo 8763eed645 Allow rewrite rules to apply to files that exist
Adds a CheckExistenceBeforeRewrite option to allow rewrite rules to take effect even on files that exist on the default path. This option is off by default.

Closes #1283
Closes #1286

Reviewed By: @ptarjan

Differential Revision: D1065548

Pulled By: @scannell
2013-11-22 09:47:40 -08:00
bsimmers 7f74da5701 Disable flaky test/zend/good/ext/standard/tests/file/copy_variation16.php
Reviewed By: @jdelong

Differential Revision: D1068500
2013-11-22 09:47:35 -08:00
Joel Marcey b6a51da104 Fix Reflection to support ordering properties like Zend
Zend orders their properties with child first then parent. We were doing the opposite. Fix that by rearranging the array in php land in reflection.php

Reviewed By: @ptarjan

Differential Revision: D1064961
2013-11-22 09:47:31 -08:00
Owen Yamauchi 4934efdba6 String::String(char) = delete; fix exposed lolbugs
While working on something else, I got bitten by this: if you construct
a String from a char, the char gets promoted to int and that constructor
won't do what you want (it stringifies the int).

To my great joy, this exposed some actual latent bugs, so I fixed them.
E.g. the things that thought they were appending a slash were actually
appending the string "47".

Reviewed By: @swtaarrs

Differential Revision: D1067258
2013-11-22 09:47:13 -08:00
Abel Nieto cde444e097 Add magic methods to the collections IDL.
The magic methods for Pair were missing from the IDL, and so were
not visible from PHP-land.

Add them to the IDL.

Reviewed By: @elgenie

Differential Revision: D1066776
2013-11-22 09:47:08 -08:00
Sara Golemon 26476669f5 Ignore test litter 2013-11-22 09:47:00 -08:00
Paul Tarjan 49be3b1277 clownlist some joomla tests
zend won't pass these without some more setup which I can't figure out how to do

Reviewed By: @JoelMarcey

Differential Revision: D1067754
2013-11-21 14:03:00 -08:00
Paul Tarjan a0e0c8e5a5 exclude 'Broken' group for MW
aparantly instead of disabling them they put them in a Broken group
clowntown

Reviewed By: @alexmalyshev

Differential Revision: D1067762
2013-11-21 14:03:00 -08:00
Paul Tarjan e474dd092d clownlist a yii test
this one needs memcache

Reviewed By: @JoelMarcey

Differential Revision: D1067702
2013-11-21 14:03:00 -08:00
Paul Tarjan 08ac3def46 make the test runner print more
this was useful while debugging the compser thing

Reviewed By: @JoelMarcey

Differential Revision: D1067489
2013-11-21 14:03:00 -08:00
Paul Tarjan a481fc7cb6 add zlib_encode and zlib_decode
Composer needs these functions all of a sudden. I couldn't figure out what they should do from the docs, and looking at the code they look to be identical to the gz versions except they don't force Gzip. Our versions of the gz fucntions don't force GZ anyways so I'll just proxy.

Reviewed By: @alexmalyshev

Differential Revision: D1067316
2013-11-21 14:02:59 -08:00
Sara Golemon 7e6176d120 Add ICU NumberFormatter class (and functions)
Implement to match Zend

Reviewed By: @ptarjan

Differential Revision: D1065096
2013-11-21 14:02:59 -08:00
Sean Cannella f93874910f Merge pull request #1288 from bzikarsky/master
Updated configure_ubuntu_12.04.sh to work on a "clean" ubuntu installation
2013-11-21 11:24:07 -08:00
Benjamin Zikarsky a793e9ae7e Update configure_ubuntu_12.04.sh
- `python-software-properties` must be installed before we try to add the `apt-fast` PPA
- Add automatic initialization of git submodules
2013-11-21 20:06:10 +01:00
Sean Cannella 0c4b037096 Fix OS X compilation
Fix compilaton on OS X due to undefined symbols

Reviewed By: @markw65

Differential Revision: D1067049
2013-11-21 10:38:03 -08:00
Paul Tarjan 12390ea61f update yii hash
they took my upstream fix

Reviewed By: @JoelMarcey

Differential Revision: D1067226
2013-11-20 22:07:57 -08:00
Jan Oravec 6a637a7c7a Fix assert in BlockableWaitHandle::blockOn()
A Gen{Array,Map,Vector}WaitHandle from an outer context may be woken up
and may establish a dependency on a WaitableWaitHandle from an inner
context. Fix the assert.

Reviewed By: @swtaarrs

Differential Revision: D1067182
2013-11-20 22:07:56 -08:00
Paul Tarjan 840da6e18f include upstreamed fix to phpmyadmin
3 more %

Reviewed By: @JoelMarcey

Differential Revision: D1066900
2013-11-20 22:07:56 -08:00
Paul Tarjan d05f4f766a remove the __construct from PDOStatement
@alexmalyshev needs this to fix PDOStatement subclassing

Reviewed By: @alexmalyshev

Differential Revision: D1066791
2013-11-20 22:07:56 -08:00
Alex Malyshev 33787f302a Update laravel hash after upstream fix
Another fix for reusing closures got upstreamed.

Reviewed By: @JoelMarcey

Differential Revision: D1065942
2013-11-20 22:07:55 -08:00
Paul Tarjan c23f2197e6 put m_cls on UserFSNode
I collided with @edwinsmith's removal of m_cls. This is better anyways.

Reviewed By: @alexmalyshev

Differential Revision: D1066263
2013-11-20 22:07:55 -08:00
Jan Oravec ffbd125dc3 Move responsibility for context entering to blockOn callers
BlockableWaitHandle::blockOn() may throw when cross-context cycle is
detected while wait handle enters context. Move this responsibility to
the caller:

- AsyncFunctionWaitHandle and SetResultToRefWaitHandle now perform the check before construction
- the cross-context cycle exception is now catchable from async functions

Related cleanups:

- blockOn & co. are now inlined
- enterContext's likely case is now inlined

Future work:

- maintain parent_context_idx <= child_context_idx invariant for all
  children of Gen{Array,Vector,Map}WaitHandles, so that enterContext()
  is not needed when collection wait handles are unblocked; once done,
  enterContext() calls will occur only on user action (construction of
  WaitHandle and await) and the logic could be simplified

Reviewed By: @jdelong

Differential Revision: D1064798
2013-11-20 22:07:55 -08:00
Paul Tarjan bc3a8b55cd add directory support for userland filesystems
Filling out our userland stream wrapper

Reviewed By: @sgolemon

Differential Revision: D1062493
2013-11-20 22:07:54 -08:00
Jordan DeLong 0d3991962e Treadmill the MethodCachePrimeData after its used
Clean up after ourselves.

Reviewed By: @markw65

Differential Revision: D1060870
2013-11-20 22:07:54 -08:00
Jordan DeLong 88af886439 Combine smart_malloc with the 'size-untracked' freelists
I kept these separate when strings were first moved from the
old SmartAllocatorImpl stuff into here because combining them
increased stores too much.  Now that almost all of the heap is going
through the smartMallocSize api, it seems ok to combine them.  Perflab
showed stores very slightly up (red only on a few endpoints), d-TLB
misses possibly slightly down, d-cache misses down, cpu time in the
noise.

Reviewed By: @edwinsmith

Differential Revision: D1062598
2013-11-20 22:07:54 -08:00
Paul Tarjan 2373167ba9 Treat incomplete like skipped
According to http://phpunit.de/manual/3.7/en/incomplete-and-skipped-tests.html incomplete shouldn't be counted as either a pass nor a fail.

Reviewed By: @JoelMarcey

Differential Revision: D1065446
2013-11-20 22:07:54 -08:00
Joel Marcey 9618294f10 Make some Mediawiki tests clowny
Some of the data sets for these tests fail in Zend as well.

We are getting rid of them all since we clown by file, but in this case that is ok, I think.

We move to 99.88%

Reviewed By: @ptarjan

Differential Revision: D1065351
2013-11-20 22:07:53 -08:00
Jordan DeLong 1203a56f1c Fix instanceDtors for ZendObjectData types
Reviewed By: @ptarjan

Differential Revision: D1065079
2013-11-20 22:07:53 -08:00
Edwin Smith e57aaca9d2 Remove dead m_cls field from ResourceData
it's dead

Reviewed By: @jdelong

Differential Revision: D1065596
2013-11-20 22:07:53 -08:00
Paul Tarjan 5e33aff80f add ViewsDataHelperTest.php to clownylist
This fails in zend

Reviewed By: @alexmalyshev

Differential Revision: D1065420
2013-11-20 22:07:52 -08:00
Paul Tarjan 0bbac0b3e7 clownify validate_range_test.php
These tests all fail in zend with the same error `Creating default object from empty value`.

Reviewed By: @alexmalyshev

Differential Revision: D1065442
2013-11-20 22:07:52 -08:00
Abel Nieto 57e1da0952 Add a FrozenSet extension class (but don't make it a collection, yet)
Add a c_FrozenSet class that inherits from BaseSet and exposes an immutable
interface to PHP-land (it implements ConstSet).

We can foreach over it, but literal syntax doesn't work yet, since it's
not a collection (will make it so in another diff).

Reviewed By: @paroski

Differential Revision: D1051520
2013-11-20 22:07:52 -08:00
Paul Tarjan 1c2d9746d7 Make DateTime serializable
In zend `DateTime` can be serialized. I could try to match their format but as long as we are consistent with ourselves I think this is ok.

Putting that attribute check seems pretty hacky but I couldn't think of a better way.

Reviewed By: @mikemag

Differential Revision: D1063231
2013-11-20 22:07:51 -08:00
Joel Marcey 17ef29c212 Clowntown - The script wasn't counting fatals in stats
Sigh. The script was not printing fatals to the stats file and thus they were not being counted in the percentage.

Reviewed By: @ptarjan

Differential Revision: D1065312
2013-11-20 22:07:51 -08:00
Guilherme Ottoni b6db443d73 Profile to detect hot functions
Use the initial profiling, interpreted requests to detect hot
functions.  Marking them as hot hints the JIT to put them in the ahot
TC area.

Reviewed By: @edwinsmith

Differential Revision: D1063581
2013-11-20 22:07:51 -08:00
Paul Tarjan bbe0eb639f set error_reporting to the php-default for framework tests
and while I'm in there actually make the setting work ;)

Reviewed By: @alexmalyshev

Differential Revision: D1064978
2013-11-20 22:07:50 -08:00
Paul Tarjan 0bc8d16905 add back test/slow/config.hdf
My desire to print more warnings was killing our test coverage for some options.

Reviewed By: @markw65

Differential Revision: D1064717
2013-11-20 22:07:50 -08:00
Paul Tarjan 6dfb28d7b4 make DateTime remember the timezone from the constructor
Reviewed By: @alexmalyshev

Differential Revision: D1065084
2013-11-20 22:07:50 -08:00
Jan Oravec 0b0c3b95a4 Move wait handle declarations to individual header files
Split ext_asio.h into multiple header files, one per each WaitHandle
subclass.

Reviewed By: @jdelong

Differential Revision: D1064750
2013-11-20 22:07:50 -08:00
Paul Tarjan 6f87770554 strip user:pass from url before going to curl
It looks like curl is unhappy when passed a user:pass to `curl_setopt(CURL_URL)`. Lets remove it before we get there.

I could have used `parse_url` and then put it back together, but the regex seemed simple enough... (famous last words)...

Reviewed By: @sgolemon

Differential Revision: D1064319
2013-11-20 22:07:49 -08:00
Paul Tarjan 741ad4cd4d Allow stream_context_create to take an array of headers
Reviewed By: @sgolemon

Differential Revision: D1064310
2013-11-20 22:07:49 -08:00
Paul Tarjan 2e83e734e9 set JitEnableRenameFunction for AuthGuardTest.php
This test uses `debug_backtrace()[0]['args']` to get the args, so we need to keep them around. If we set this always it is a 5% perf regression so only doing it specifically for this test.

Reviewed By: @JoelMarcey

Differential Revision: D1064678
2013-11-20 22:07:49 -08:00
Bert Maher f359d60449 Use store immediate for writing Func* to ActRec in SpillFrame
We were moving the immediate to a register and then to
memory; we can save an instruction by storing directly to memory.

Reviewed By: @jdelong

Differential Revision: D1064108
2013-11-20 22:07:48 -08:00
Jordan DeLong 3c777c570c Specialize array iteration in GenArrayWaitHandle::create
Also, only do one pass over the array, instead of two.

Perflab things it cuts on instructions a very tiny bit, and cuts
branch misses (less than a percent.)  This is adding a place that
assumes packed and mixed arrays have the same value layout---do we
think it's worth that?  (We can always rip it out later, and maybe
GenArrayWaitHandle will become less important if people soon use
Map/Vector WaitHandle instead?)

Reviewed By: @jano

Differential Revision: D1061039
2013-11-20 22:07:48 -08:00
Sara Golemon f1e7c82463 Limit mini-systemlib names to 16 characters
Some platforms (MacOS) don't allow section names
longer than 16 characters.  Use "ext." plus the first
twelve hexits of md5($extname) instead.

This diff also adds an objdump wrapper for checking for
and dumping the contents of mini-systemlib sections.

Reviewed By: @scannell

Differential Revision: D1061643
2013-11-20 22:07:48 -08:00
aravind 20c679133f Support pcre-8.32's JIT
8.32 has a JIT for regular expressions.

Reviewed By: @ottoni

Differential Revision: D1052476
Differential Revision: D1067435
2013-11-20 22:07:34 -08:00
Sara Golemon ec1d6c6b26 Make sqlite3 testless flakey
Destructor timing makes this test just everso-slighty
nondeterministic.  (I occaisionally see it kick in between the
last two tests rather than before them).

Move the close to the end and it'll always happen in the right order.

Also change expectf "finalised" to "finali%ced" to
account for libsqlit3's switch from Brittish English to American English.
Or maybe it was the other way around. Either way... Ugh.

Reviewed By: @ptarjan

Differential Revision: D1065633
2013-11-20 14:38:47 -08:00
Jordan DeLong 86224fbae8 Fix a bug in func prologue guards---it used cmpl instead of cmpq
Unlikely case: if we called the wrong Func, the target Func
was in low memory but the actual Func wasn't, and the guard and
actually-called Func have the same low 32-bits, it would pass the
guard.  While here, also change a few assembler calls to use the new
api.

Reviewed By: @edwinsmith

Differential Revision: D1060995
2013-11-20 14:38:47 -08:00
Alex Malyshev 6c1fb74fe8 Implement ReflectionFunctionAbstract::getClosureScopeClass()
Needed for laravel

Reviewed By: @ptarjan

Differential Revision: D1062117
2013-11-20 14:38:46 -08:00
Joel Marcey 8d92efa6a9 Fix Mediawiki Install
Need to call parent::install() first before creating LocalSettings.php

Reviewed By: @alexmalyshev

Differential Revision: D1063867
2013-11-20 14:38:46 -08:00
Jordan DeLong 95975ac58b Remove CSE flag from several Array-related opcodes
We have to know nothing mutated the array on the other side
of the SSATmp representing the array.

Reviewed By: @markw65

Differential Revision: D1060861
2013-11-20 14:38:46 -08:00
Jordan DeLong 55d6180140 Remove CSE flag from LdFuncCachedSafe, and a few others
For LdFuncCachedSafe, if it returns null, we can't cache it
without knowing if something inbetween defined the func.  The other
ones might work but are too dubious for now.

Reviewed By: @edwinsmith

Differential Revision: D1060858
2013-11-20 14:38:46 -08:00
Jordan DeLong 3062a5c1f1 Remove CSE flag on LdClsMethod{F,}Cache
These are essential and need to mutate an actrec.  I'm not
sure why they have CSE.

Reviewed By: @ottoni

Differential Revision: D1060857
2013-11-20 14:38:46 -08:00
aravind ded1d9a1a5 Continuation object changes
1. Restructure c_Continuation to put the Continuation object
after the ActRec.
2. Cache the entry TCA for the continuation function in the
Continuation object.

Reviewed By: @jdelong

Differential Revision: D1055946
2013-11-20 14:38:46 -08:00
Jan Oravec e058bde149 Detect cycles only when necessary
Move the responsibility for cycle detection from blockOn() to its
caller. Do not detect cycles when the parent wait handle is being
creates, as it's impossible for new cycle to be introduced that way.

Also, it was previously not possible to catch a cycle exception by
adding try/catch around the await. Fix it.

Reviewed By: @jdelong

Differential Revision: D1062770
2013-11-20 14:38:46 -08:00
Jan Oravec 0bbdc8af8f Simplify AsyncFunctionWaitHandle, take advantage of eager execution
Eager execution semantics guarantees that "await" can reenter ext_asio
only with blocked WaitableWaitHandle. Also, an AsyncFunctionWaitHandle
is constructed only when blocked WaitableWaitHandle is encountered.

Take advantage of that, kill all dead code and simplify the rest.

Reviewed By: @jdelong

Differential Revision: D1062521
2013-11-20 14:38:46 -08:00
Alex Malyshev 53172b6bc4 Sync VM regs before executing SQL queries
The SQL queries can have UDFs in them, which causes havoc with the JIT
if we haven't sync'd our registers beforehand.

Reviewed By: @jdelong

Differential Revision: D1060223
2013-11-20 14:38:45 -08:00
Alok Menghrajani ed50758e0f Revert "Switch nullable type failures to recoverable_error"
This reverts commit 83c970e1d8c01fd6e20c2cdb32d6a047c79edc4d.

Reverting this will allow us to run old revisions of www in perflab. I can
bring this diff back in a few weeks.

Reviewed By: @jdelong

Differential Revision: D1062203
2013-11-20 14:38:45 -08:00
Sean Cannella 44c3020a7c Replace slice_array(func_get_args, C)) with hphp_func_slice_args(C)
array_slice(func_get_args(), N) ends up making array copies that are unnecessary. Provide a new library function to deal with this pattern.

Reviewed By: @markw65

Differential Revision: D1057678
2013-11-20 14:38:45 -08:00
Fred Emmott 47384d7426 Add support for /etc/hhvm/config.hdf fallback
Add support for reading /etc/hhvm/config.hdf as a fallback if no configuration file is specified on the commandline.

Closes #1251
Closes #1275

Reviewed By: @edwinsmith

Differential Revision: D1061239

Pulled By: @scannell
2013-11-20 14:38:45 -08:00
Bert Maher 787ebdc7b1 Use inline stores for object property initialization
When we know the object properties at jit time we can just
emit stores inline to do initialization, instead of calling memcpy.

Reviewed By: @markw65

Differential Revision: D1063044
2013-11-20 14:38:45 -08:00
Sean Cannella a6638af048 Fix OS X compilation warnings
Fix more printf type compilation warnings

Reviewed By: @markw65

Differential Revision: D1063319
2013-11-20 14:38:45 -08:00
Joel Marcey 7078150b4d Fix Pear some more. We now pass 95%+ of running tests.
Fix Pear to support HHVM error messages. Upstream changes.

https://github.com/pear/pear-core/pull/23

Reviewed By: @ptarjan

Differential Revision: D1063129
2013-11-20 14:38:45 -08:00
Stephen Heise 06fdff0f29 Include kernel instructions in perf counts
This patch standardizes that we always collect user+sys stats,
not just user stats.

Having fewer counter flavors is a prerequisite for one-day
sharing counters in the kernel.

Short-term this patch will change perflab behavior to start to count
kernel instructions.

Other tools such as perf and dynolog already collect user+sys stats.

Reviewed By: @markw65

Differential Revision: D1059681
2013-11-20 14:38:45 -08:00
Yumikiyo Osanai a2137e9825 Fix error_get_last() to be compatible with Zend
Make BaseExecutionContext::recordLastError() virtual since
file/line number information is only accessible in VMExecutionContext.

Closes #1260
Closes #1281

Reviewed By: @alexmalyshev

Differential Revision: D1061728

Pulled By: @scannell
2013-11-20 14:38:44 -08:00
Guilherme Ottoni 519d0e92ed Update support for perf events
The support for LLC and dTLB more precise events don't work in perf
anymore, so update them to use the more generic (but less accurate)
events.  While here, I added support for more events in tc-print:
iTLB, L1I, and L1D misses.

Ths diff also fixes a couple of issues in Func to deal with the fact
that a tx64 object is not created in tc-print anymore. These issues
were introduced when we got rid of Translator::Get() and company
recently, and they were seg-faulting tc-print.

Reviewed By: @bertmaher

Differential Revision: D1062649
2013-11-20 14:38:44 -08:00
Paul Tarjan 73bb00ac49 Make PDOStatement::__construct callable
zend can call it and a laravel unit test does

Reviewed By: @alexmalyshev

Differential Revision: D1062725
2013-11-20 14:38:44 -08:00
Owen Yamauchi b85fa7d06f Kill ATTRIBUTE_COLD
With our new linker script technology, we don't need this anymore.

Reviewed By: @edwinsmith

Differential Revision: D1062500
2013-11-20 14:38:44 -08:00
Sara Golemon 4a23fdc0dc Provide blowfish implementation for crypt()
Mostly an import of Zend code.

Reviewed By: @ptarjan

Differential Revision: D983797
2013-11-20 14:38:44 -08:00
Joel Marcey 6ff5f5ec7b Fix the way we find test files...
Instead of some sort of brute force, best effort way to get the test files, use the phpunit xml provided by each framework (if there is one).

Record the expect files again with this new information.

(Also, fixed a minor bug where Incomplete tests were not being put in the errors file)

Reviewed By: @alexmalyshev

Differential Revision: D1062413
2013-11-20 14:38:44 -08:00
Joel Marcey 21800bf32a Fix ZipFile. It was breaking Pear tests. And it wasn't matching Zend either.
Our ZipFile implementation was not matching Zend, particuarly in tell() and seek(). This reared its ugly head with the Pear test suite. So, I tried to fix this, using PlainFile as a model.

Reviewed By: @ptarjan

Differential Revision: D1061351
2013-11-20 14:38:43 -08:00
Abel Nieto 42b20b441a Abstract the functionality in c_Set into a base class.
As a first step in implementing FrozenSet, move *all* the functionality in
c_Set to an abstract BaseSet class. c_Set and c_FrozenSet can then both
inherit from BaseSet, except that they expose different PHP "interfaces"
(i.e. FrozenSet doesn't have any of the mutable methods).

Reviewed By: @paroski

Differential Revision: D1050796
2013-11-20 14:38:43 -08:00
Jordan DeLong 8c64de9a8c Replace a few instanceof(c_WaitHandle::classof()) checks with object attr
Now that we have it, might as well use it.

Reviewed By: @jano

Differential Revision: D1061030
2013-11-20 14:38:43 -08:00
Jordan DeLong d04d42f67a Prime method cache across requests by smashing an immediate in the TC
Reviewed By: @bertmaher

Differential Revision: D1060868
2013-11-20 14:38:43 -08:00
bsimmers 68d745477c Disable flaky Zend test
Reviewed By: @dariorussi

Differential Revision: D1061932
2013-11-20 14:38:43 -08:00
Alex Malyshev e7f2916b30 Have Reflection track the use variables of a closure
Need their name and value for ReflectionFunction::getStaticVariables

Reviewed By: @ptarjan

Differential Revision: D1060435
2013-11-20 14:38:43 -08:00
mwilliams 5017e3c6cc Use huge pages for the hot part of the runtime
MADV_HUGEPAGE only works on anonymous, privately mapped
memory. So re-map the hot part of the binary, and mark it huge.

Reviewed By: @edwinsmith

Differential Revision: D1061057
2013-11-20 14:38:43 -08:00
Sean Cannella db03be5f53 Fix clang errors
Fixing some clang errors that look like real bugs.

Reviewed By: @edwinsmith

Differential Revision: D1061452
2013-11-20 14:38:43 -08:00
Paul Tarjan 8d83afeaee Fill out user-land stream wrapper
This was a little broken. It is still a bit different from zend, but at least VFS works.

Reviewed By: @sgolemon

Differential Revision: D1053993
2013-11-20 14:38:42 -08:00
Julius Kopczewski 20dc3d7630 Fixing FastCGI support for KEEP_CONN
Fixing support for KEEP_CONN = false. The connection is now
closed *after* the currently server request is responded to.

Reviewed By: @scannell

Differential Revision: D1057616
2013-11-20 14:38:42 -08:00
Paul Tarjan 72286be212 fix ReflectionProperty for dynamic classes
I fixed ReflectionClass before, this should use it

Reviewed By: @dariorussi

Differential Revision: D1061173
2013-11-20 14:38:42 -08:00
Paul Tarjan 8a2f760ea1 update CodeIgniter Hash
They fixed the preg yelling upstream

Reviewed By: @JoelMarcey

Differential Revision: D1061177
2013-11-20 14:38:42 -08:00
Alex Malyshev dc3303356c Make ini_get('allow_url_fopen') return true
Needed for Assetic

Reviewed By: @ptarjan

Differential Revision: D1060610
2013-11-20 14:38:42 -08:00
seanc 874c9049e0 Add GCC 4.7.x workaround for asio
Summary: asio needs _GLIBCXX_USE_NANOSLEEP to compile on 4.7.x as well.
2013-11-20 07:25:03 -08:00
Paul Tarjan d71b06ace3 Don't email anyone since we do bulk pushes
The person who's diff is on top is not necessarily to blame
2013-11-19 18:14:34 -08:00
Jordan DeLong 5dfe3fec2e Add AsyncAwait opcode to speed up await code path
The logic for await expr is:

  - check if expr is null, if so return null
  - if expr is not a WaitHandle, call getWaitHandle

  - if the wait handle is finished, either pull out its result or
    throw its exception
  - else if it's unfinished, either suspend the continuation or if
    we're eagerly executing the async function, wrap it in a result
    wait handle and create an async function that will continue here.

This diff changes the null check to not do reference counting (use an
unnamed local instead of Dup), and makes an opcode to speed up the
logic in the second part, by removing function calls and reference
counting due to another Dup.

Reviewed By: @jano

Differential Revision: D1058415
2013-11-19 13:40:42 -08:00
bsimmers d15d5e045b New refcount optimization pass
This diff replaces the old DCE-based refcount optimization with one
based on an algorithm we trust a lot more. Both optimizations rely on each
produced reference being consumed exactly once, and this new pass verifies that
fact as it goes along. This caught a number of leaks and other refcounting bugs.

I tried to heavily document the code itself, so for an overview of the
optimization start at the optimizeRefcounts function in refcount-opts.cpp. A
few notes about changes not contained to refcount-opts.cpp:

- IncRef no longer produces a new SSATmp. This allows us to generate IR in more
  straightforward ways without worrying about which IncRefs chain to which
  DecRefs.
- All refcounting instructions are now marked Essential. DCE will leave them
  alone, and only optimizeRefcounts will move or remove them.
- The code in FrameState that knows how each opcode affects the current locals
  has been separated from the code to update the tracked state of those
  locals. This allows the optimization to also take advantage of this
  knowledge.
- OverrideLoc and SmashLocals have been removed, and their behavior has been
  folded into the instructions they used to follow. This was needed so we can
  process each instruction and its effects on locals atomically.

Reviewed By: @ottoni

Differential Revision: D1044602
Differential Revision: D1062844
Differential Revision: D1054603
2013-11-19 10:38:57 -08:00
Sean Cannella eb8dcf0a91 Fix RecursiveIteratorIterator issues
Fix a couple of issues with RecursiveIteratorIterator

Reviewed By: @aryx

Differential Revision: D1060266
2013-11-18 11:27:37 -08:00
Jordan DeLong 483f0abfb1 Remove CSE flag from GetCtxFwdCall
If this gets CSE'd, we will try to replace it with an IncRef,
which is a type error because it's not a subtype of Gen.

Reviewed By: @edwinsmith

Differential Revision: D1060856
2013-11-18 11:27:36 -08:00
Owen Yamauchi 00c678e8f9 Hoist the first-byte check out of is_strictly_integer
It turns out that checking the first byte of a string to see if it's in
the range ['0', '9'] is a better early-exit than the isStatic + hash
sign bit check. We can also use the NUL-termination invariant to make
the check slightly more efficient: no need to check the length
separately, but just subtract '0' and use unsigned comparison with 9.

Ad hoc instrumentation with stats counters shows that the first-byte
check bails us out in the vast majority of cases.

Reviewed By: @edwinsmith

Differential Revision: D1060828
2013-11-18 11:27:36 -08:00
Jordan DeLong bab354960b Remove HphpArray::m_hash; compute it from the this pointer
Now that @edwinsmith has hoisted various redundant computations of
m_hash, this is adds less instructions.  It's still a slight increase
in instructions, but stores are slightly down and loads in the noise.
It seems better in principle to do some extra math rather than some
extra memory accesses, and it saves a small amount of memory.

Reviewed By: @edwinsmith

Differential Revision: D1060836
2013-11-18 11:27:36 -08:00
Edwin Smith 104556b5b4 Unpeel the loops in HphpArray::find() and findForInsert()
This reduces loads and stores but costs a few more ALU instructions
that initialize registers that don't get used when we only probe
one time.

Reviewed By: @jdelong

Differential Revision: D1053987
2013-11-18 09:17:57 -08:00
Joel Marcey 2161e54895 Update Assetic hash because they fixed a bug
Assetic fixed a bug that was causing test failures for us.

https://github.com/kriswallsmith/assetic/pull/520

Reviewed By: @alexmalyshev

Differential Revision: D1060621
2013-11-18 09:17:53 -08:00
Edwin Smith b1951a2618 Use more ArrayInit
I noticed some unnecessary Array growing when looking at LLC-store-misses,
this fixes a few of the top ones.

Reviewed By: @markw65

Differential Revision: D1057028
2013-11-18 09:17:48 -08:00
Owen Yamauchi d22918b2cb Clean up Translator::Get() and stuff, remove TC-cycling logic
Calling through tx(), TranslatorX64::Get(), and Translator::Get() is
utter nonsense. The global tx64 object now doesn't need to be
thread-local; it can just be global, since there really is only ever one
during the entire process lifetime.

The TC-cycling logic isn't used, hasn't been tested in ages, and as such
is likely broken, so I'm removing it.

I also devirtualized a bunch of crap in Translator, and added the
override virt-specifier to the two legit overrides in TranslatorX64.

Reviewed By: @jdelong

Differential Revision: D1059757
2013-11-18 09:17:44 -08:00
Kun Chen 47a18001b6 Support getShortName and getNamespaceName for ReflectionFunctionAbstract
This diff added two methods getShortName and getNamespaceName to class ReflectionFunctionAbstract,
 so classes ReflectionMethod and ReflectionFunction can use these two methods.

The implementation is compatible with Zend implementation:

https://github.com/php/php-src/blob/0d7a6388663b76ebed6585ac92dfca5ef65fa7af/ext/reflection/php_reflection.c

Reviewed By: ptarjan

Differential Revision: D1058177
2013-11-18 09:17:39 -08:00
Sean Cannella da472bbb4d Remove dead code in hphp/compiler
While working on something else I noticed a bunch of dead code (presumably related to hphpc) so remove it.

Reviewed By: @markw65

Differential Revision: D1059801
2013-11-18 09:17:35 -08:00
Alex Malyshev 6c63687b65 Implement PDO::sqliteCreateFunction (again)
Need to sync VM state before calling functions that execute
SQL queries, some of which are PDOStatement::{execute,fetch}.

Reviewed By: ptarjan

Differential Revision: D1059768
2013-11-18 09:17:26 -08:00
Paul Tarjan 3a9c18fe82 deal with case-insensitivity in get_class_methods
Reviewed By: @jdelong

Differential Revision: D1057571
2013-11-18 09:17:21 -08:00
Joel Marcey 50e24864bc Record the Laravel expect file again after git hash change
We changed the Laravel git has (due to ptarjan getting a pull request accepted). Let's record the expect file again.

Reviewed By: @alexmalyshev

Differential Revision: D1059633
2013-11-18 09:17:17 -08:00
Alex Malyshev 12d4f1a0e6 Add support for named subpatterns in preg_replace*
It was implemented for preg_match but not others.

Reviewed By: ptarjan

Differential Revision: D1052338
2013-11-18 09:17:12 -08:00
Alex Malyshev e1177bf11f Handle UTF-8 chars in string_html_encode like Zend
Changes string_html_decode's behavior with non-ASCII UTF-8 chars to
be more like Zend's.

Reviewed By: ptarjan

Differential Revision: D1055317
2013-11-18 09:17:07 -08:00
bsimmers c26c90206b Disable flaky test/zend/good/ext/standard/tests/file/fileowner_basic.php
Reviewed By: @dariorussi

Differential Revision: D1059751
2013-11-18 09:17:01 -08:00
Joel Marcey 7881fcf3e3 Graylist some tests for Pear and modify blacklist and graylist handling
The Pear tests may be somewhat out of date. There are many tests that fail with HHVM, but also fail PHP 5.5. And, HHVM and PHP 5.5. are printing the same "different than expected" output.

Let's whitelist these tests and don't count them as failures or passes.

During this process, I modified the way we handle blacklist and graylist tests. Basically just move these to "disabled" during the install process. That way we know they won't get executed.

Reviewed By: @ptarjan

Differential Revision: D1058987
2013-11-15 15:04:10 -08:00
Paul Tarjan df859438ee update laravel hash
They took 2 of my fixes upstream.

Reviewed By: @JoelMarcey

Differential Revision: D1058397
2013-11-15 15:04:10 -08:00
Abel Nieto 7372fa38b7 Implement COW when materializing a FV
Invoking a Vector's toFrozenVector() method is now an O(1) operation.

Subsequent modifications to the vector trigger a copy-on-write.

Reviewed By: @paroski

Differential Revision: D1012992
2013-11-15 15:04:10 -08:00
Joel Marcey e1314ffc61 Fix wordwrap. It wasn't matching Zend.
Zf2 tests were failing wordwrap with input like:

wordwrap('foobar*foobar', 6, '*', true);

HHVM would print: foobar**foobar
Zend would print: foobar*foobar

Reimplement wordwrap in PHP-land

Reviewed By: @ptarjan

Differential Revision: D1047300
2013-11-15 15:04:09 -08:00
Alok Menghrajani c14d9fce0b Switch nullable type failures to recoverable_error
The code in www is basically clean with a few last diffs going in
next week. There's no longer any reason to treat these failures in a
different way.

Reviewed By: @paroski

Differential Revision: D1050132
2013-11-15 15:04:09 -08:00
Joel Marcey 7d8e60cc0c Need to check for added pull requests to force possible redownload.
Since we added new pull requests, we need to force a framework redownload if they don't have it. E.g., @ptarjan's cron job needs to redownload Pear because of this.

Reviewed By: @alexmalyshev

Differential Revision: D1057685
2013-11-15 15:04:09 -08:00
Mike Magruder f272385380 Lookup Continuation functions during process init instead of on each next/send/raise call
We were seeing a surprising number of hits with perf in FixedStringMap::find() under WaitHandle::join(). This is used while looking up the methods send, next, and raise on Continuation in c_Continuation:call_send() and friends. Since there's a single method to find, go find it during process init and use the result there instead of doing a string lookup on each call.

Reviewed By: @markw65

Differential Revision: D1056356
2013-11-15 15:04:08 -08:00
Paul Tarjan 8fd0426b88 fix SimpleXML count
It looks like if you have two children with the same name, we just make an array of them. So we have to count them up too.

Reviewed By: @JoelMarcey

Differential Revision: D1054872
2013-11-15 15:04:08 -08:00
Paul Tarjan f8c949707b Fix reflection about private variables in traits
I don't know why they originally did it like this. I think it was just an oversight by Parker last year in D599728

Reviewed By: @JoelMarcey

Differential Revision: D1056703
2013-11-15 15:04:08 -08:00
Paul Tarjan 4a0f934975 Add pretty printer for Class*
Reviewed By: @markw65

Differential Revision: D1056709
2013-11-15 15:04:08 -08:00
Paul Tarjan 525d97518e do special comparisons for DateTime
Zend does, them. We should too. I basically copied `ArrayObject`.

Reviewed By: @jdelong

Differential Revision: D1054508
2013-11-15 15:04:07 -08:00
Paul Tarjan 067577e5c8 make offsetExists match offsetGet
and while I'm there, make it more explicit what the failure case is for offsetGet

Reviewed By: @JoelMarcey

Differential Revision: D1054887
2013-11-15 15:04:07 -08:00
Joel Marcey 5e39267ee6 Pull more code in for PEAR
The file not found errors we were getting for PEAR was due to the fact that we needed more PEAR packages. I added some more pull requests.

Reviewed By: @ptarjan

Differential Revision: D1057255
2013-11-15 15:04:07 -08:00
Edwin Smith 6f3f58a7fa Fix copyPackedAndResizeIfNeededSlow() when only hashtable is full
If m_used==0 but isFull()==true, the hashtable is full but the
array is empty.  We try to copy 0 elements, which crashes because
wordcpy() is a do-while loop.  But also, we should be compacting
in this case instead of growing.  Add an assert, and do compaction.

Reviewed By: @markw65

Differential Revision: D1057100
Differential Revision: D1059120
2013-11-15 15:04:06 -08:00
Joel Marcey 954bbd1cc1 Record the yii expect file again
After @ptarjan's awesome find about the wrong phpunit.xml being used in testing, let's record the yii expect file again.

Reviewed By: @ptarjan

Differential Revision: D1057061
2013-11-15 15:04:06 -08:00
Paul Tarjan 279b14c3bf fix test path for yii
yii has multiple xml files (for example blogs and such) some of which appear alphabetically before `tests`. Lets make sure we find the right one.

Reviewed By: @JoelMarcey

Differential Revision: D1056958
2013-11-15 15:04:06 -08:00
mwilliams c457a79885 Apply some strict-alias warning fixes
Its a little alarming that gcc warns about eg using an
int, and also memcpy'ing to/from that int (which is explicitly
allowed by the standard's aliasing rules).

Reviewed By: @jdelong

Differential Revision: D1052741
2013-11-15 15:03:27 -08:00
Yumikiyo Osanai 3a6a8f282e eval() should return false on syntax errors
eval() should return false on syntax errors

Closes #1267
Closes #1270

Reviewed By: @alexmalyshev

Differential Revision: D1055028

Pulled By: @scannell
2013-11-15 10:13:48 -08:00
Guilherme Ottoni 1211c032db Avoid ret branch miss in Continuation::send, next, raise
These functions are generally called from enterTCHelper, but their
return address is set so that they return to the callToExit stub.
This was causing the ret instruction ending this translations to miss
all the time, since the return address didn't match what the hardware
return address stack predicted.

This diff marks these functions as AttrVMEntry, a new attribute
meaning that the function is generally a VM entry point.  This
information is used to generate a predictable direct branch to the
callToExit stub.

Reviewed By: @swtaarrs

Differential Revision: D1054750
2013-11-15 10:13:48 -08:00
Paul Tarjan 10305b01e9 unwrap all IteratorAggregates in IteratorIterator
Reviewed By: @alexmalyshev

Differential Revision: D1055581
2013-11-15 10:13:47 -08:00
Paul Tarjan 4cd76aae2a implement fileinfo
A direct port of zend's forked libmagic code embeded in the same way they do it. All the bad tests are from `var_dump` imcompatability or unrelated unimplemented functions.

Reviewed By: @paroski

Differential Revision: D1050594
2013-11-15 10:13:41 -08:00
mwilliams a0e1b2409a Don't dump bytecode by default
There also doesn't seem to be a good reason for
forcing the jit off. I'm assuming these got committed by
accident.

Reviewed By: @edwinsmith

Differential Revision: D1055752
2013-11-15 07:51:53 -08:00
Abel Nieto 36bff65cf6 Add test case for mutating collections while iterating
In a previous version of D1012992 I broke Vector by
accidentally disallowing the following pattern

  $v = Vector {1, 2, 3};
  foreach ($v as $e) {
    $v[0] = 42;
  }

i.e. we should be able to mutate elements of Vector (and Map, and StableMap)
while iterating over the collection at the same time.

The bug was caught by a flib unit test, but it seems there wasn't an
hphp unit test that tested the behaviour.

So I'm adding it.

Reviewed By: @paroski

Differential Revision: D1056037
2013-11-15 07:51:42 -08:00
bsimmers a2b39089dd Disable test/zend/good/ext/pcntl/tests/pcntl_wait.php
It's failing in asan builds. Disabling so we can investigate without
time pressure.

Reviewed By: @ptarjan

Differential Revision: D1055854
2013-11-15 07:51:37 -08:00
Paul Tarjan 7cbeaf5a53 make default message work
implode doesn't know what to do with Vectors. I also like having them on their own line for easy copy-paste (I'm ok to undo that if you have a reason not to).

Reviewed By: @JoelMarcey

Differential Revision: D1055626
2013-11-15 07:51:32 -08:00
Joel Marcey d16010495c Add no proxy information for FB internal access (FacebookPHPSDK)
The FacebookPHPSDK curl test was failing since we had a proxy set and that is not good for internal curl access. Add no_proxy settings.

Reviewed By: @alexmalyshev

Differential Revision: D1055647
2013-11-15 07:51:27 -08:00
Enis Rifat Sert a5f9d518e0 Implement ZipArchive
This diff implements ZipArchive class and zip functions of
PHP, as described in http://php.net/manual/en/class.ziparchive.php and
http://www.php.net/manual/en/ref.zip.php respectively.

This diff is not complete, summary and test plan will be updated as
the code revised.  Also I should land a third-party repo commit as
well, libzip, before I land this code.

Reviewed By: @ptarjan

Differential Revision: D1040058
2013-11-14 15:30:58 -08:00
Sara Golemon 8db131ac79 Embed per-extension systemlibs 2013-11-14 14:19:35 -08:00
Joel Marcey dd68b94be2 Bump Twig Hash to add large int parsing fix
@ptarjan successfully got an upstream Twig pull request accepted for tests that parse large ints.

We are now Twig=100% :)

Reviewed By: @alexmalyshev

Differential Revision: D1055267
2013-11-13 19:40:47 -08:00
Paul Tarjan c18087a601 Fix bug causing Pear to fatal
Framework::$parallel needs to be set in the constructor only, or Pear fatals

Reviewed By: @JoelMarcey

Differential Revision: D1054784
Differential Revision: D1054961
Differential Revision: D1055096
2013-11-13 19:40:46 -08:00
Eugene Letuchy 9295135383 collections cleanup: throw_expected_array{_or_collection}_exception
Some array_* utils were migrated to understand collections,
 but still warn that "array_xyz expects array(s)" when passed a
 scalar.  This diff audits all instances of throw_bad_array_exception
 and renames some to throw_expected_array_exception and others to
 throw_expected_array_or_collection_exception, depending on whether
 the function has been migrated.

Reviewed By: anietoro

Differential Revision: D1053736
2013-11-13 14:10:37 -08:00
Joel Marcey 94eed3a392 Fix the flakiness of Pear
WTF PEAR!!?!?!

Well, Pear was out of control running tests in separate process with wildly changing statuseses for a given test depending on the time of day and alignment of the moon. So created a serial option...

We have consistency now. --record and subsequent runs give the same results.

In the future, maybe allow the parallel/serial flag to be set at the command line, but for now just setting this within the framework class itself.

Pear runs much slower this way. Results can't be viewed piecemail (gotta wait until the end of the run). And I will need to fix the test run messages that get printed in the diff/errors/fatals file to extract single test files this way (the message now tells you to run the entire test suite again).

This script is not affecting flib tests.

Reviewed By: @ptarjan

Differential Revision: D1054205
2013-11-13 14:10:36 -08:00
Owen Yamauchi 2eae7c350d Replace REQ_INTERPRET with judicious interp-ones
REQ_INTERPRET is kind of heavyweight when we really just want a
conditional interp-one. This diff replaces REQ_INTERPRET in failure
cases with an interp-one on an exit trace, and removes the ReqInterpret
instruction. We still need the service requests, for the debugger case.

Reviewed By: @swtaarrs

Differential Revision: D1052990
2013-11-13 14:10:36 -08:00
Alex Malyshev 4a03d98ba9 Move string out of bounds warning under HH syntax
Zend doesn't raise a warning, and this causes Joomla tests to fail

Reviewed By: @ptarjan

Differential Revision: D1051636
2013-11-13 14:10:36 -08:00
Jordan DeLong c8f0886f72 Tweak magic call prologues to be a bit more efficient
They were doing increfs and decrefs while trying to get the
args into the packed array, and went through a C++ helper.  They also
would jump backward in the nPassed = 2 case and do a BIND_JMP in the
middle of the prologue, which prevents fallthrough from ever working.
This fixes that, uses the empty array for nPassed = 0, and
disentangles the code from the other prologues.  (I didn't do the same
for the ARM version for now.)

Reviewed By: @markw65

Differential Revision: D1049527
2013-11-13 14:10:35 -08:00
Alex Malyshev 516207b436 Define ENT_SUBSTITUTE, fix flags handling in f_html* functions
We were just casting the flags argument from an int to a
StringUtil::QuoteStyle, but the arg can have more bits set in it.

Reviewed By: @ptarjan

Differential Revision: D1053206
2013-11-13 14:10:35 -08:00
Joel Marcey 0e404be0b6 Print better test run information.
Print out the actual command line string to run a given test. This will be printed in the errors/fatals/diff files.

Reviewed By: @ptarjan

Differential Revision: D1053801
2013-11-13 14:10:35 -08:00
Joel Marcey b84d93eb4a Fix install bug after move to Framework classes
This bug basically prohibited the install of frameworks. Why? Because I was doing setXXX calls in the Framework constructor even if the framework wasn't installed. So I fixed that. To do this quickly, I removed the parallelization of multiple framework installs. But since the install should be rare, this quick fix is worth the time hit.

Failing flib tests have nothing to do with this script

Reviewed By: @ptarjan

Differential Revision: D1053633
2013-11-13 14:10:34 -08:00
Eugene Letuchy d25f3414a7 teach array_push about collections
Straight forward for Vectors and Sets: continue to throw
 exceptions for mapping types. ## array_push ## takes its array
 parameter as a reference, so the semantics are very close to a
 collection helper function.

Reviewed By: anietoro

Differential Revision: D1049841
2013-11-13 13:36:58 -08:00
Jordan DeLong 87addf0293 Remove a few dead functions from runtime.cpp
Reviewed By: @ottoni

Differential Revision: D1051475
2013-11-13 13:36:58 -08:00
Mike Magruder 6ecd0c9318 Minor optimization to the common path in hhvm extension stubs
Reduce the number of instructions needed on what ought to be the most common path on some of the simpler extension stubs. For calls to functions on this_ with no locals the tests in free_frame_locals_inl and friends were redundant. Provided a path to avoid those. Also out-lined a bit of code which should be more rare to try to save a little code size, and added some LIKELY/UNLIKELY markers. Switched a memcpy to a struct assignment. Looking at the asm output for th_10WaitHandle_getWaitHandle() shows a leaner and straighter path after the call thru to the return. The difference bewtween the memcpy and the struct assignment is (strangely) slightly different register scheduling which produces what I imagine could be fewer stalls.

Reviewed By: @jdelong

Differential Revision: D1051867
2013-11-13 13:36:57 -08:00
Joel Marcey f80c9b89bb Allow Zend to be used to run the unit tests for the frameworks
This gives the option to allow zend to be used to run the framework unit tests. This could be good for comparison purposes or to whitelist tests for HHVM that Zend also fails. Right now, we specify the path to the Zend binary. Later, we could see about using env variables or something to retrieve it.

Reviewed By: @ptarjan

Differential Revision: D1053279
2013-11-13 13:36:57 -08:00
bsimmers d7496a2fad Fix whitespace error in expect file
we think it was arc land's fault

Reviewed By: @jdelong

Differential Revision: D1053214
2013-11-13 13:36:57 -08:00
Rachel Kroll 6f3319f881 Clean up lingering elements of old file-cache API
Fix callers which depended on old API, and drop compat hacks

Reviewed By: bmaurer

Differential Revision: D1038433
2013-11-13 13:36:56 -08:00
Joel Marcey aa7f6646b2 Add proxies to our testing
We may be failing tests because the test needs access to the outside world, but we cannot get there due to the default firewall behavior. Provide the proxy info as part of the proc_open command to run the tests.

Also fixed a "thumb" problem. Better to rely on the contents of the expect file vs the out file to see if things ran as expected instead of setting variables all over the place.

Reviewed By: @ptarjan

Differential Revision: D1053079
2013-11-13 13:12:42 -08:00
Fred Emmott 1388a11eb5 Reimplemented RecursiveIteratorIterator
RecurisveIteratorIterator's original reverse engineer from lack
of PHP.net documentation had some parity differences -- make it better.

Closes #1260
Closes #1266

Reviewed By: @ptarjan

Differential Revision: D1052707

Pulled By: @scannell
2013-11-13 13:12:38 -08:00
Sean Cannella 0f5bf20761 Fix GCC 4.7.x compilation issue with lambda
GCC 4.7.x on Amazon Linux AMI compilation results in the linker
being unable to find the lambda so de-lambdify it.

Closes #1264

Reviewed By: @ptarjan

Differential Revision: D1052778
2013-11-13 13:12:33 -08:00
Drew Paroski de2b766540 Fix code path that can overflow the native stack
We had a bug where a PHP program can infinitely recurse in a certain way
that doesn't hit any of our native stack overflow checks and causes the
process to segfault. Below I've included a snippet of the callstack that
caused HHVM to crash.

The fix is to make invokeFunc(), invokeFuncFew(), and invokeContFunc()
unconditionally perform a stack overflow check for the native stack. I
tried to keep the fix minimal and non-invasive so that we can get this
hotfixed if needed.

  #0  0x00000000032ba2ef in malloc ()
  #1  0x000000000257401e in HPHP::Util::canonicalize(char const*, unsigned long, bool) ()
  #2  0x0000000001c15f0e in HPHP::resolve_include(HPHP::String const&, char const*, bool (*)(HPHP::String const&, void*), void*) ()
  #3  0x0000000001bd0327 in HPHP::Eval::resolveVmInclude(HPHP::StringData*, char const*, stat*) ()
  #4  0x0000000001fe47d0 in HPHP::VMExecutionContext::lookupPhpFile(HPHP::StringData*, char const*, bool*) ()
  #5  0x0000000001fe521a in HPHP::VMExecutionContext::evalInclude(HPHP::StringData*, HPHP::StringData const*, bool*) ()
  #6  0x0000000001c17231 in HPHP::AutoloadHandler::Result HPHP::AutoloadHandler::loadFromMap<HPHP::ConstantExistsChecker>(HPHP::String const&, HPHP::String const&, bool, HPHP::ConstantExistsChecker const&) ()
  #7  0x0000000001c174ed in HPHP::AutoloadHandler::autoloadConstant(HPHP::StringData*) ()
  #8  0x00000000020c1c73 in HPHP::Unit::loadCns(HPHP::StringData const*) ()
  #9  0x0000000001f1d10e in HPHP::Transl::lookupCnsHelper(HPHP::TypedValue const*, HPHP::StringData*, bool) ()
  #10 0x000000002827f855 in ?? ()
  #11 0x00000000026e566e in enterTCHelper ()
  #12 0x0000000001f35ef0 in HPHP::Transl::TranslatorX64::enterTC(unsigned char*, void*) ()
  #13 0x0000000002018004 in HPHP::VMExecutionContext::enterVM(HPHP::TypedValue*, HPHP::ActRec*) ()
  #14 0x000000000201821c in HPHP::VMExecutionContext::reenterVM(HPHP::TypedValue*, HPHP::ActRec*, HPHP::TypedValue*) ()
  #15 0x0000000002018612 in HPHP::VMExecutionContext::invokeFunc(HPHP::TypedValue*, HPHP::Func const*, HPHP::Array const&, HPHP::ObjectData*, HPHP::Class*, HPHP::VarEnv*, HPHP::StringData*, HPHP::VMExecutionContext::InvokeFlags) ()
  #16 0x0000000001c146d0 in HPHP::vm_call_user_func(HPHP::Variant const&, HPHP::Array const&, bool) ()
  #17 0x0000000001c17107 in HPHP::AutoloadHandler::Result HPHP::AutoloadHandler::loadFromMap<HPHP::ConstantExistsChecker>(HPHP::String const&, HPHP::String const&, bool, HPHP::ConstantExistsChecker const&) ()
  #18 0x0000000001c174ed in HPHP::AutoloadHandler::autoloadConstant(HPHP::StringData*) ()
  #19 0x00000000020c1c73 in HPHP::Unit::loadCns(HPHP::StringData const*) ()
  #20 0x0000000001f1d10e in HPHP::Transl::lookupCnsHelper(HPHP::TypedValue const*, HPHP::StringData*, bool) ()
  #21 0x000000002827f855 in ?? ()
  #22 0x00000000026e566e in enterTCHelper ()
  #23 0x0000000001f35ef0 in HPHP::Transl::TranslatorX64::enterTC(unsigned char*, void*) ()
  #24 0x0000000002018004 in HPHP::VMExecutionContext::enterVM(HPHP::TypedValue*, HPHP::ActRec*) ()
  ...
  #28992 0x0000000001c174ed in HPHP::AutoloadHandler::autoloadConstant(HPHP::StringData*) ()
  #28993 0x00000000020c1c73 in HPHP::Unit::loadCns(HPHP::StringData const*) ()
  #28994 0x0000000001f1d10e in HPHP::Transl::lookupCnsHelper(HPHP::TypedValue const*, HPHP::StringData*, bool) ()
  #28995 0x000000002827f855 in ?? ()
  #28996 0x00000000026e566e in enterTCHelper ()
  #28997 0x0000000001f35ef0 in HPHP::Transl::TranslatorX64::enterTC(unsigned char*, void*) ()
  #28998 0x0000000002018004 in HPHP::VMExecutionContext::enterVM(HPHP::TypedValue*, HPHP::ActRec*) ()
  #28999 0x000000000201821c in HPHP::VMExecutionContext::reenterVM(HPHP::TypedValue*, HPHP::ActRec*, HPHP::TypedValue*) ()
  #29000 0x0000000002018612 in HPHP::VMExecutionContext::invokeFunc(HPHP::TypedValue*, HPHP::Func const*, HPHP::Array const&, HPHP::ObjectData*, HPHP::Class*, HPHP::VarEnv*, HPHP::StringData*, HPHP::VMExecutionContext::InvokeFlags) ()
  #29001 0x0000000001c146d0 in HPHP::vm_call_user_func(HPHP::Variant const&, HPHP::Array const&, bool) ()
  #29002 0x0000000001c17676 in HPHP::AutoloadHandler::Result HPHP::AutoloadHandler::loadFromMap<HPHP::ClassExistsChecker>(HPHP::String const&, HPHP::String const&, bool, HPHP::ClassExistsChecker const&) ()
  #29003 0x0000000001c17a57 in HPHP::AutoloadHandler::invokeHandler(HPHP::String const&, bool) ()
  #29004 0x00000000020cb504 in HPHP::Unit::loadClass(HPHP::NamedEntity const*, HPHP::StringData const*) ()
  #29005 0x000000000203247e in void HPHP::VMExecutionContext::dispatchImpl<2>(int) ()
  #29006 0x000000000203ef43 in HPHP::VMExecutionContext::dispatchBB() ()
  #29007 0x0000000001f35f70 in HPHP::Transl::TranslatorX64::enterTC(unsigned char*, void*) ()
  #29008 0x0000000002017ed7 in HPHP::VMExecutionContext::enterVM(HPHP::TypedValue*, HPHP::ActRec*) ()
  #29009 0x000000000201888d in HPHP::VMExecutionContext::invokeFunc(HPHP::TypedValue*, HPHP::Func const*, HPHP::Array const&, HPHP::ObjectData*, HPHP::Class*, HPHP::VarEnv*, HPHP::StringData*, HPHP::VMExecutionContext::InvokeFlags) ()
  #29010 0x0000000002018ea0 in HPHP::VMExecutionContext::invokeUnit(HPHP::TypedValue*, HPHP::Unit*) ()
  #29011 0x0000000001c15964 in HPHP::invoke_file(HPHP::String const&, bool, char const*) ()
  #29012 0x0000000001c19a52 in HPHP::include_impl_invoke(HPHP::String const&, bool, char const*) ()
  #29013 0x0000000001c5d883 in HPHP::hphp_invoke(HPHP::ExecutionContext*, std::basic_fbstring<char, std::char_traits<char>, std::allocator<char>, std::fbstring_core<char> > const&, bool, HPHP::Array const&, HPHP::VRefParamValue const&, std::basic_fbstring<char, std::char_traits<char>, std::allocator<char>, std::fbstring_core<char> > const&, std::basic_fbstring<char, std::char_traits<char>, std::allocator<char>, std::fbstring_core<char> > const&, bool&, std::basic_fbstring<char, std::char_traits<char>, std::allocator<char>, std::fbstring_core<char> >&, bool, bool, bool) ()
  #29014 0x0000000001b2659e in HPHP::RPCRequestHandler::executePHPFunction(HPHP::Transport*, HPHP::SourceRootInfo&, HPHP::RPCRequestHandler::ReturnEncodeType) ()
  #29015 0x0000000001b285d3 in HPHP::RPCRequestHandler::handleRequest(HPHP::Transport*) ()
  #29016 0x0000000001b6b85b in HPHP::XboxWorker::doJob(HPHP::XboxTransport*) ()
  #29017 0x0000000001b669a3 in HPHP::JobQueueWorker<HPHP::XboxTransport*, HPHP::Server*, true, false, HPHP::JobQueueDropVMStack>::start() ()
  #29018 0x000000000252c127 in HPHP::AsyncFuncImpl::ThreadFunc(void*) ()
  #29019 0x00007f1ce3787f88 in start_thread (arg=0x7f1c377ff700)

Reviewed By: @jdelong

Differential Revision: D1052293
2013-11-13 13:12:29 -08:00
Nicholas Ormrod 26c966423f rm tr1
C++11 has standardized the TR1 implementation; the latter
should now be purged.

With the deprecation of gcc-4.6, we have full C++11 support and are
capable of moving off of tr1. Further, moving to gcc-4.8 with tr1
causes some compilation issues, incentivising an immediate switch.

== How ==

  echo A | codemod --extensions h,cpp,cc,d,tcc 'std::tr1::' 'std::'
  echo A | codemod --extensions h,cpp,cc,d,tcc 'tr1::' 'std::'
  echo A | codemod --extensions h,cpp,cc,d,tcc 'include\s*<tr1/' 'include <'
  echo A | codemod --extensions h,cpp,cc,d,tcc '\s*namespace tr1 = std::tr1;\n' ''
  echo A | codemod --extensions h,cpp,cc,d,tcc '\s*using namespace tr1;\n' ''
  echo A | codemod --extensions h,cpp,cc,d,tcc 'using namespace std::tr1;' 'using namespace std;'

Performing
  ls | grep -v third-party | xargs egrep --color=auto -RIws "tr1"
yields a few non-comment results in
FacebookUpdate/windows/omaha/third_party/gtest/include/gtest/ and
facer/engine/worker/gearmand_0.11/ (seems like non-fb code), some
html (which has not been changed), ti/etc/wrapper.py (this looks like
some compatibility code), and linters/cpplint/ (which seem acceptable).

There are a few files which use tr1 legitimately. Specifically, google
value-parameterized tests require tr1::tuple, and do not work with
std::tuple. Fortunately, these are all cpp test files, not headers.
These files have had their codemod changes reverted.

tr1::functions may be initialized with NULL. std::function makes this
explicit and only allows construction from a newfangled nullptr_t. Clang
is very strict about this, so some NULLs needed to be changed to nullptrs.

== HPHP ==

Most of the non-codemod changes were to hphp. hphp needed to specialize
some hash functions in namespace std::tr1; the tr1 level has been
removed and now-duplicate definitions have been fixed.

hphp/tools/tc-print/perf-events.h makes use of std::tr1::array::assign,
which is no longer a standard function. Uses of assign have now been
replaced with fill. Of note, the arrays are of integral type, and so
slight differences in copy/move/delete semantics between fill and assign
should be irrelevant.

Reviewed By: @andrewjcg

Differential Revision: D1052036
2013-11-12 10:33:08 -08:00
steffen 772f598ff6 PDOStatement::queryString not set in all cases
PDOStatement::queryString right now is not being set when using
 the regular PDOStatement. If you use PDOStatement you don't want the
 constructor to be called, but you want queryString to be set in any
 case.

Closes #1211
Closes #1263

Reviewed By: @ptarjan

Differential Revision: D1051402

Pulled By: @scannell
2013-11-12 10:30:14 -08:00
Alex Malyshev 0c796cec44 Revert "Implement PDO::sqliteCreateFunction"
This reverts commit fc7fc47221308572e34e00b22d96773a1d18d051.
Was breaking open source build.

Reviewed By: @ptarjan

Differential Revision: D1052342
2013-11-12 10:30:10 -08:00
Joel Marcey 7af3cb978f Create classes for the frameworks
A fairly sizeable design change. Now all frameworks are subclasses of a master abstract Framework class. This makes special casing better and easier (e.g. Pear). And it is just better code, I think, for long term maintainability.

Reviewed By: @ptarjan

Differential Revision: D1049900
2013-11-12 10:30:01 -08:00
Paul Tarjan 6d0e85f4e3 Don't serialize Objects in ReflectionClass
Objects can change out from under this caching (dynamic properties) so this is safest. If it turns out to be perf critacl we can cut the data into cacheable and not. But then we'll have it figure out what key to use, since serializing it isn't in the contract of this class.

Reviewed By: @alexmalyshev

Differential Revision: D1051775
2013-11-12 10:29:57 -08:00
Paul Tarjan 3105114ae5 print file name
nice to have the name of the test at least

Reviewed By: @JoelMarcey

Differential Revision: D1052179
2013-11-12 10:29:52 -08:00
Stephen Chen b8cca52a9a Log requests that were timed out while queuing to access.log
Previously when we timeout requests that's been sitting on the queue for too
long, we just return 503 to the client on the transport. In addition to that, we
should log the request in access.log

Reviewed By: afrind

Differential Revision: D1033156
2013-11-12 10:29:48 -08:00
Edwin Smith 4c74bd2976 Remove HOT_FUNC
These macros are NOPs now, due to D1046368.  Remove them entirely.

Reviewed By: @markw65

Differential Revision: D1050690
2013-11-12 10:29:26 -08:00
Drew Paroski 779ce103ea Update unserialize to support moving all collections to a namespace
This diff extends the approach from D1031058 so that unserialization is
both forwards/backwards compatible with migrating all collection classes
to the HH namespace.

Reviewed By: anietoro

Differential Revision: D1050299
2013-11-12 10:24:14 -08:00
Jordan DeLong 60fcacb5f7 Some tweaks to conv_10
Some parameters were unused, and the length output parameter
can be sent back in a register.

Reviewed By: @edwinsmith

Differential Revision: D1050294
2013-11-12 10:24:10 -08:00
Jordan DeLong 34fd7cb844 Fix an issue with methodCacheSlowerPath if Fatal == false
After we store the null Func, it was setting an invName on
the ActRec even though it's not a magic call.  It would also update
the MCE as if it were magic.  I'm not sure if this could've caused a
bug (maybe someone would treat the invName as a VarEnv, since there
should never be an invName on a non-prelive actrec?)

Reviewed By: @bertmaher

Differential Revision: D1050301
2013-11-12 10:24:05 -08:00
Jordan DeLong f11209f4c4 Add string_data_eq_same function object
Similar to string_data_same, except uses exact equality first.

Reviewed By: @scannell

Differential Revision: D1048085
2013-11-12 10:23:56 -08:00
Yumikiyo Osanai 0d3f4092d3 APC shouldn't show as loaded when disabled
This modifies get_loaded_extensions() to not show the APC
extension when Server::APC::EnableApc is false.

Closes #1103
Closes #1262

Reviewed By: @JoelMarcey

Differential Revision: D1050685

Pulled By: @scannell
2013-11-12 10:23:52 -08:00
Jordan DeLong 8498e97562 Fix performance of array operator+= when lhs has refcount of 1
The change to make this unconditionally allocate a new array
changes big-O behavior of user code in some situations.  Thanks to
lesha and andrewparoski for catching this.  An equivalent case for
array_merge shouldn't be possible because an inc ref always happens to
pass it to the builtin.

Reviewed By: @paroski

Differential Revision: D1046251
2013-11-12 10:23:47 -08:00
Jordan DeLong 05718fd22c Fix build--redefinition of s_storage
Reviewed By: @edwinsmith

Differential Revision: D1050880
2013-11-12 10:23:43 -08:00
Edwin Smith abfb1b0684 Streamline findForNewInsert and copy/grow loops.
Remove the inline restrictions from findForNewInsert(), and
pass in table & mask so the loads from m_tableMask and m_hash
can be hoisted out of the hashtable init loops in Grow & Copy.
Also, replace memcpy/memset with loops that operate on words
at a time. (no alignment checks, even #s of words).

Reviewed By: @jdelong

Differential Revision: D1047021
2013-11-12 10:23:38 -08:00
Paul Tarjan 3c4ba6d1e6 make (array) of ArrayObject return the contents
I originally tried to use `o_get` but that isn't const, so I added a const version.

A side effect is `var_dump` of an ArrayObject now shows the inner array. Are we cool with that? I like it.

I also tried to move this class down to C++ but that is too much work for this.  @sgolemon is there an easy way to have the class in C++ but most of the impl in PHP?

Reviewed By: @jdelong

Differential Revision: D1041009
2013-11-12 10:23:34 -08:00
seanc c6382b6c23 CMake fix for GCC 4.7.x
Summary: Fix GCC 4.7.x build on some platforms for the following error:
error: ‘sleep_for’ is not a member of ‘std::this_thread’

Closes #1264
2013-11-11 15:58:54 -08:00
Sean Cannella 02ad508647 Disable FastCGI on aarch64
Summary: FastCGI doesn't currently build on aarch64 due to lack of Thrift support, disable it.

Reviewed By: @ptarjan
2013-11-11 04:47:53 -05:00
Alan Frindell 9fd97af110 Fix LibEventServer takeover
I refactored the logic here and missed a case that sets m_accept_socket back to -1 for a server that takes over.  This doesn't affect it's operation, but makes it unable to yield its fd to the next server (eg: 2nd gen takeover was busted)

Reviewed By: @paroski

Differential Revision: D1050529
2013-11-11 09:51:18 -08:00
Alan Frindell e5e065c8cf admin endpoint to change the log level
This is super useful for debugging ProxygenServer

Reviewed By: @jdelong

Differential Revision: D1049645
2013-11-11 09:51:11 -08:00
Rachel Kroll be19d77a4f Accept paths without leading /, too
Paths without a leading / were being rejected by MakePathList.
This changes the code to match the original FileCache::writeDirectories
logic.  It also drops the "return the filename, too" scheme since the only
call site just throws it out anyway.

Reviewed By: @paroski

Differential Revision: D1050552
2013-11-11 09:51:07 -08:00
Jordan DeLong feeda44dd0 Remove CSE flag from LdClsCachedSafe
If this instruction returns null, it's not safe to CSE it if
something in between may have defined the class.

Reviewed By: @markw65

Differential Revision: D1050386
2013-11-11 09:50:59 -08:00
Jordan DeLong d4ac83521a Translate InstanceOf
Mostly can use opcodes we've made for InstanceOfD, with a few
other additions.

Reviewed By: @markw65

Differential Revision: D1050261
2013-11-11 09:50:56 -08:00
Drew Paroski e2af194cf2 Fix reserialize() to properly handle the 'V' and 'K' serialization types
We hit an APC-related bug where reserialize() was being called on a
serialized collection during HHVM startup (when reading APC prime values
from a file), and this caused HHVM to fall over.

This diff fixes reserialize() and adds some test cases and comments.

Reviewed By: @markw65

Differential Revision: D1050281
2013-11-11 09:50:21 -08:00
Jordan DeLong 5f2af563e0 Remove generic dtor helper stub
It appears this doesn't help us in HHIR.

Reviewed By: @ottoni

Differential Revision: D1047133
2013-11-11 09:48:28 -08:00
Jordan DeLong fcc5e960ba Remove object data vtable
This is feasable now, after all the steps taken toward it
earlier.

Some subclasses still use vtables, so now we now have to take care to
do correct casts between ObjectData* and c_Foo*'s.  (HNI should
eventually let us change the c_Foos so they don't derive from
ObjectData at all.)  This diff changes things so that we have a custom
instance delete function (this replaces the late-bound ~ObjectData), a
bit in the object attributes that indicates whether it's got a native
subclass, and some additional metadata in PreClass telling us the
offset of the ObjectData subobject.  A variety of extension
destructors were also moved to headers so they could be inlined in the
appropriate delete_Foo functions (their only caller).

Reviewed By: @jano

Differential Revision: D1046763
2013-11-11 09:48:24 -08:00
Jordan DeLong 8efed9f7c9 Move o_properties out of ObjectData to side table
Pessimize dynamic properties in favor of smaller objects.
This goes with removing the vtable for ObjectData.

Reviewed By: @swtaarrs

Differential Revision: D1046746
2013-11-11 09:48:20 -08:00
Bert Maher e9dd65bffa FPushCuf: Optimize the case where callable is an (obj, staticstr)
The pattern call_user_func(array($obj, "staticString"), ...)
is pretty common, and it's basically the same as FPushObjMethodD
except it warns instead of fataling when the method is not defined.
Catch this pattern and turn it into a similar IR sequence, and add a
template flag to methodCacheSlowPath to warn instead of fataling.

Reviewed By: @swtaarrs

Differential Revision: D1042143
2013-11-11 09:48:16 -08:00
bsimmers 4c192e8bcc Clean up types of Block::back and Block::front
They returned IRInstruction*, while dereferencing a Block::iterator
gives IRInstruction&. This diff changes it to be consistent with every other
container. I also changed it so you can't get an IRInstruction& from a const
Block*. Luckily no code appeared to be depending on that.

Reviewed By: @jdelong

Differential Revision: D1049640
2013-11-11 09:48:12 -08:00
mwilliams 2bbc51c8a1 Get rid of global register variable in function-entry-helpers
This rewrites some helpers to avoid using the global
rbx register. This is needed for lto support (or at least, we
would have to compile function-entry-helpers.cpp with lto
off). Its also needed if we want to compile with clang, and it
will help with the arm port.

This adds a few new arm failures, but also fixes some existing bugs.

Reviewed By: @jdelong

Differential Revision: D1045712
2013-11-11 09:48:08 -08:00
Alex Malyshev b7712156bf Move warning in gc_collect_cycles() under HHSyntax
Was causing tests to fail in Magento2

Reviewed By: @scannell

Differential Revision: D1048980
2013-11-09 06:46:02 -08:00
Alex Malyshev 37acf16916 Have ElemDObject treat ArrayObject like an array
Corrects the case when a SetM is performed on an ArrayObject
that holds an array with a ref count of 1.

Reviewed By: @ptarjan

Differential Revision: D1048713
2013-11-09 06:45:58 -08:00
Eugene Letuchy 714a255691 reflection: better tests for xhp reflection
... and expect file built from correct branch this time.

Reviewed By: @scannell

Differential Revision: D1049263
2013-11-09 06:45:54 -08:00
Joel Marcey 7c8a387130 Move back to a fgets model and clean up test analyzing a bit
Since we determined that fgetc didn't solve deadlocking, and we just blacklisted those tests instead, we go back to fgets.

Also, clean up the way we analyze tests and their statuses.

PEAR is flaky. I don't think it is any atomicity or overwrite problem with the script. I think it might be the fact that we are running these things with separate processes. Or the tests are flaky. Either way we need a serial mode.

Reviewed By: @ptarjan

Differential Revision: D1049044
2013-11-09 06:45:50 -08:00
Eugene Letuchy 75b7cfeb46 correct undoing xhp name mangling in type_annotation
... this code should be the inverse of
 ScannerToken::xhpLabel.

Reviewed By: @dariorussi

Differential Revision: D1039358
2013-11-09 06:45:46 -08:00
Julius Kopczewski 7d8796a4c3 Fixing OSX build.
This is an internal part of the fix that allows HHVM to compile
under OS X.

Reviewed By: @scannell

Differential Revision: D1048727
2013-11-09 06:45:37 -08:00
Stephen Chen d47e3bde5f More improvements to the test framework for job queue
- simulate random arrival of events.
- keep track of request queue time and wall time for each request.
- keep track of the max queue time and max load.
- added ability to add a padding to the time to simulate random delays.
- compute various statistics for queuing time and wall time.

Reviewed By: rkroll

Differential Revision: D1044762
2013-11-09 06:45:17 -08:00
Joel Marcey 846da77cb8 Modify calculation formula and a bit of clean up
Modifying the calculation formula to take into account blacklisted tests as failures.

Reviewed By: @ptarjan

Differential Revision: D1048288
2013-11-09 06:45:08 -08:00
seanc 773a4cd620 Fix fastcgi build break on OS X
Summary: Disable fastcgi compilation on OS X due to missing dependencies
for the moment.

Reviewed By: @julk
2013-11-08 17:12:20 -08:00
seanc a596e67ce0 Add libboost-thread to Travis dependencies
Summary: With the fastcgi implementation we now depend on
libboost-thread so add it to the list of Travis dependencies.
2013-11-08 09:36:52 -08:00
Sean Cannella c47ea09d91 Merge pull request #1244 from EloB/configure_ubuntu_auto_yes
Added auto yes to apt-get install in configure_ubuntu_12.04.sh
2013-11-08 08:41:49 -08:00
Drew Paroski 0641b1d9e3 Revert "Fix /stop command issued when hhvm can't bind port"
This reverts D944849

Reviewed By: @bertmaher

Differential Revision: D1047984
2013-11-08 04:54:32 -08:00
Julius Kopczewski 6b1aaf3e87 Fixing changes in $_SELF logic.
Reverted unintentional changes in $_SELF computation logic.

Reviewed By: @ptarjan

Differential Revision: D1047953
2013-11-08 04:54:31 -08:00
Joel Marcey af46513d6a Blacklist some test files causing deadlocking issues
A few test files from a few frameworks are causing deadlocking issues with the script. Blacklist them. Deal with them later.

Reviewed By: @ptarjan

Differential Revision: D1047939
2013-11-08 04:54:31 -08:00
Joel Marcey 83fb9cfadc Miscellaneous fixes: add newlines back, remove specific user path info, and help message update
Removing the final newlines from the expect files was premature and probably a mistake.

http://stackoverflow.com/questions/729692/why-should-files-end-with-a-newline

So, leave it to clients/upstream to deal with newlines at the end of the file.

Also, do not print user path info out in expect files (or other files). e.g., no joelm

Also, list frameworks in help message when specifying invalid ones

Reviewed By: @ptarjan

Differential Revision: D1045907
2013-11-08 04:54:31 -08:00
Alex Malyshev ea9704e611 Initial implementation of ReflectionClass::getDefaultProperties()
We weren't tracking the default values of properties in
ReflectionProperty. Unfortunately this diff only fixes the issue for
classes that don't use ClassInfo, so builtin classes will still break.
Fixing them will be a separate diff.

Also replace old for loops with range-for

Reviewed By: @ptarjan

Differential Revision: D1043255
2013-11-08 04:46:33 -08:00
Alex Malyshev 19761000c7 RecursiveIteratorIterator must be constructed with a Traversable
This is Zend's behavior, and zf2 reflection tests check this

Reviewed By: @ptarjan

Differential Revision: D1045288
2013-11-08 04:46:29 -08:00
Jordan DeLong aed54167d1 Fix: fb_rename_function of extract disabled the wrong direction
This disabled making new functions named 'extract', which
doesn't work because extract already exists.  We want to disable
allowing creating new functions that have the behavior of extract.

Reviewed By: danielm

Differential Revision: D1042932
2013-11-08 04:46:21 -08:00
Rachel Kroll 6340ab6f36 Unit tests for mem-file
Unit tests for mem-file.

Reviewed By: bmaurer

Differential Revision: D1040720
2013-11-08 04:46:12 -08:00
Edwin Smith ac36d7a49c Demallocify md5
This refactors the MD5 code a bit to avoid forcing the use of malloc.
Now, the raw MD5 api unconditionally gives back a 16-byte digest,
and we have wrappers to convert to std::string and String, respectively.

Reviewed By: @jdelong

Differential Revision: D1046220
2013-11-08 04:46:07 -08:00
Jan Oravec e2a30d9af4 Unit test: do not assume existence of Static*WaitHandle::create() functions
Use async functions to generate Static*WaitHandles. The explicit methods
to do so will be gone soon.

Reviewed By: @billf

Differential Revision: D1046534
2013-11-08 04:45:59 -08:00
Alex Malyshev 3e87af5430 Give ArrayObject's fields default values
Magento2 (and possibly other frameworks) end up making classes
that extend ArrayObject but never call its constructor. This works
under Zend so it should work under us as well.

Reviewed By: @scannell

Differential Revision: D1045913
2013-11-08 04:45:54 -08:00
Guilherme Ottoni 24fa57241c Inline small cold functions into hot ones
I noticed some missed opportunities for inlining were because the
callee was not marked as hot, but the caller was.  There's a check to
prevent inlining in such case, which kind of makes sense -- the call
may be in a cold path.  However, in some cases the callee is not
marked as hot probably just because it's too small.  And if the
function is small enough it's better to inline it anyway -- they code
may get smaller.  So I added a callee code-size threshold below which
inlining is always allowed.

I did some experiments with different values for the new threshold,
and also the previously existing HHIRInliningMaxCost, and set them to
what seems best these days.

Reviewed By: @jdelong

Differential Revision: D1044965
2013-11-07 05:11:42 -08:00
Eugene Letuchy 4b9cf93aca parity: make ZipArchive Not Implemented errors informative
... throwing ##"Not implemented is not implemented"## does
 not cover oneself in glory. Easy fix with a few emacs macros

Reviewed By: @ptarjan

Differential Revision: D1044243
2013-11-07 05:11:38 -08:00
Eugene Letuchy cd90ada2ce parity: move gc_enable warnings behind hip hop syntax
... and make gc_disable emit no warnings, since it's a 100%
 effective no-op.

Reviewed By: @ptarjan

Differential Revision: D1044225
2013-11-07 05:11:34 -08:00
Joel Marcey 4b4289d0f3 Sort the expect files alphabetically.
Let's sort the expect files alphabetically so any changes to them doesn't result in mega-diffs.... well, this will be the last mega diff to prime the expect files :)

Reviewed By: @ptarjan

Differential Revision: D1044747
2013-11-07 05:11:29 -08:00
bsimmers ef42b9fafb Add PushL for use in continuations
PushL pushes the value of a local on the stack and unsets it, avoiding
any refcounting operations. This is useful in Continuation::send and async
functions.

Reviewed By: @ottoni

Differential Revision: D1042054
2013-11-07 05:11:14 -08:00
bsimmers 1fa7056183 PHP integers are 64 bits
The fact that ArrayData::m_size is uint32_t complicated things a bit.

Reviewed By: @bertmaher

Differential Revision: D1043095
2013-11-07 05:11:09 -08:00
Stephen Chen 38190c61f3 unittest for doing a controlled simulation of job queue workload
A simple framework for doing a controlled simulation on job queue. Within this
set up, we can specify a duration for each request going through the system. The
request will have a fixed service duration of x ticks. We define our own
TickWorker that finishes the request after x ticks. We have a static global
logical clock we can then use to drive the simulation.

The next step is to generate a reasonable workload based on our real work
request latency distribution and run it through the system. After that, we can
simulate server side issues (ie. all reqeusts incur additional latency or small
percentage of request with very high latency).

The test case will help us select and fine tune the algorithm for doing queuing
and timeouts.

Reviewed By: rkroll

Differential Revision: D1043222
2013-11-07 05:11:04 -08:00
Sara Golemon 39ac07f4fb Remove generated file from repo 2013-11-06 14:40:22 -08:00
Paul Tarjan de8225a594 use a different config for frameworks
@elgenie had a good point that we don't want to turn on hiphop syntax for the frameworks.

Reviewed By: @elgenie

Differential Revision: D1044204
2013-11-06 11:08:55 -08:00
bsimmers 16ccd2e16d Move the rest of Type's methods into type.cpp
Reviewed By: @jdelong

Differential Revision: D1043399
2013-11-06 11:08:51 -08:00
Paul Tarjan a61dd82692 expose dynamic properties in reflection
ReflectionClass supports taking an object and should use the dynamic props from it. @alexmalyshev is going to send a diff about default, so we'll have to co-ordinate whoever lands first.

Reviewed By: @elgenie

Differential Revision: D1043099
2013-11-06 11:08:47 -08:00
Paul Tarjan d5679aa80a now isCallable won't die if there isn't a type_hint
Reviewed By: @dariorussi

Differential Revision: D1042437
2013-11-06 11:08:43 -08:00
Sean Cannella 7ecc6dfab6 HHProf: Support showing all allocations
Add a mode for HHProf where all allocations are shown. This
isn't helpful for leak tracking or looking at what memory is still
alive, but this allows visibility into allocation patterns that would
otherwise be hidden because they are balanced.

Reviewed By: @mikemag

Differential Revision: D1042696
2013-11-06 11:08:39 -08:00
Joel Marcey 48ceb22824 Use a different stream timeout approach
fgets was not working. stream_select seemed ok, but fgets seems to block anyway if only a certain amount of data is available without a newline. Use an fread(), character by character approach.

Reviewed By: @ptarjan

Differential Revision: D1043978
2013-11-06 09:29:20 -08:00
Paul Tarjan fb12616289 don't emit warning with empty haystack
zend doesn't emit a warning

Reviewed By: @alexmalyshev

Differential Revision: D1043427
2013-11-06 09:29:20 -08:00
Joel Marcey fa5b05e204 Fix "Nothing to do" errors coming from PHPUnit test suite
We were getting errors like: PHPUnit_Framework_Exception: HipHop Notice: Nothing to do. Either pass a .php file to run, or use -m server.

It had to do with running php in processes and passing php code via stdin. We need the php wrapper/symlink to hhvm instead of the explicit hhvm binary.

The fix was to fork phpunit, make a change to their getphpbinary() function to check for an environment variable that we then set in this script. Then we upstreamed that fix to the master phphunit branch and it was quickly accepted (that was nice!)

Also added @elgenie fork for Slim as well.

Reviewed By: @ptarjan

Differential Revision: D1043544
2013-11-06 09:29:19 -08:00
Paul Tarjan 5036732b47 cast instead of L
crossplatform

Reviewed By: @alexmalyshev

Differential Revision: D1043270
2013-11-06 09:29:19 -08:00
Surupa Biswas bbc5965894 Batched apc_store and apc_add support
Added support for passing arrays to apc_store/add instead of key,value pairs one at a time. Sharing an early
version to get code review feedback.

Reviewed By: @paroski

Differential Revision: D1037553
2013-11-06 09:29:19 -08:00
Bert Maher 405a9d6679 Remove StaticMethodCache::lookup, since lookupIR has supplanted it
It's dead, Jim.  Also rename lookupIR -> lookup, since
there's no distinction any more.

Reviewed By: @swtaarrs

Differential Revision: D1042980
2013-11-06 09:29:18 -08:00
Edwin Smith fe6b89cf5b Streamline string_replace()
I noticed this was hot in perf, so I did some standard streamlining:
- have the string functions use String(ReserveString) instead of malloc
- switch a std::vector to smart::vector
- inline the small String::replace() wrapper functions
- mark f_string_replace and string_replace() as HOT_FUNCTION

Reviewed By: @jdelong

Differential Revision: D1041907
2013-11-06 09:29:18 -08:00
Alex Malyshev 144ba6cce5 Implement PDO::sqliteCreateFunction
This function is already implemented as SQLite3::createFunction, however
PDO is expected to have it's own version of it as well. I leaked some of
the SQLite3 declarations over to PDO to get it to work.

Zend just duplicates all the functionality between PDO and SQLite3, for
instance 'php_sqlite3_func_callback' and 'php_sqlite3_callback_func' are
the same function just in different files...

Reviewed By: @ptarjan

Differential Revision: D1039095
2013-11-06 09:29:18 -08:00
bsimmers b59a8c407b Clean up codegen for InstanceOf
instanceOfHelper was just a thin wrapper around Class::classof. Do the
null check in the TC and call classof directly. I also get rid of a null check
in classof which trimmed down its assembly a bit.

Reviewed By: @jdelong

Differential Revision: D1042062
2013-11-06 09:29:18 -08:00
Sean Cannella d8cfc0420a Remove dead shared memory code
Removing dead shared (between processes) memory code and doc references

Reviewed By: @markw65

Differential Revision: D1042569
2013-11-06 09:29:17 -08:00
Joel Marcey c38100a138 Fix the timeout issues when running framework tests.
I was checking for false on stream_select; I needed to check for 0 instead.

Reviewed By: @ptarjan

Differential Revision: D1042557
2013-11-06 09:29:17 -08:00
aravind 549043294f Revert "Relax guard on input of SetM"
: This reverts commit 8bd12391c963659e70a46562776a9e6aeb842c7f.

Reviewed By: @ottoni
2013-11-06 09:29:17 -08:00
Drew Paroski c1967fa90a Wrap "test/slow/collection_classes/817.php" within a main() function
Eugene found some bugs with collections when he wrapped some of the our
collections tests inside a "main" method. These bugs have since been fixed,
so we can update collections tests that are not wrapped in "main" methods.

Reviewed By: @ptarjan

Differential Revision: D1041602
2013-11-06 09:29:16 -08:00
Julius Kopczewski e6b78bb278 Implement Fast CGI support
Split the monolithic functions preparing special variables such
as $_REQUEST or $_SERVER into multiple functions to enable feeding of
data from multiple sources. In case of FastCGI protocol, the values are
sent by the web server.

Import parts of proxygen and thrift.

Added #ifdef's to allow compilation with an unpatched version
of libevent library.

Reviewed By: @ptarjan

Differential Revision: D988737
Differential Revision: D1008756
Differential Revision: D1021808
Differential Revision: D1035231
2013-11-06 09:02:37 -08:00
Sara Golemon e4e0607370 Update folly submodule
Remove duplicate IOBufQueue from folly build
2013-11-05 17:40:27 -08:00
Sara Golemon 9680ccc24a Remove dead file 2013-11-05 17:40:27 -08:00
Sara Golemon 68cabf216a Remove RTLD_DEEPBIND from dlopen() call
It confuses TLS objects.

Closes #1174

Reviewed By: @scannell

Differential Revision: D1009729
2013-11-05 14:24:12 -08:00
Owen Yamauchi d65887fd2c Slightly relax FPushFunc's locals-destroying semantics
If the call has no arguments, it can't destroy locals, even if it's a
call to extract().

Reviewed By: @jdelong

Differential Revision: D1042425
2013-11-05 14:24:09 -08:00
Owen Yamauchi 39b3ab3075 Codegen for ConvArrToBool fast path
If it's not an NVTW, it's really quick to convert an array to a bool: is
m_size nonzero? The cold path is still a call to C++.

We can argue about codegen if you want. I could have the C++ helper
return a bool, get that into the dest register, and then jump over the
setcc, or do what I've done here.

Reviewed By: @edwinsmith

Differential Revision: D1040912
2013-11-05 14:23:56 -08:00
Cullen Walsh a6320cb4bc Allow generation of hack types in hhvm thrift extension
Look for a "format" key in the thrift spec array for collections (maps, vectors, sets). If the value is "collection", construct a Map/Vector/Set object rather than an array.

Reviewed By: @andrewcox

Differential Revision: D1025009
2013-11-05 14:23:41 -08:00
Paul Tarjan e5fbfabddd stop reporting negative numbers for memory
We were calling `newSlab` at statup and then `hphp_session_init` promptly calls `resetStats` setting it to 0. It looks like we should clear the stats when we clear the slab. That's a little scary for now, so I'm going to just make it non-zero.

Reviewed By: @jdelong

Differential Revision: D1041217
2013-11-05 14:23:37 -08:00
Jordan DeLong e4c2f9e280 Streamline method cache helpers
Make the fast path of the method cache slow path do a little
less work.

This was in part to see if the wouldCall logic could get simple enough
to make it a fast path unique stub in ahot.  This version of the code
was simple enough for me to translate to a unique stubs, which I tried
last night (the theory was that getting it on the first page of ahot
could help iTLB/icache), but it was in the noise.  I only did
methodCacheSlowPath(), so maybe it would only help if the whole thing
was pulled over, but I'm inclined to think that this suggests idea of
trying to move hot helpers to ahot stubs isn't very promising.

Reviewed By: @markw65

Differential Revision: D1039748
2013-11-05 14:23:33 -08:00
Jordan DeLong 0d9b67916c Remove null check from AtomicSmartPtr::operator->
I saw code doing null checks on the m_preClass in
target-cache.cpp's wouldCall(), but it turned out to be unreachable
code.

Reviewed By: @dariorussi

Differential Revision: D1039739
2013-11-05 14:23:28 -08:00
Mike Magruder 056301d824 Ensure ext_hotprofiler always closes main() with the data from when profiling was turned off
When we run out of log space while profiling, we close out the dangling stack with the last entry we have. This under-represents the functions left on the stack, which is fine, but also (sometimes greatly) under-represents main(), which is a pseudo-function intended to represent the entire profiling run. This change ensures that we always close out main() with data from when profiling was turned off, even if we run out of trace space.

Reviewed By: @swtaarrs

Differential Revision: D1040813
2013-11-05 14:23:20 -08:00
Edwin Smith 39d2a5f953 Streamline tvDupFlattenVars
Some callsites always pass nullptr, and some always pass non-null.
Also, we can make the whole thing smaller by rearranging the cases.

Reviewed By: @markw65

Differential Revision: D1041950
2013-11-05 14:23:08 -08:00
Alex Malyshev 012708bca5 Move sort comparators returning bools warning under HH syntax
Fixes a lot of errors in doctrine2.

Reviewed By: @ptarjan

Differential Revision: D1041273
2013-11-05 14:23:04 -08:00
Joel Marcey 9d0eaf9a15 Refactor SingleTest
SingleTest was a bit unwieldly. This hopefully refactors it a bit nicer. Also, found some output bugs that may have affected our runs.

Next is to sort the expect files so that we can change them without monster diffs

Reviewed By: @ptarjan

Differential Revision: D1041553
2013-11-05 14:22:56 -08:00
mwilliams d4d5106d3d Use sign bit for static ref count
Switches to using the sign bit to indicate that a refCount
is static, and rewrites the various decRef sequences to be:

  if (count == 1) release();
  else if (count > 1) --count;

Adds runtime options to allow experimentation with the exact strategy;
 - whether to load the count into a register (if one is available)
 - whether to use if (!--count) release(); if we don't need a static check
 - whether to skip using the register and just emit --count if we know
   its not static, and can't hit zero.

Also switcher various other static-bit checks to do byte tests on the
high byte, rather than word tests on the entier value.

Reviewed By: @edwinsmith

Differential Revision: D1012547
2013-11-05 14:22:48 -08:00
Paul Tarjan 715d7e0062 Make ReflectionParameter not completely wrong
@dariorussi what is this crazyness? Do you have a rewrite of this class? This is 100% insane.

Reviewed By: @dariorussi

Differential Revision: D1041883
2013-11-05 14:22:39 -08:00
Paul Tarjan 5d9c81fab1 fix ProxyArray::Escalate
this was a copy-paste bug that eagle-eye-@edwinsmith found

Reviewed By: @jdelong

Differential Revision: D1040832
2013-11-05 14:22:35 -08:00
Chad Horohoe b23bccfaeb Move functioning Zend test
Move functioning Zend test

Closes #1246

Reviewed By: @ptarjan

Differential Revision: D1041989

Pulled By: @scannell
2013-11-05 14:22:30 -08:00
Daniel Marinescu babd644466 Made fb_rename_function to not allow renaming to "extract".
fb_rename_function will not allow renaming to "extract".

Reviewed By: @jdelong

Differential Revision: D1041497
2013-11-05 14:22:26 -08:00
mwilliams eddaab5bcb Fix threading issues with fb_intercept
The first time we call a method, we add its flag to the
intercept table (so it can be enabled by future calls to intercept)
and then set the flag based on whether or not its intercepted in
the current thread.

That leaves a hole where thread a could call intercept,
thread b could call the function (setting the flag to zero,
because its not intercepted in thread b), and then thread a
would behave as if the function were not intercepted.

Fixed by using adding a flag to the global table to say whether
or not its ever been intercepted, and initializing the method's
flag from there.

Reviewed By: @jdelong

Differential Revision: D1039463
2013-11-05 14:22:18 -08:00
Sean Cannella c3c4ee838f Change CheckSymLink default to match Zend
CheckSymLink (following symlinks and making the realpath calls)
is the Zend behavior so we should default to this as well and allow
people to disable it for performance reasons instead of the inverse.

Depends on D1034342

Reviewed By: @ptarjan

Differential Revision: D1034354
2013-11-05 09:20:49 -08:00
Guilherme Ottoni b978890b9b Avoid DV initializer loop in prologues for small number of DVs
We were always generating a loop like:
     0xd800252: mov eax, 0x1
     0xd800257: sub rbx, 0x10
     0xd80025b: inc eax
     0xd80025d: mov byte ptr [rbx+0x8], 0x0
     0xd800261: cmp eax, 0x2
     0xd800264: jl 0xd800257
to set the DVs that didn't get a value passed in to Uninit.

This diff unrolls the loop for small number of values to be
initialized.

Reviewed By: @jdelong

Differential Revision: D1041394
2013-11-05 09:20:46 -08:00
aravind 71201e2933 Relax guard on input of SetM
Reviewed By: @ottoni

Differential Revision: D1041679
2013-11-05 09:20:42 -08:00
Sean Cannella 5d60ea9eaf Reduce default JIT structure sizes
Right now HHVM allocates about 1.2 GB of memory by default.
Reduce this by a factor of ~10 for a better experience with small
applications, VMs with limited memory, evaluation and testing purposes,
etc.

The configuration settings are available to change this to the previous
behavior is reproduced here for ease of access:

Eval {
  JitAHotSize = 4194304
  JitASize = 536870912
  JitAProfSize = 536870912
  JitAStubsSize = 536870912
  JitGlobalDataSize = 134217728
}

Reviewed By: @markw65

Differential Revision: D1034305
2013-11-05 09:20:37 -08:00
Cristian Hancila 0cd140154b Added async stack inspection and traversal to hphpd
Debugger commands 'up','down' and 'variable' now operate on the async
stack as well as the regular stack. If used in conjuction with 'where async'
the awaitable dependency stack is traversed instead of the regular stack
by the said commands.

Reviewed By: @mikemag

Differential Revision: D1034548
2013-11-05 09:20:33 -08:00
mwilliams 537a2ba1f4 Fix refCounting issues with various String functions
Some functions took a const String&, but assumed
that if the refCount was 1 they could destroy the parameter.

This is fine for calls from the vm, because it always refcounts
correctly, but can lead to surprising results for calls from c++
code.

It turns out that (for g++/x86 at least) the actual calling convention
for a function taking a String is identical to one taking a const String&
(ie its the caller's responsibility to pass a reference to a
temporary in the former case). So this diff just changes them
over to be String (which required a bit of hackery in the code to
generate the vm stubs). That fixes the issue for calls from c++, and
has no effect on calls from the vm.

Reviewed By: @jdelong

Differential Revision: D1040836
2013-11-05 09:20:29 -08:00
Paul Tarjan bce1718652 start supporting date.timezone INI setting
We need to initialize the timezone or else we get a warning in the logs. I could have added a -v option, but I want to start putting things in the INI files when they exactly correspond to a PHP ini setting.

I created a `php.ini` file just for the test runner and forced us to use it.

Reviewed By: @JoelMarcey

Differential Revision: D1040418
2013-11-05 09:20:25 -08:00
Niharika Marwah 8a7b741f2e Remove deprecated methods
Remove the deprecated methods hphp_thread_set_warmup_enabled/hphp_thread_is_warmup_enabled

Reviewed By: @ptarjan

Differential Revision: D1026245
2013-11-05 09:20:20 -08:00
Edwin Smith 6ccd766a74 Delete unused string_concat() and string_trim()
They are dead code.

Reviewed By: @bertmaher

Differential Revision: D1040044
2013-11-05 09:20:16 -08:00
Drew Paroski db77268a47 Small fix for ContSuspend* instructions
The ContSuspend* instructions were not marked as "terminal" (TF), and so
the bytecode emitter thought it was possible to these instructions to fall
through and there some unnecessary Null instructions being emitted for
"yield" expressions to satisfy asserts in the bytecode emitter.

This marks the ContSuspend* instructions as "terminal" and gets rid of the
unnecessary Null instructions that were being emitted.

Reviewed By: @jdelong

Differential Revision: D1039548
2013-11-05 09:20:12 -08:00
Dario Russi 37ba80ba8c Inline fast path for packed array get and isset
Teach the JIT to specialize the get and isset operations on packed arrays

Reviewed By: @bertmaher

Differential Revision: D1031551
2013-11-04 13:57:04 -08:00
Alex Malyshev 70a41e059e Don't fatal on null properties when using magic methods
Matches Zend's behavior of emitting a fatal error on properties that
start with \0 only if the object does not have the appropriate magic
method defined.

Reviewed By: @ptarjan

Differential Revision: D1032024
2013-11-04 13:56:56 -08:00
Drew Paroski 7119bff22c Fix Traversable
HHVM's instanceof operator was returning true when checking if an array was
an instance of the Traversable interface, and this was breaking some PHP
code out in the wild. This diff fixes HHVM so that the instanceof operator
returns false in such cases.

There are some existing hh files that require that "array() instanceof
Traversable" return true. To solve this, we introduce a new interface
named "HH\Traversable" and we change "instanceof" to return true when
checking if an array is an instance of \HH\Traversable, and we update the
parser so that it implicitly imports \HH\Traversable for hh files when we
are in the global namespace and there are no conflictly "use" statements.
To keep the interface hierachy coherent, the Iterator interface required
similar treatment.

Reviewed By: @ptarjan

Differential Revision: D1037748
2013-11-04 13:56:52 -08:00
Jordan DeLong 7dfea4e50d Change stubsCode to mainCode in ARM::emitFuncPrologueRedispatch
This is in mainCode in X64---figured I'd change it in case it
is easy to miss when we actually implement the stub.

Reviewed By: @scannell

Differential Revision: D1039633
2013-11-04 13:56:48 -08:00
Jordan DeLong 17380509be Better dispatch for rhs of array_merge and +
Specialize on array kinds.

Reviewed By: @markw65

Differential Revision: D1034616
2013-11-04 13:56:44 -08:00
Edwin Smith a4c7a7a0d0 Delete unused option ThreadingJit
It was dead

Reviewed By: @markw65

Differential Revision: D1039955
2013-11-04 13:56:39 -08:00
Owen Yamauchi 22fb60143f Fix a bug in my previous fix of SetL/BindL logic
Silly me, I thought that box() does sort of the opposite of unbox(). To
wit, I thought it would box Cells and pass through already-boxed stuff.
Turns out it assert-fails on already-boxed stuff.

Reviewed By: @swtaarrs

Differential Revision: D1038748
2013-11-04 13:56:35 -08:00
Kristaps Kaupe 52b7fa1c95 Add TypedResults for MySQL extension
Introduced MySQL TypedResults runtime parameter, which allows
switching from HHVM behavior of returning also ints and doubles from
MySQL results to Zend behavior of returning only strings and nulls.

Closes #1237
Closes #1238

Reviewed By: @ptarjan

Differential Revision: D1038046

Pulled By: @scannell
2013-11-04 13:56:31 -08:00
bsimmers 43ab3169d3 Use type aliases instead of inheritance in smart-containers.h
Because it's the right thing to do. We overrode the default
constructor for hash_map so I left that alone for now.

Reviewed By: @jdelong

Differential Revision: D1035287
2013-11-04 13:56:26 -08:00
Paul Tarjan 0f69678368 make preg_replace work with /e
Remove a lot of the HPHPc hacks and do real eval. I could have re-used the escaping but the code was a bit cleaner like this

Reviewed By: @markw65

Differential Revision: D1015443
2013-11-04 13:56:22 -08:00
aravind 2830cca4ed Refcount validator fix
Check countness of current SSATmp, not the original SSATmp for
refcount validation. Passthrough instructions like CheckType<Int>
can cause the countness to change.

Reviewed By: @ottoni

Differential Revision: D1038437
2013-11-04 13:56:14 -08:00
mwilliams 68bb74d226 Clean up object/resource destruction
More changes to avoid mulitiple copies of destruct
sequences, to make it easier to modify the incRef/decRef
code.

No intentional changes to behavior/performance

Reviewed By: @jdelong

Differential Revision: D1038763
2013-11-04 13:56:10 -08:00
Joel Marcey 29a7593652 Fix (Hopefully) the timeout/deadlock issue...
Some tests would deadlock, even with the specified timeout. So I added some more stream_select statements before appropriate fgets calls.

Reviewed By: @ptarjan

Differential Revision: D1039419
2013-11-04 13:56:05 -08:00
Jordan DeLong 1c07c73744 Avoid VerifyParamType on specialized object types, when possible
This can kick in if you inline a function, passing an
argument that came directly from AllocObj, but isn't measurable on the
site.

Reviewed By: @bertmaher

Differential Revision: D1038352
2013-11-04 13:56:01 -08:00
Jordan DeLong 123598b569 Fix a bug when lookupClsMethodHelper needs to fatal
It forgot to propagate the exception.

Reviewed By: @bertmaher

Differential Revision: D1039332
2013-11-04 13:55:57 -08:00
Joel Marcey fd17888ae8 Framework Script Refactoring #1
No change in functionality. Just some refactoring. Putting methods in classes. Common forking and bucketing method. Etc.

Next up:

Timeout bug
Alphebetize expect file
More refactoring

Reviewed By: @ptarjan

Differential Revision: D1039348
2013-11-04 13:55:52 -08:00
Edwin Smith 98d233f262 Support (gpr,gpr)=>xmm movs in shuffle2
If you turn off Precoloring without turning off XMM support,
stuff breaks due to not copying Cell values coming back from
calls, from (eax,edx) to whatever full xmm register was assigned.

Reviewed By: @ottoni

Differential Revision: D1037919
2013-11-04 13:55:48 -08:00
Eugene Letuchy 5c12c61de4 collections: teach implode() about collections
very straight-forward, since ##isContainer##,
 ##getContainerSize##, and ##ArrayIter## are already collection
 friendly.

Reviewed By: @paroski

Differential Revision: D1031865
2013-11-04 13:55:44 -08:00
Dario Russi 467da2a3df Reflection Zend compatibility fix for Relfection::getStaticProperties
getStaticProperties returns an array with propName => value and not a propName => propInfo

Reviewed By: @ptarjan

Differential Revision: D1033668
2013-11-04 13:55:39 -08:00
Guilherme Ottoni 1cfb1afa2f Dump IR after ref-count optimization when validation fails
Just that.

Reviewed By: aravind

Differential Revision: D1038415
2013-11-04 13:55:35 -08:00
Paul Tarjan cb52292f91 do normalizeNS in GetNamedEntity
Lets see if we can put this up to `GetNamedEntity`. It is a LOT cleaner this way and fixes the bug in the attached class.

I still need the helper as constants don't have `NamedEntities`.

Reviewed By: @markw65

Differential Revision: D1032816
2013-11-04 13:55:30 -08:00
Jordan DeLong 155b55fa10 Don't punt on Clone; call ObjectData::clone from TC
Reviewed By: @swtaarrs

Differential Revision: D1038227
2013-11-04 13:55:26 -08:00
Jordan DeLong a5e94b6ef5 Don't interp one {Class,Interface,Trait}Exists as much
Reviewed By: @swtaarrs

Differential Revision: D1038082
2013-11-04 13:55:21 -08:00
Jordan DeLong 3aa64638d9 Revert "Drop "de-const" cast hack from API migration"
This reverts commit 2678af0f83d35530c4285295419ea5ebcb79113d.

Reviewed By: @bertmaher

Differential Revision: D1038880
2013-11-04 13:55:12 -08:00
Olle Bröms 7e13f9c899 Added auto yes to apt-get install in configure_ubuntu_12.04.sh 2013-11-04 00:45:39 +01:00
mwilliams f1a5b3f2b0 Destructor cleanup
Reduce to a single implementation of the generic
dec-ref-and-destroy code.

RefData can never be static, so stop checking it

Reviewed By: @swtaarrs

Differential Revision: D1037810
2013-11-01 14:54:48 -07:00
Bert Maher 9138f0b6de Implement SetOpL for array arguments
A few hot call sites use this.

Reviewed By: @ottoni

Differential Revision: D1037492
2013-11-01 14:54:44 -07:00
Joel Marcey 7b5a122c6d Sort frameworks for test bucket breakup
Sort the frameworks vector so that we can have a general alphabetical order of test
running after we bucket them in threads.

Fix a couple of bugs (undefined variable and possible div by zero) too.

Reviewed By: @ptarjan

Differential Revision: D1038251
2013-11-01 14:54:40 -07:00
Jordan DeLong 29ed627bef Make AllocObj{,Fast} return a specialized object type
Reviewed By: @dariorussi

Differential Revision: D1032573
2013-11-01 14:54:32 -07:00
Mike Magruder 21b8e31e3b Release old arrays when we grow them while setting/unsetting elements
D988759 changed the way we reallocate arrays, and broke a previous optimization in SetNewElemArray and UnsetElemArray, causing memory leaks in a wide variety of cases. We got a very nice repro from the Firehose team. This fixes the test case in the referenced task, which can complete now with minimal memory use. I suspect this also explains a number of other OOM bugs which have been cropping up since the 10/25 release, and perhaps the extra swapping in v3 we've experienced since then.

Reviewed By: @jdelong

Differential Revision: D1038091
2013-11-01 14:54:28 -07:00
Edwin Smith a2c5dfa486 Add PhysLoc::numWords and rename SSATmp::numNeededRegs->numWords
This is just code cleanup; sometimes we care about the # of logical
words for a tmp or PhysLoc, (eg 2 for a TypedValue) and sometimes
we care about the physical locations assigned (eg 1 for FullXMM,
0 for a constant).  This separates the two a bit more clearly.

Reviewed By: @bertmaher

Differential Revision: D1037818
2013-11-01 14:54:24 -07:00
Jordan DeLong c122ac9394 Remove unused bool m_no_volatile_check
Always false.

Reviewed By: @markw65

Differential Revision: D1036977
2013-11-01 14:54:19 -07:00
Paul Tarjan bacc8cbfe4 actually remove temporary php_ini
I thought this was taken care of me for free. Nope.

Reviewed By: @alexmalyshev

Differential Revision: D1038214
2013-11-01 14:54:15 -07:00
aravind be95320b33 Don't decref Objects while sweeping
Per title

Reviewed By: @jano

Differential Revision: D1037445
2013-11-01 14:54:11 -07:00
Rachel Kroll cc400ca76a Drop "de-const" cast hack from API migration
Preserve const in mem-file
Track malloced pointer separately in mem-file

Reviewed By: bmaurer

Differential Revision: D1037894
2013-11-01 14:54:07 -07:00
mwilliams 21baad1c0f Fix user profiler for native funcs
Various places test func->info to determine whether a Func is a c++
builtin or not. Some of them need to include Native Funcs.

Rename Func::info to Func::methInfo to find all the uses, and spot
check them.

Reviewed By: @jdelong

Differential Revision: D1035915
2013-11-01 10:11:26 -07:00
Joel Marcey f714b0c3fa Fix forking problem when running individual tests
The script now preloads all of the tests for all of the specified frameworks (every test is retrieved with --all). Then we fork of threads, bucketing as necessary to keep things sane. This is instead of forking of a thread per framework and then more threads for the tests of each framework where we could get up to 1000+ instances of HHVM going (and that is bad).

Also fixed a bug on how we retrieve the actual tests.

Did a little more refactoring too.

Singled out two tests from zf2 that was causing some weird deadlocking. Don't run those. Figure out why and then take them out.

Reviewed By: @ptarjan

Differential Revision: D1037105
2013-11-01 09:16:20 -07:00
aravind 797de2403a Fix for readMetaData
In legacy mode, readMetaData should not modify the input
rtts, since these are shared with the tracelet's guards.

Reviewed By: @ottoni

Differential Revision: D1036751
2013-11-01 09:16:12 -07:00
Owen Yamauchi efc2a76205 Two little ARM fixes
- There were register "allocation" bugs in the closure code. First, the
  incref code was clobbering the address of the datum to incref with the
  refcount. Second, the closure prologue code was using rAsm2 to hold
  the closure's address, and that got clobbered by the fixed incref
  code. >_<

- The type calculus of SetL's effects on locals wasn't right. If the
  local is boxed before SetL, it'll be boxed after, regardless of what's
  on the RHS.

Reviewed By: @jdelong

Differential Revision: D1036579
2013-11-01 09:16:08 -07:00
Eugene Letuchy 905e758514 parity: update Slim framework to latest release
Minor version 2.3.5 vs 2.3.1; with a pull of the commit
 listed in run.php, it will have no errors.

Reviewed By: @ptarjan

Differential Revision: D1036922
2013-11-01 09:16:04 -07:00
Joel Marcey 7b948ad8ea Run each test from each framework individually.
This diff begins to allow indivdual tests per framework to be run in separate processes. Now we won't stop on fatals and we should be able to get a nice percentage number for all frameworks.

There is a "too many threads" spawned issue right now that needs fixing (deadlocking occurs as I create too many at this point). But let's start the review process.

Also did a fairly sizeable refactoring too.

Reviewed By: @ptarjan

Differential Revision: D1035690
2013-11-01 09:15:59 -07:00
mwilliams ace23b01ce depthOne already checks that the depth is one
thats it

Reviewed By: @edwinsmith

Differential Revision: D1035861
2013-11-01 09:15:48 -07:00
Bert Maher 8575f79d64 Translate FPushClsMethod
This adds new IR opcodes to lookup class methods from the TC
instead of interpreting.  LookupClsMethod basically does the same
thing as the interpreter; LookupClsMethodStatic is optimized for the
case where the call is in a static function.

Additionally, when the class input comes from a LdCtx we can get the
method slot at jit time and burn that into the TC.  This case is
pretty common since "LateBoundCls; FPushClsMethod" is a common
pattern.

Reviewed By: @jdelong

Differential Revision: D1035577
2013-11-01 09:15:40 -07:00
Abel Nieto a94364d310 Patch unserialize so that it handles namespaced collections
We want to be able to unserialize both Vector and HH\Vector.

Patch unserialize to that effect.

Reviewed By: @elgenie

Differential Revision: D1031058
2013-11-01 09:15:11 -07:00
David Soria Parra 497676b54f Let the HHVM debugger client/server listen on IPv6
We manually initialize the IPV6 sockaddr_in6 structure
as gethostbyname_r has problems with numeric IPv6 adresses
(http://sourceware.org/bugzilla/show_bug.cgi?id=5479). In the particular
case it fails with permission denied, while it works with the equivalent
ipv4 address.

Reviewed By: @mikemag

Differential Revision: D1030284
2013-11-01 09:15:06 -07:00
Jordan DeLong 77daeaa7c1 Remove two unused hashtables from ExecutionContext
Reviewed By: @dariorussi

Differential Revision: D1035098
2013-11-01 09:15:02 -07:00
Jordan DeLong 9944d09edc Make collection mask bits a little clearer
Easier to see how many bits are left in o_attributes.

Reviewed By: @edwinsmith

Differential Revision: D1035048
2013-11-01 09:14:57 -07:00
Javier Eguiluz 89aa1e64b5 Fix doc typos
Fix doc typos

Closes #1231

Reviewed By: @JoelMarcey

Differential Revision: D1035977

Pulled By: @scannell
2013-11-01 09:14:48 -07:00
Owen Yamauchi 43dabf533d Fix bug: "unbox()", not "innerType()"
I failed to appreciate the difference between the two (unbox works on
types that aren't necessarily boxed) in my last diff.

Reviewed By: @edwinsmith

Differential Revision: D1035871
2013-11-01 09:14:44 -07:00
Sean Cannella 4d80a542d1 Fix build break on aarch64
On aarch64, don't break the default build.

Reviewed By: @oyamauchi

Differential Revision: D1034887
2013-11-01 09:14:39 -07:00
Jordan DeLong 76ea945b56 Translate FPushCuf in more contexts; add fast paths
Adds fast paths in native helper functions for some common
cases for FPushCuf; bails to the full vm_decode_function logic if
things are less than simple.

I also tried a fast path for strings with class names ("Foo::bar"),
which made those calls about 2x faster in micro-benchmarks, at the
expense of making "self::foo" about 3x slower.  It was in the noise on
perflab, and also required differences in autoload order, so I'm
leaving that one out for now.

Reviewed By: @bertmaher

Differential Revision: D1032035
2013-11-01 09:14:34 -07:00
naresh 101c45fa9a Support systems without BFD_DECOMPRESS flag
Support systems without BFD_DECOMPRESS flag

Closes #1102
Closes #1225

Reviewed By: @markw65

Differential Revision: D1034235

Pulled By: @scannell
2013-11-01 09:14:10 -07:00
James Bornholt 38619fc4bf Fix handling of non-int/array flags to filter_var
HHVM treats all non-int flags as arrays, but Zend treats all
non-array flags as ints, so HHVM handles e.g. string flags
incorrectly. Reverse the logic to match Zend.

Closes #1226

Reviewed By: @alexmalyshev

Differential Revision: D1034218

Pulled By: @scannell
2013-11-01 09:14:01 -07:00
Rachel Kroll 65c7f03d4b Remove old cache code from hphp
Remove the old code (with a few lingering stubs to be cleaned up in a future change)

continuous build seems to be expecting bad strings in unrelated code

Reviewed By: bmaurer

Differential Revision: D1030191
2013-11-01 09:13:50 -07:00
aravind 6ce6334141 Add refcount validation pass
This adds a refcount validation pass. The pass creates an
approximation of a map from SSATmps to refcount-deltas for
each exit block. The validation consists of verifying that the
deltas are same before and after refcount optimizations.
This is run only in debug mode or under the runtime
flag Eval.HHIRValidateRefcount.

Reviewed By: @ottoni

Differential Revision: D1022219
2013-11-01 09:13:45 -07:00
Owen Yamauchi b638f9c0bd Be less aggressive in dropping types on OverrideLoc
The assert in the minstr translator was failing in
test/quick/poly-torture.php. The setup is: there's a CGetM whose base is
boxed, and before the CGetM there's an InterpOne that causes us to drop
all knowledge of refs' inner types in the frame. (This happens in x64
mode too if I force IncDecL to be interped.)

We can actually drop the inner types to InitCell instead of just Cell --
you can't have a reference to uninit. Then we can slightly weaken the
assert in the minstr translator, and it will pass. Weakening the assert
is justifiable; the codegen for LdRef knows that it shouldn't bother
emitting a typecheck if the box's inner type is InitCell.

Reviewed By: @swtaarrs

Differential Revision: D1033158
2013-11-01 09:13:40 -07:00
mwilliams c81f911e0a Refactor some more countable code
This is intended to be code cleanup, with no real change in
functionality, but should make the sign-bit-as-static-indicator
diff much smaller, and easier to reason about.

Reviewed By: @andralex

Differential Revision: D1030409
2013-11-01 09:13:30 -07:00
Edwin Smith b57f4c969d Extended Linear Scan Register Allocator
Based on Christian Wimmer's 2010 paper.

Reviewed By: @jdelong

Differential Revision: D997084
2013-11-01 09:13:16 -07:00
Edwin Smith 062178e270 Fix Shuffle bugs with unused dests and constants copied to DefLabel
Shuffle didn't handle two corner cases correctly:
1. unused destinations.  These could/should be eliminated upstream
but there's nothing incorrect about them, we can just ignore those
copies.
2. a DefConst feeding into a DefLabel needing 2 registers; We already
handled DefConst, but not when the destination doesn't have a known
type.  e.g. merge(1,"foobar") => {Int|StaticStr}, which needs 2
registers.

Reviewed By: @dariorussi

Differential Revision: D1032504
2013-11-01 09:13:11 -07:00
aravind 1b9dd05bc9 Don't increment result of StLoc unless it is pushed
StLoc was producing an incref on its result even if the result
was not pushed on stack (consumed).

Reviewed By: @ottoni

Differential Revision: D1032861
2013-11-01 09:13:05 -07:00
Guilherme Ottoni 2cf4ab129e Cleanup selectTraceletLegacy
It was taking a full RegionContext when it only needs the spOffset.

Reviewed By: aravind

Differential Revision: D1032271
2013-11-01 09:13:00 -07:00
Sara Golemon 6fca9198e5 Use gcc-4.8 on travis for faster builds 2013-10-30 13:11:46 -07:00
Owen Yamauchi d5db0d8b98 Fix some bugs with fb_setprofile in ARM mode
- Have separate stubs for the three return helpers. They don't need to
  be implemented yet, but they all need to have distinct addresses
  because we compare against retInlHelper directly to determine whether
  to run function-exit hooks.

- This exposed a bug in cgGuardRefs, where the "is logical immediate"
  assert was firing. This time I actually invested real time into
  understanding what the hell's going on there and rewrote the thing
  properly. (There are still some improvements to be had: most notably,
  when the mask is a single bit, we can use Tst instead of And-Cmp.)

- Fixups done on faked-up ARs in the simulator's catch block were
  succeeding, but not ones done from VMRegAnchors. The underlying cause
  is that the VM stack is not participating in the native frame pointer
  chain, because we're not using native call instructions to get into or
  out of the TC. I added logic to FixupMap that looks at the stack of
  simulators stored in ExecutionContext, and reads their registers to
  look for the place to apply the fixup.

Reviewed By: @edwinsmith

Differential Revision: D1032483
2013-10-29 17:05:58 -07:00
Owen Yamauchi a2704716f4 Add sync points in ARM code; sync registers on exceptions from simulated code
Fixups for simulated calls to C++ were basically not working at all.
This fixes a couple of test failures. There are still some failures left
that are failing with a null AR* in fixupWork, which I'm researching
separately.

To add the pseudo-unwind personality to the simulator, I made a
mechanism to provide an "exception hook". Eventually we'll probably want
it to return a flag indicating whether or not to re-throw, but that's
not necessary yet. I made it a hook instead of implementing the logic
right in the catch block to avoid having vixl depend on libruntime.

Reviewed By: @edwinsmith

Differential Revision: D1031833
2013-10-29 17:05:47 -07:00
Daniel Sloof 729ab7d033 headers_list should return array() with no headers
headers_list should return an empty array when there are no
 headers. There were already tests involving this in ext_network.php, but it's
 being skipped (at least in the github repository).

Closes #1218

Reviewed By: @alexmalyshev

Differential Revision: D1030259

Pulled By: @scannell
2013-10-29 17:05:38 -07:00
Michal Gregorczyk 602f634292 Record time spent in usleep function.
Added 4 counters to Transport to track how long thread sleeps in various sleep functions
when serving a request. I exported the request through hphp_get_timers.

Reviewed By: @mikemag

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

Reviewed By: @markw65

Differential Revision: D1010456
2013-10-29 15:17:44 -07:00
Abel Nieto 9306c9df11 Add stuff missing from the FrozenVector API
Vector had a bunch of methods that were not available in FrozenVector.
Add the ones that make sense given that FV is immutable (e.g. we can't sort it).

Reviewed By: @paroski

Differential Revision: D1014907
2013-10-29 15:17:44 -07:00
Alex Malyshev 9cc9ce7a52 Implement glob:// stream
Adds GlobStreamWrapper, a subclass of Stream::Wrapper.

Reviewed By: @ptarjan

Differential Revision: D1028484
2013-10-29 15:17:44 -07:00
Joel Marcey 6a7071c1c2 Stub out ZipArchive using HNI
ThinkUp fataled on the lack of a ZipArchive class. Well, here it is. Stubbed out.

Reviewed By: @ptarjan

Differential Revision: D1025542
2013-10-29 15:17:43 -07:00
Paul Tarjan bf57855cc8 try to fix yii again
It turns out the path is unique to my machine. Try glob.

Reviewed By: @JoelMarcey

Differential Revision: D1031707
2013-10-29 15:17:43 -07:00
Paul Tarjan c06684768f don't call autoload handler with an empty class
Zend doesn't do it and we shouldn't either. It was causing an assert in a debug build.

Reviewed By: @markw65

Differential Revision: D1030881
2013-10-29 15:17:43 -07:00
mwilliams 482852ef22 Fix fallback when optimized translation fails
analyze needs to read live state, which is only
valid if this is the first tracelet in the region. For
subsequent tracelets, fall back to the interpreter.

Reviewed By: @ottoni

Differential Revision: D1028657
2013-10-29 15:17:43 -07:00
Owen Yamauchi d87087977d Implement ARM closure prologues
I left this unimplemented in my initial prologues diff, just out of
laziness. Time to actually get it done.

This diff contains anecdotal validation for my decision to fork code-gen
instead of trying to put the ARM assembler behind the X64Assembler
interface. Note the AttrStatic part in the closure prologue
implementation -- the x64 version uses a weird quirk of the shrq
instruction that puts the former LSB in the carry flag. Trying to
emulate that in terms of ARM instructions seems pretty foolish.

Reviewed By: @markw65

Differential Revision: D1025972
2013-10-29 15:17:42 -07:00
Eugene Letuchy c0443bc8eb tools: some pretty printing changes in gdb helper
* __doc__ for the module
 * Make RECOGNIZE regex part of the process of defining a pretty-printer
 * remove ##lambda x: bar(x)##

Reviewed By: @ptarjan

Differential Revision: D975674
2013-10-29 15:17:42 -07:00
Paul Tarjan ae4982f60b Introduce ProxyArray
Mutation operations can reseat the original array. In zend land, this isn't the case so we need a wrapper for the original array which will change its internal pointer during any reseating operation.

I verified that every method was implemented in this by removing the inheritance and making sure there were no unknown methods in the big table.

Reviewed By: @jdelong

Differential Revision: D1009352
2013-10-29 15:17:42 -07:00
Paul Tarjan acc91affa7 fix varargs for mongo
`sysdoc.php` didn't handle the varargs annotation

Reviewed By: @aryx

Differential Revision: D1030692
2013-10-29 15:17:41 -07:00
Eugene Letuchy 56ba16934f parity: correctly prevent 'self' and 'parent' user classes
Verily, case sensitive and insensitive comparisons are not
 the same. Zend knows this too: http://codepad.viper-7.com/YmAmQk

Reviewed By: @jdelong

Differential Revision: D1031067
2013-10-29 15:17:41 -07:00
aravind 40d4c00e6e Allow multiple exit blocks for Jump optimization
The main trace can have multiple exit blocks. Allow jump
optimization to work with such traces.

Reviewed By: @jdelong

Differential Revision: D1031384
2013-10-29 15:17:41 -07:00
Jordan DeLong 8d889ea18a Initial HHBBC commit (prototype of bytecode optimizer)
Reviewed By: @swtaarrs

Differential Revision: D1025662
2013-10-29 15:17:36 -07:00
Jordan DeLong 74e6f0a1a2 Pass HardTypeHints=0 for slow/invalid_argument/1383.php in RepoAuthoritative
This is another test that recovers from VerifyParamType,
which we don't handle correctly in RepoAuthoritative mode (by design).
Modify it so it will SEGV without the correct flags, and then pass
them.

Reviewed By: @markw65

Differential Revision: D1019278
2013-10-29 12:02:39 -07:00
Jordan DeLong bb8eb52d68 Add a NopDefCls opcode, for use with always hoistable classes
Every PreClass structure contains an Offset pointing usually
into the psuedo-main, to the DefCls for that PreClass.  For closures
it points to the opcode after the CreateCl (perhaps unintentionally?).
If a merge-only unit fails to define a class, it "fakes" like it was
running the psuedo-main, and sets PC to this offset before raising the
error.  Right now, a Nop is placed in the bytecode for this.  This
changes things to have a new instruction for this case, so that static
analysis of the bytecode can see why the Nop was there.

Reviewed By: @edwinsmith

Differential Revision: D1029696
2013-10-29 12:02:35 -07:00
Jordan DeLong f9a715189d Add support for more assert types opcodes; fix assert stack offsets
Option types, static string and static array, and specific
class types.  And AssertTStk was not correctly computing the Location.

Reviewed By: @swtaarrs

Differential Revision: D1029072
2013-10-29 12:02:31 -07:00
Jordan DeLong 4484f29d9f Another bytecode spec tweak for WFooIter instructions
I messed up how they treat %4 in the last update.

Reviewed By: @dariorussi

Differential Revision: D1029665
2013-10-29 12:02:27 -07:00
Jordan DeLong 048c37f4a5 Add a BreakTrackHint hhbc instruction
HHBBC sometimes infers that functions return Bottom
(i.e. infinite loop or always throw).  In this case, after the FCall,
I want to insert a String "static analysis error"; Fatal sequence, but
that sequence ends up included in the Tracelet that does the FCall.
One way to break it is to have the analyze pass / region selectors
recognize this pattern, but it seems that this might come up in other
contexts where ahead-of-time analysis may have good reasons to suggest
tracelet breaks (e.g. to avoid our "double tail" problem on control
flow diamonds, or maybe StaticLoc?).

Reviewed By: @swtaarrs

Differential Revision: D1029595
2013-10-29 12:02:23 -07:00
Jordan DeLong af481f5e9b Add a PopA instruction
This aids in implementing strength reduction if you can
constant propagate to instructions taking a classref when there is a
*D form.  (E.g. AGetL; ClsCns converting to ClsCnsD, FPushClsMethod ->
FPushClsMethodD, etc.)

Reviewed By: @bertmaher

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

Reviewed By: @swtaarrs

Differential Revision: D1029398
2013-10-29 12:02:14 -07:00
Jordan DeLong 46aac2e534 Some tweaks to continuation opcodes in bytecode.specification
We put the top of stacks toward the right in the spec.  Also,
make it a little clearer that CreateCont and CreateAsync unset locals
on the current frame.

Reviewed By: @edwinsmith

Differential Revision: D1029381
2013-10-29 12:02:10 -07:00
Jordan DeLong e3727fe306 Fix bytecode spec for DecodeCufIter
It claims it pushes a bool, but it doesn't.

Reviewed By: @edwinsmith

Differential Revision: D1029315
2013-10-29 12:02:06 -07:00
Jordan DeLong 6afcba1044 Various runtime changes related to hhbbc
Mostly exposing some fields on the FooEmitters, consts, and
other small things like that.  This is split off in an attempt to make
the code review a little easier.

Reviewed By: @markw65

Differential Revision: D1025651
2013-10-29 12:02:02 -07:00
Jordan DeLong a43878fbc5 Encode NewArray capacity hints in the bytecode, with a NewArrayReserve op
This makes it easy to keep it around during the
bytecode-to-bytecode thing.

Reviewed By: @edwinsmith

Differential Revision: D1025556
2013-10-29 12:01:58 -07:00
Jordan DeLong a9b11650cb Relax invariant about empty eval stack at starts of try blocks
I don't think anything in the system actually requires this,
so we might as well not have the rule.

Reviewed By: @edwinsmith

Differential Revision: D1025601
2013-10-29 12:01:54 -07:00
Jordan DeLong 33e71c9c57 Remove MetaInfo::Kind::NopOut
Unused after D1025494

Reviewed By: @edwinsmith

Differential Revision: D1025500
2013-10-29 12:01:50 -07:00
Jordan DeLong 5f875aac6c Add various stack-flavor-only Nop opcodes; use them instead of MetaInfo
These instructions do nothing.  They match up for the cases
that we currently use metadata to nop things out, except FPassC
(because FPassC is already always a no op).  I'll remove
MetaInfo::NopOut in a separate diff on top of this to perflab it
separately.

Reviewed By: @edwinsmith

Differential Revision: D1025494
2013-10-29 12:01:45 -07:00
Alok Menghrajani f82d212f0c Remove blacklisted Xhp type
We no longer need this special case.

Reviewed By: @jdelong

Differential Revision: D1029228
2013-10-29 12:01:41 -07:00
James Bornholt cdfd08ee38 Zend parity with file() for blank files
file() shouldn't return null for a blank file. Do what Zend
 does, return an empty array.

CLoses #1216

Reviewed By: @JoelMarcey

Differential Revision: D1030231

Pulled By: @scannell
2013-10-29 12:01:37 -07:00
Sean Cannella aa92991929 Fix linking issue on OS X 10.9 with libc++
ld on OS X 10.9 doesn't seem to be able to locate the ctype.h
functions (ex. isdigit) when they are used as function pointers, so wrap
them in lambdas.

Reviewed By: @markw65

Differential Revision: D1030137
2013-10-29 12:01:33 -07:00
Bert Maher 13d98bda87 Disable SQLite memory stats to avoid locking during shutdown
Since bmaurer noticed that we spend a lot of time locking on
memory stats during webserver shutdown, and we don't do anything with
these stats anyways, let's just turn them off.

Reviewed By: bmaurer

Differential Revision: D1030301
2013-10-29 12:01:29 -07:00
Eugene Letuchy c823ab96c4 parse error for 'abstract async' ...
... because it's a meaningless syntax

Reviewed By: @paroski

Differential Revision: D1016954
2013-10-29 12:01:20 -07:00
Paul Tarjan e35c83763d stop yii from see-sawing
yii leaves this file around which is a duplicate of its test. So the autoloader loads it twice. Kill it between runs.

Reviewed By: @JoelMarcey

Differential Revision: D1030682
2013-10-29 12:00:50 -07:00
Bert Maher 641a0ed1cc Fix type_profiler test
The test output depended on the sort order of equally-likely
types; we don't care about their order, but we do care about frequency
ordering, so bias the output towards integer.

Reviewed By: @scannell

Differential Revision: D1030488
2013-10-29 12:00:45 -07:00
Owen Yamauchi 5c2fb806cc Implement ARM::emitCallArrayPrologue
The x64 version of this distinguishes the case where dvs.size() == 1
because then it can use a compare with mem and immediate operands. ARM
can't do that.

Reviewed By: @edwinsmith

Differential Revision: D1028069
2013-10-29 12:00:12 -07:00
Owen Yamauchi 34dcd32cd3 Fix build breaks in various configurations
Apparently #error isn't the best thing. This fixes a couple build
blockers: building vixl natively on ARM, and building in non-fast-TLS
mode.

Reviewed By: @scannell

Differential Revision: D1029917
2013-10-29 12:00:07 -07:00
Edwin Smith f869b1e304 Rename RegisterInfo to PhysLoc
RegisterInfo either represents registers or spill locations for
an SSATmp; Looking at the way we use it, the name PhysLoc makes
more sense.

Reviewed By: @ottoni

Differential Revision: D1025818
2013-10-28 11:28:48 -07:00
Edwin Smith fbb70fa6f9 Introduce Shuffle instruction
Linear scan inserts Shuffle to resolve copies of Jmp instructions,
removed shuffle code from cgJmp.

Reviewed By: @swtaarrs

Differential Revision: D1023716
2013-10-28 11:28:42 -07:00
Edwin Smith d12929d7c2 Rename code-gen.cpp/h to code-gen-x64.cpp/h
Reviewed By: @oyamauchi

Differential Revision: D1027811
2013-10-28 11:01:40 -07:00
Edwin Smith 52f9a1f241 Use <= instead of subtypeOf in a bunch of JIT code
This is mechanical and I think it improves the code.

Reviewed By: @swtaarrs

Differential Revision: D1026129
2013-10-28 11:01:35 -07:00
Drew Paroski 6464d329dc Make array_intersect and array_intersect_key work with collections
Rewrote the algorithms for array_intersect() and array_intersect_key() to
work with collections and to achieve better performance (particularly for
array_intersect()).

Reviewed By: @dariorussi

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

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

Reviewed By: @mikemag

Differential Revision: D1021035
2013-10-28 11:01:23 -07:00
Max Wang b6785d8a5d Implement SleepWaitHandle
Allows us to sleep asynchronously.

Reviewed By: @jano

Differential Revision: D984340
2013-10-28 11:01:14 -07:00
Joel Marcey a5363d8e21 Add an --allexcept option and fix some bugs
Add an --allexcept option that allows us to run all tests but those listed.

Fix a weird bug that happens with an HipHop warning occurs on the same line as a status. Had to fix the regex for that.

A few other fixes

Next up:
  Each test of each framework in own process
  Create per framework shell script to run only those tests that had a different status than expected

Reviewed By: @ptarjan

Differential Revision: D1028292
2013-10-28 11:01:05 -07:00
mwilliams 6258f03127 Fix a race in retranslateOpt
retranslateOpt called retranslate, which could end up
returning nullptr if another thread got the source-key lock, and
then got blocked on the write lease.

Call translate instead, and don't generate optimized translations
if the debugger is attached.

Reviewed By: @ottoni

Differential Revision: D1027892
2013-10-28 11:00:53 -07:00
Bert Maher efbb366885 Integrate into hphpd info command
Modified info command in debugger to display type information for a
specified function

Reviewed By: @hermanventer

Differential Revision: D887484
2013-10-28 11:00:48 -07:00
Mike Magruder a4492a4fc1 Revert "Use a separate field to keep track of allocations for the purpose of out of memory checking."
: This reverts commit 93009b15c5c09549425a264dc17d24cff6cb1e14.

Conflicts:
	hphp/NEWS

Reviewed By: @hermanventer
2013-10-28 11:00:44 -07:00
Abel Nieto ede2e5c30a Change the return type of map() et al
map(), filter() and their family members should return FVs, instead of vectors.

Reviewed By: @paroski

Differential Revision: D1022281
2013-10-28 11:00:40 -07:00
Owen Yamauchi 677a59c594 Remove 'using namespace JIT::X64' from tx64; implement fallback interp
Removing the using-directive exposed most of the remaining bits of
x64-specificness in tx64. I just added explicit namespace qualification
to most of them and will deal with them properly later. (I actually find
it kind of suspect that we haven't hit problems with, for example,
bindJmpccFirst yet.)

The one place where I made actual changes is in the code that handles
emitting a fallback request to interp in the event of total codegen
failure for a tracelet. Previously it was handy to keep this
unimplemented (I've been testing with an assert(false) in the
X64Assembler ctor) because it exposed places where we were getting
spurious failures because not enough IR opcodes were implemented. The
remaining places where we're hitting this failure mode are legitimate:
polymorphic tracelet explosion and running out of spill space.

Reviewed By: @ottoni

Differential Revision: D1027996
2013-10-28 11:00:35 -07:00
Sean Cannella f4ef9cae24 Implement missing forward compat constants
Implement unused FILE_BINARY and FILE_TEXT because PHP does
even though they have no effect in PHP 5.

Closes #1215

Reviewed By: @JoelMarcey

Differential Revision: D1027907
2013-10-28 11:00:30 -07:00
Naresh 62c0cd0052 Implement PhpFileExtensions runtime option
Implement file extensions set that should be treated like PHP
files in the webserver

Closes #1207

Reviewed By: @markw65

Differential Revision: D1021819

Pulled By: @scannell
2013-10-28 11:00:25 -07:00
Sara Golemon fbd9dd7258 Don't build folly/experimental/exception_tracer/StackTrace.c
Closes #1219
2013-10-28 10:58:52 -07:00
Sara Golemon 90d08a2b8f Kill bin/ directory
Move generated systemlib.php to hphp/system/
Let other intermediates live in their CMakeFiles dirs
2013-10-25 15:31:28 -07:00
Sara Golemon 7dacd36a25 Clean up ext_hhvm CMakeLists.txt 2013-10-25 15:16:42 -07:00
Sara Golemon 8a15eeb271 Minor refactor of CMake files
Move hphp_runtime_static build steps into hphp/runtime
Save main hphp/CMakeLists.txt to be a meta makefile
2013-10-25 14:56:26 -07:00
Sara Golemon 77f7c80733 Pick up new folly changes 2013-10-25 14:01:39 -07:00
Owen Yamauchi 9435d5cb5f Implement debugger guards for ARM
All the debugger tests were failing because of this.

The Tricky Topic of the Day introduced in this diff is ARM code's
interaction with thread-local storage. ARM has its own way of getting a
pointer to thread-local storage (already implemented in tlsBase()) but I
don't know exactly how it works -- i.e. whether it works the same way as
on x64, where the system register points to an area with a bunch of
pointers to thread-local objects. ARM certainly doesn't have
segmentation the way x64 does.

Rather than figure all that out and implement corresponding support in
vixl, I've elected to just call into C++ to get the TLS base. This is
going to be one area where simulated-ARM mode diverges significantly
from native-ARM mode, but we'll cross that bridge when we come to it.

Reviewed By: @jdelong

Differential Revision: D1023960
2013-10-25 12:03:42 -07:00
mwilliams 93842ddea9 Fix retranslateOpt bug
If we've already optimized, we want to do a regular
translation, not an optimized one

Reviewed By: @ottoni

Differential Revision: D1026773
2013-10-25 12:03:34 -07:00
Jan Oravec 1e752dda0d Remove unused childOfYield and hphp_continuation_done()
childOfYield flag and hphp_continuation_done internal method are no
longer used. Remove them.

Reviewed By: alexsuhan

Differential Revision: D1016610
2013-10-25 12:03:30 -07:00
Joel Marcey 0de11da8e7 fix stream_select error
I am a clown.

Reviewed By: @ptarjan

Differential Revision: D1027352
2013-10-25 12:03:22 -07:00
Joel Marcey 40073897e8 Fix the timeout process in the oss framework test script
The timeout was broken, as in it didn't work. Take a new approach. Timeout per individual test in an individual framework instead.

Default is allow 60 seconds per test.

And some other fixes too.

Reviewed By: @ptarjan

Differential Revision: D1027221
2013-10-25 12:03:18 -07:00
Eugene Letuchy 1990ff3bd4 create a Class creation time hook
... for the purpose of adding trait-based methods to a class at PreClass-to-Class conversion time.

Reviewed By: @jdelong

Differential Revision: D1023552
2013-10-25 12:03:09 -07:00
Alex Malyshev 6b68831b2f SQLite3::escapestring should be static
We had it as an instance method.

Fixes a fatal in Joomla

Reviewed By: @scannell

Differential Revision: D1026742
2013-10-25 12:03:05 -07:00
Max Wang 878b1dc4f0 Refactor SessionScopedWaitHandle from ETEWH
Generic wait handle for async executions which are not bound by context
but rather have session scope.  Used for upcoming SleepWaitHandle.

Reviewed By: @jano

Differential Revision: D1018708
2013-10-25 12:03:00 -07:00
aravind 0dfc7771c1 IncRef Sinking fix
An IncRef that is marked as a candidate for sinking should
be removed from the sinking list only if the corresponding DecRefNZ
is live.

Reviewed By: @ottoni

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

Fixes the last fatal in yii

Reviewed By: @ptarjan

Differential Revision: D1026211
2013-10-25 12:02:52 -07:00
Jan Oravec 2782370d68 Process ready wait handles in LIFO rather than FIFO order
After eager execution, the queue of ready ContinuationWaitHandles may
contain only unblocked handles. Process the most recently unblocked first
to improve cache locality.

Reviewed By: alexsuhan

Differential Revision: D1016230
2013-10-25 12:02:47 -07:00
Paul Tarjan 5896ab5879 set m_documentRoot even if there is no hdf
This variable is entirely independent of the hdf, so it should be set even it there isn't one.

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

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

Reviewed By: @markw65

Differential Revision: D1025781
2013-10-25 12:02:43 -07:00
Edwin Smith 39d72574d4 Tidy up the API to postorderWalk()
We always call it with the full # of blocks and the unit's
entry point, so just pass the unit.

Reviewed By: @jdelong

Differential Revision: D1026189
2013-10-25 12:02:35 -07:00
mwilliams 6ecedd940e Fix jitted symbols in gdb 7.6
gdb traps calls to a function named __jit_debug_register_code,
and updates its internal symbol tables.

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

Reviewed By: aravind

Differential Revision: D1026295
2013-10-25 12:02:26 -07:00
Max Wang 5fb8233ee2 Allow ETE receiveSome() to timeout, as receiveSomeUntil()
We want to be able to timeout waiting for external thread event
completion in order to order correctly with async sleeps.

Reviewed By: @jano

Differential Revision: D1018706
2013-10-25 12:02:21 -07:00
Joel Marcey 348911acfb Simplify the content of the test script expect files
The expect files were containing a bit too much infomration. Now they just contain name of test and status. No other data.

Also increased the timeout (mostly because of the time for pear) and tried to text align the csv output as best I could.

Some minor other changes too

@ptarjan: You should run the graph script with --csv and --csvheader ... modify the script to handle the header that comes each time we append.

Reviewed By: @ptarjan

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

Closes #1210

Reviewed By: @markw65

Differential Revision: D1025861
2013-10-25 11:57:56 -07:00
Abel Nieto da31dcca9d Support (de)serialization
FrozenVector now supports serialize() and unserialize().

Additionally, as a result of the above, var_dump(some_frozen_vector)
now gives a more meaningful output.

Reviewed By: @paroski

Differential Revision: D1013734
2013-10-25 11:57:51 -07:00
Abel Nieto fb61a37771 Make the JIT aware of traits implementing interfaces
Correctly populate the instanceBits of each class so that "fast path"
taken by the JIT correctly supports traits implementing interfaces.

Reviewed By: @swtaarrs

Differential Revision: D1023165
2013-10-25 11:57:47 -07:00
Joel Marcey 89827a6513 Just some minor fixes to the code generator for HNI
After stubbing out ZipArchive, there were a few issues that caused complilation problems. This fixes those.

- Add a string argument to NotImplementedException
- Change CStrRef to const String&
- I think "null" should be "void" in the typemap; otherwise you get "static null HHVM_METHOD" type functions.

Reviewed By: @sgolemon

Differential Revision: D1025577
2013-10-25 11:57:42 -07:00
Sara Golemon 2ecabd236d Switch folly to using a submodule instead of a fork.
To sync the folly submodule the first time, you'll need
to issue:

git submodule init
git submodule update

From then on, you'll also want to make sure folly is up to
date by issuing `git submodule update` after a `git pull`.
2013-10-25 11:45:56 -07:00
Sara Golemon 3fd7ec17f7 Skip mongo tests when ext not built in 2013-10-24 13:54:56 -07:00
javer 920046e2c2 Preserve class property DocComment for reflection
This allows to use annotations in Doctrine 2 ORM Entities.

Fixes 225 unit tests in doctrine/doctrine2.
Fixes 118 unit tests in doctrine/annotations (100% passes now).

Closes #1199

Reviewed By: @paroski

Differential Revision: D1019739

Pulled By: @scannell
2013-10-24 11:49:39 -07:00
Edwin Smith 0afb900ab3 Per-instruction register map
Change RegAllocInfo from a 1D SSATmp->RegisterInfo map to a
2D IRInstruction,SSATmp->RegisterInfo map.  This lets the register
allocator assign a different register or spill slot to a single
SSATmp at different locations during its lifetime.

Reviewed By: @ottoni

Differential Revision: D1021754
2013-10-24 11:49:39 -07:00
Eugene Letuchy 71d75a0144 make traits tests independent of the contents of systemlib
... it's not germane to the purpose of the tests: nor is it
 sustainable to continue to add/remove the names of system traits from
 these tests. A possible alternative is to pass a flag to
 get_declared_classes|traits to exclude systemlib builtins.

Reviewed By: @paroski

Differential Revision: D1023627
2013-10-24 11:49:39 -07:00
Jordan DeLong f97767ee50 Change magic number in memory-manager debug mode to be more 1337
The old magic number was pretty shamefully bad.  It's
definitely no 0xC01O55A1B0B51ED5, but maybe this is a little better
than what it was ...

Reviewed By: @edwinsmith

Differential Revision: D1019412
Differential Revision: D1025644
2013-10-24 11:49:28 -07:00
Jordan DeLong 5ce77ede53 Don't allow certain AssertType types in the JIT for now
The JIT will crash in some situations with these.  We can end
up going to cgAssertType with a constant src, which will break when it
didn't have registers.

Reviewed By: @swtaarrs

Differential Revision: D1019432
2013-10-24 08:07:12 -07:00
Jordan DeLong 960f3e2194 Make AssertT* instructions actually affect tracelet length and guards
Reviewed By: @swtaarrs

Differential Revision: D1019431
2013-10-24 08:07:12 -07:00
Jordan DeLong d952cf1e4f Reformat FileScope::analyzeIncludesHelper
I was trying to understand what this function does, and this
made it a bit easier for me to follow the logic (less nesting).

Reviewed By: @andralex

Differential Revision: D1018846
2013-10-24 08:07:12 -07:00
bsimmers 35cc0c5d54 Don't look at NormalizedInstruction's fields to translate FPushClsMethodF
The information is available in the IR.

Reviewed By: @jdelong

Differential Revision: D1020934
2013-10-24 08:07:11 -07:00
bsimmers 0d316a5b7e Stop using Classes from NormalizedInstruction in emitFPushObjMethodD
This information is available in the IR so let's get it from there
instead of NormalizedInstruction. This is part of my crusade to minimize
IRTranslator's role and eliminate NormalizedInstruction.

Reviewed By: @ottoni

Differential Revision: D1020925
2013-10-24 08:07:11 -07:00
bsimmers 23c3e83f11 Move most of FPushCuf's work from IRTranslator to HhbcTranslator
This kind of logic doesn't belong in IRTranslator, especially since
it's a thin layer we'd like to eventually get rid of.

Reviewed By: @oyamauchi

Differential Revision: D1020911
2013-10-24 08:07:11 -07:00
bsimmers 4c36e0af6a Stop using class names from NormalizedInstruction in emitAGet*
If the names are really constant, they should be available to
HhbcTranslator. If there are any cases where they're not available, we should
make them available.

Reviewed By: @jdelong

Differential Revision: D1020897
2013-10-24 08:07:11 -07:00
bsimmers f6e0bc47c2 Clean up class property and global setting/getting code
This code was quite old and was using predicted types and strings
passed in from fields on NormalizedInstruction, which will be going away
soon. It's been changed to just use the information we already have available
in m_evalStack and rely on the optimizations/prediction support we have now. I
also fixed a bug where the name string wasn't being consumed on every path by
reworking who's responsible for destroying it.

Reviewed By: @jdelong

Differential Revision: D1020885
2013-10-24 08:07:10 -07:00
bsimmers b11dbab7bb Clean up Assert(Type|Loc|Stk), add filterAssertType
filterAssertType is used by some upcoming code to handle things like
assserting {InitNull|Obj<C>} when the known type is Obj. I also cleaned up how
we handle invalid types from static analysis. We used to replace the assert
instruction with a Fatal, but we can still end up generating bogus IR if we
continue translating. The best thing to do (for now) is to punt on the whole
trace, since there's no clear way to create well-formed IR for the whole thing.

Reviewed By: @jdelong

Differential Revision: D1020613
2013-10-24 08:07:10 -07:00
bsimmers d70e4828ea Add new dest types for LdRef and This, add support for weak type constraints
LdRef now removes any specialization from what we think is in the
inner type, to avoid having to guard on it again. This produces a value
specialized with the current context class. Weak type constraints go through
the process of finding the appropriate guard to constrain but don't actually
constrain the guard. They can be used to determine if we can use a specialized
type without having to add any additional guards, which I'll need to do in an
upcoming diff.

Reviewed By: @ottoni

Differential Revision: D1020843
2013-10-24 08:07:10 -07:00
bsimmers 619dfe69ea Don't read NormalizedInstruction's inputs in IRTranslator
I'm planning on eliminating the inputs vector soon. Reading types from
it (instead of HhbcTranslator) can bypass guard relaxation, and the information
is all available elsewhere. This diff just includes the straightforward cases;
the more invasive bytecodes will come in separate diffs.

Reviewed By: @ottoni

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

Reviewed By: @markw65

Differential Revision: D944849
2013-10-24 08:07:09 -07:00
Guilherme Ottoni 9fba6f4f73 Regionize and retranslate each function at once
This diff changes how region translation operates, with the goal of
improving code locality.  Instead of triggering retranslation at a
translation granularity, this diff changes things so that only
translations corresponding to the function-body entry trigger
retranslations.  The other translations still keep their profile
counters, which are used to guide region formation.

When an optimized retranslation is triggered for a function, a series
of regions is created for this function.  These regions ensure that
all profiling translations for this function (and control flow arcs
connecting them) are covered by the regions created.  The regions are
then translated consecutively in the TC, following an order that tries
to improve the locality of the generated code.

After a function has been regionized, any retranslation that is
triggered by new live types uses the tracelet JIT.

Reviewed By: @swtaarrs

Differential Revision: D1017506
2013-10-24 08:07:09 -07:00
Sean Cannella 07e72438f2 Re-implement GenerateDocComments
GenerateDocComments had inadvertently become a no-op. Restore
it.

Reviewed By: @markw65

Differential Revision: D1023934
2013-10-24 08:07:08 -07:00
Sean Cannella 453195bb1f Remove dead hphpc options
Remove hphpc options that are no longer used

Reviewed By: @markw65

Differential Revision: D1023862
2013-10-24 08:07:08 -07:00
Kristaps Kaupe 223bdd7523 Native.h macro typo
Fix macro typo

Reviewed By: @JoelMarcey

Differential Revision: D1023850

Pulled By: @scannell
2013-10-24 08:07:08 -07:00
Paul Tarjan 9d1d782cf0 re-import zend headers
Had I been smarter when I started this project, I would have done this from the begining. It used to be a hodgepodge of some implementation in headers and others in .cpp. When I would import a new extension I had to fight importing all the new macros and function signatures, putting them in their right place or else I will get compile errors.

So, I spent today cleaning up this story. Now all headers are original Zend (codemodded with tabs to spaces) with any changes I needed to make wrapped in a `#ifdef HHVM`. That way if I ever want to re-import I can slice it and insert it easily. It also has the nice property that the old code is right there so you can compare at the glance what I am doing and what they are doing.

I updated the README to explain the file structure.

I talked to @jdelong and @markw65 about a good long-term solution. @jdelong things we should code to the API and not share any implementation, @markw65 prefers compile errors  but said link errors would be ok. He just doesn't think I should pull in all the implementations and force run-time errors since those would be hard to debug. I think having their `.h` files and our own `.cpp` is a good compromize for now.

Reviewed By: @paroski

Differential Revision: D983907
2013-10-24 08:07:08 -07:00
Paul Tarjan 215b2d2e2c import mongo extension
This is the biggest extension on pecl. Most of their tests depend on a server implementation which I don't really want to package into our test infra yet.

Many of the tests don't pass, but I want to get this up for review with the passing tests since i think many of the changes are good.

Reviewed By: @paroski

Differential Revision: D979397
2013-10-24 08:07:01 -07:00
Jordan DeLong f8cde99fb2 A few bytecode spec tweaks (relating to FPI, cuf iters)
It's not explicitly listed, but we can't have Catch, Fault or
DV entry offsets inside of FPI regions, so I added that.  Also update
a little bit about Cuf iters.

Reviewed By: @edwinsmith

Differential Revision: D1019493
2013-10-24 07:39:10 -07:00
Jordan DeLong 816863ff6f Make Fatal take only a single OA arg
This was a little more convenient for the bytecode
representation I'm using (it's nice but not critical that all opcodes
with subops only have a single subop).  Also hook up to assembler
while here.

Reviewed By: @alexmalyshev

Differential Revision: D1022933
2013-10-24 07:39:06 -07:00
Jordan DeLong 1e848825b7 Add an unsupported case in scalar array emission
If you don't run some of the optimization passes, sometimes
scalar arrays from UnaryOpExpression will have sub-members that are
other UnaryOpExpressions, which isn't handled here.  It looks like
getScalarValue is there for this.

Reviewed By: @edwinsmith

Differential Revision: D1017234
2013-10-24 07:38:56 -07:00
Bert Maher 0a338e7d49 Partial de-trace-ification of DCE
Some cleanup of DCE, attempting to get rid of IRTrace where
it's not needed.  A lot of DCE deals explicitly with traces so I'll
leave that for the another diff.

Reviewed By: @edwinsmith

Differential Revision: D1023480
2013-10-24 07:38:51 -07:00
Edwin Smith cdebfada6f Use hints instead of trace to order blocks in postorderWalk()
postorderWalk() chooses which successor blocks to visit based on
trace; it visits main->exit edges first, to bias towards visiting
them sooner.  (So they'll be later in reverse-postorder).
This diff uses block hints instead.  This will result in slightly
different order for if/then/else regions with an Unlikely arm, that
were entirely on the same trace.  But it should be equivalent for
main->exit edges since exit blocks are all marked Unlikely.

Reviewed By: @jdelong

Differential Revision: D1022275
2013-10-24 07:38:46 -07:00
Sara Golemon e8b0e6a6ed Link against libpam if it's available
The logic looking at c-client's linkage.h file is too clever. (hah)
Just follow PHP's example and always link it when possible.

Closes #1181
2013-10-23 23:31:03 -07:00
Franck STAUFFER e69df8d6e4 row_count properly set on INSERT/UPDATES
Fixes bug due to variable shadowing

Closes #364

Reviewed By: @JoelMarcey

Differential Revision: D1021780

Pulled By: @scannell
2013-10-23 08:24:41 -07:00
Owen Yamauchi 05dc23323c Implement unconditional jump smashing on ARM; fix lolbug
There were two problems. First, jmpTarget() wasn't recognizing jumps
properly because I was looking at the wrong instruction bits. Then,
smashing unconditional jumps wasn't implemented.

Reviewed By: @jdelong

Differential Revision: D1021956
2013-10-23 08:24:37 -07:00
Owen Yamauchi 0e34715a4a Implement function prologues in ARM
This is mainly what's holding us back in test/quick. There's a lot of
stuff going on here:

- Adding code-gen-helpers-arm.cpp. There's a practical need for this:
  we're starting to write out a lot of calls to C++ functions, which
  should be abstracted out because it happens differently depending on
  whether we're simulating ARM or running on native ARM.

- Initialize rStashedAR when starting the simulator. This was a bug.

- Change the order of pushing x29 and x30 around calls to properly mimic
  the x64 stack frame.

- Implement fcallHelperThunk.

- Templatize a couple of vixl functions to let us move pointers into
  registers without reinterpret_cast. Also fill the simulator stack with
  junk before starting up a simulator; in an early version of this diff
  we were actually reading from the stack out-of-bounds. It wasn't
  causing any bugs, but let's get out ahead of that.

Reviewed By: @jdelong

Differential Revision: D1019980
2013-10-23 08:24:33 -07:00
Igor Zinkovsky ebb082916f send all Logger output to stderr
Prior to this change, Logger::Info and Logger::Verbose were going to
stdout, which can easily break scripts.

I didn't see any Logger::Info or Logger::Verbose call sites, which assume that
their output is going to stdout.

Reviewed By: @paroski

Differential Revision: D962372
2013-10-23 08:24:28 -07:00
aravind f1b382e431 Don't trace through IncRef for SpillStack
This can cause mismatched IncRef/DecRef pairs in the IR.

Reviewed By: @swtaarrs

Differential Revision: D1022881
2013-10-23 08:24:24 -07:00
Paul Tarjan 836d7b81a3 fix ASAN bug in JSON parser
Wow, our json parser has diverged so much from zend. This is basicaly what theirs does. More importantly, this is correct.

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

Reviewed By: @scannell

Differential Revision: D1021678
2013-10-23 08:24:20 -07:00
Drew Paroski 6b57769566 Make array_diff and array_diff_key work with collections
This diff reimplements array_diff() and array_diff_key() to be more
performant and to support collections.

The new implementation is more than 5x faster the old implementation on a
number of micro-benchmarks I tried, with some of the micro-benchmarks
showing as much as a 40x improvement.

Reviewed By: @dariorussi

Differential Revision: D1019693
2013-10-23 08:24:08 -07:00
Joel Marcey ae92abb5c6 Fix issue with composer timing out on downloading dependencies and fix deadlocking
- Fix issue with composer timing out on downloading dependencies
- Try to reduce or eliminate deadlocking by using individual repos for each framework run
- Add Mediawiki to the frameworks; Remove typo3 since the tests are running correctly
- Simplified the expect files to just have test and status
- Other modifications

I have decided I need to refactor this thing a bit. May try to parallelize it more. Probably make some classes. Etc. For example, I should add a --jit and --nojit mode, probably.

Reviewed By: @ptarjan

Differential Revision: D1022337
2013-10-23 08:21:23 -07:00
Owen Yamauchi 1274347ca3 Implement codegen for UnpackCont in ARM mode
UnpackCont is troublesome to interp-one; it doesn't even work in x64
mode. It translates to a single IR instruction, so this just implements
codegen for that.

In the process of debugging, I discovered that the stack-chasing for
UnpackCont was getting the order of its stack outputs wrong.

Reviewed By: @edwinsmith

Differential Revision: D1020297
2013-10-23 08:13:28 -07:00
Owen Yamauchi 0e2b208855 CGetL2 looks past a StackElem, not a Gen
IR translation for CGetL2 was assuming the top element on the stack was
a Gen, but it can also be a Cls. StackElem unifies these two types, and
is what we want.

Reviewed By: @swtaarrs

Differential Revision: D1022105
2013-10-23 08:13:24 -07:00
Rachel Kroll 47b8369f86 Create file cache as 0664, not 0600
Match mode for file cache relative to original code

Reviewed By: @emiraga

Differential Revision: D1022126
2013-10-23 08:13:20 -07:00
bsimmers dc1abd31c5 Revert "[hphp] make 'abstract async' syntax error only behind !(whole program)"
We're still not ready for this.

Reviewed By: @elgenie
2013-10-23 08:13:16 -07:00
Andrey Sukhachev b825e9fa88 Provide an API to store an APC key without the TTL adjustment applied.
Why do I need that?
On devservers I need to be able to store certain APC keys without them
being automatically evicted when the TTLLimit expires, i.e. to simulate
the "primed" behavior in sandboxes, which don't have apc_prime.so.
The  cost of rebuilding these keys can negatively impact the sandbox
performance.

The function name is intentionally scary do discourage the unintentional
use (which mimics the www conventions).

Reviewed By: @dariorussi

Differential Revision: D1016718
2013-10-23 08:13:11 -07:00
Bert Maher 072cb790d2 Print and toString for Blocks
These are nice to have when poking around in gdb

Reviewed By: @edwinsmith

Differential Revision: D1021633
2013-10-22 10:00:20 -07:00
Edwin Smith 59dd9c68a7 Remove Block::m_func and un-plumb it through the JIT.
I think the need for m_func has been subsumed by every instruction
having a BCMarker.  This is a mechanical change; m_func was dead.

Reviewed By: @ottoni

Differential Revision: D1019715
2013-10-22 10:00:20 -07:00
bsimmers 654c563286 Skip function exit events after side exiting in an inlined call
This is slightly less optimal than running the function enter event in
the exit trace, but it's significantly simpler and safer. I might investigate a
better solution some time in the future.

Reviewed By: @mikemag

Differential Revision: D1020793
2013-10-22 09:53:16 -07:00
Julius Kopczewski 0445bebfd7 Refactoring JobDispatcher for greater type safety
Removed a superflous template argument for the Dispatcher,
replaced void* m_opaque for typed m_context.

Reviewed By: @jdelong

Differential Revision: D988558
2013-10-22 09:53:08 -07:00
Paul Tarjan baf17e9b74 change to https://
I want to be able to run these headless, and with the `git@` urls it tries my public key first.

Reviewed By: @JoelMarcey

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

Reviewed By: @mikemag

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

Reviewed By: @mikemag

Differential Revision: D1017420
2013-10-22 09:52:51 -07:00
Yuval Hager a1be625704 Fix Buffer Overrun messages for tiff files
While processing tiff tags, the end pointer was not updated
after a realloc. Also, while processing IFD tag, end and begin pointers
were switched.

Closes #1154
Closes #1193

Reviewed By: @ptarjan

Differential Revision: D1019738

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

Reviewed By: @JoelMarcey

Differential Revision: D1019758
2013-10-21 14:16:49 -07:00
Sean Cannella e4c6ee2e8a Fix template explosion in TransRec::print
folly::format explodes and exceeds a sane template depth so
break up the calls.

Reviewed By: @swtaarrs

Differential Revision: D1019754
2013-10-21 14:16:45 -07:00
Bert Maher fa892e57b8 Jump opt for side-exiting jcc's
In the region compiler we can create side exits due to
user-level control flow, and we'd like the side exit to not go through
Astubs after it's been chained, if possible.  This optimization is
almost like what we already have for CheckStk and CheckLoc, but we
need it for Jcc's too.

Reviewed By: @jdelong

Differential Revision: D1019242
2013-10-21 14:16:33 -07:00
Gordon Huang 58cbeb02d5 Add two more functions to FBUnserializer API
This diff adds two functions to the FBUnserializer API, which I need to use.
1. done(), check whether the whole string is unserialized (I need it to make sure the fbobject/assoc range unserialize consumes all the input and didn't leave anything undecoded (and lost parts of the data).
2. getSerializedMap. I ran into a case that the map (structure data) comes first in the result, but the needed info (structure data fbtype) comes after that. I need to record the serialized map somewhere and then redecode the map with the fbtype.

Reviewed By: andrii

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

Reviewed By: @sgolemon

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

Reviewed By: @edwinsmith

Differential Revision: D1017631
2013-10-21 14:16:20 -07:00
Paul Tarjan 1632ca1184 rename HPHP_VERSION to HHVM_VERSION
People keep asking me how to verify their upgrade worked and I tell them to print this constant. Then they always ask why is it still named HPHP. Good question.

I left the old one. Maybe we can kill it in 6 months?

Reviewed By: @sgolemon

Differential Revision: D1019640
2013-10-21 14:16:00 -07:00
Sara Golemon 6dbd9c85f6 Revert temporary gcc 4.6 hacks.
I modded the OSS version of the repo last week to keep it
building on gcc 4.6.  After much discussion we're setting the
minimum version at 4.7 and rather than sync these hacks internally
we'll be reverting them from the OSS side.
2013-10-21 13:49:18 -07:00
Sara Golemon e04980ca2b Increase minimum GCC version to 4.7.0
If you absolutely can't upgrade past gcc 4.6.x,
checkout tag gcc-4.6 or follow branch HHVM-2.2
2013-10-21 13:29:28 -07:00
Paul Tarjan 5848896a92 Allow default .hdf to be compiled in to php binary
Reviewed By: @swtaarrs

Differential Revision: D1013374
2013-10-20 21:02:26 -07:00
Jordan DeLong 2f4aa50bc5 Memoize getNativeFunctionName
Makes doing IR dumps faster.  (Ideally we'd combine this with
the one for Disasm but it's probably not a big difference and this
helped for now.)

Reviewed By: @swtaarrs

Differential Revision: D1013823
2013-10-20 21:02:22 -07:00
Edwin Smith e23001357e Update terminology in ir.specification to refer to blocks as blocks.
The IR is block-based now, and labels are optional.  Updated wording.

Reviewed By: @jdelong

Differential Revision: D1019285
2013-10-20 21:02:18 -07:00
Jordan DeLong 179439a9e4 Fix a bug in AGet{L,C} and simplifyLdCls
If AGetL throws due to autoload failure (e.g. parse time
fatal), we crash in the unwinder.

Reviewed By: @bertmaher

Differential Revision: D1018048
2013-10-20 21:02:13 -07:00
bsimmers 6d7e68a5cc tc-print improvements and fixes
tc-print used to assume that all the bytecodes in a translation were
in the same function. This was a fine assumption, but now we have inlining so
that's often not true. TransBCMapping now holds an MD5 to identify the unit it
came from. This is then used while printing bytecodes to look in the correct
unit. I included a few other small tweaks:

- Better alignment for some output, and replace a lot of snprintf with
  folly::format
- systemlib is embedded in the tc-print binary so it can be loaded at startup
  (it's not in production repos)
- The native func and class units are generated at startup
- Function names are printed in translation summaries
- Bytecode offsets are printed in decimal instead of hex, to match conventions
  elsewhere

Reviewed By: @ottoni

Differential Revision: D1016351
2013-10-20 21:02:09 -07:00
Bert Maher 88a2da1408 Describe the global litstr table in bytecode.specification
Also spellchecked, because OCD

Reviewed By: @jdelong

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

Closes #945

Reviewed By: @jdelong

Differential Revision: D1006603
2013-10-18 22:18:48 -07:00
Owen Yamauchi 4915bdf7fd Add support for emitting PC-relative loads to vixl assembler
The lower-level assembler infra is there, but this addressing mode
wasn't exposed in the public-facing API. This will allow us to generate
better code for stuff like smashable jumps, which I've included in this
diff. (Previously, it was one instruction to compute an address and
another one to load; now it's just a load.)

Reviewed By: @jdelong

Differential Revision: D1017834
2013-10-18 22:18:47 -07:00
Joel Marcey 9e1f0cd094 Stub out two sqlite PDO methods.
Doctrine unit tests calls one of these two methods (sqliteCreateFunction). We fatal because we do not support it. The PHP docs says these functions are experimental, but let's not fatal if we don't have to.

http://www.php.net/manual/en/pdo.sqlitecreatefunction.php

With this diff (and a Doctrine patch that fixes some interface issues it was having), we no longer fatal in Doctrine! We do, however, fail a lot of tests.

Reviewed By: @ptarjan

Differential Revision: D1017386
2013-10-18 22:18:47 -07:00
Joel Marcey 79db99c827 Add Pear and Magento to our test script
Pear and Magento now run correctly with unit testing. I had to do an additional download for PEAR via the new
pull request mechanism, but it works out well. Neither fatal! :)

Reviewed By: @ptarjan

Differential Revision: D1018560
2013-10-18 22:18:47 -07:00
Joel Marcey 952163b9ae Add the pull request that fixes the interface problem with Doctrine
The interface problem ended up being a problem with Dbal (a dependency). This was fixed via a fork from the main dbal repo, but hasn't been merged into the main repo yet.

The script is updated to support pull requests.

Reviewed By: @ptarjan

Differential Revision: D1017683
2013-10-18 22:18:46 -07:00
James Miller 8e87aaa617 update .gitignore for HHVM
Adds a few more filetypes to the HHVM .gitignore

Reviewed By: @ptarjan

Differential Revision: D1015499

Pulled By: @scannell
2013-10-18 22:18:40 -07:00
aravind 7f6e7e9cbe Fixes for PGO mode
This fixes a couple of asserts I hit running www in DEBUG mode with
-vEval.JitPGO=1 -vEval.JitRegionSelector=hottrace
-vEval.JitPGOHotOnly=0.

Reviewed By: @ottoni

Differential Revision: D1016284
2013-10-18 22:12:21 -07:00
Brett Simmers 6a41c10cdf Don't truncate HphpArray's allocation size to 32 bits
For arrays that hold ~150 million or more elements, we need to
allocate more than 4GB of ram. computeAllocBytes used to return a uint32_t so
we were truncating the real size and allocating a lot less memory than we
needed.

Reviewed By: @jdelong

Differential Revision: D1016732
2013-10-18 22:12:12 -07:00
Owen Yamauchi df4a7e74da Move function prologues out of tx64
This is the last big chunk of code emission logic in tx64. The path to
getting stuff working in ARM is now blocked by function prologues, so
this needs to happen now.

Function prologues are delicate and messy, so this change isn't 100%
straight code motion.

- The call-array prologue stuff was quite smooth, and all the changes
  are mechanical.

- funcPrologue() turned out to have a pretty big and easily separable
  chunk of x64-specific code in the middle, sandwiched between big
  chunks of platform-agnostic code. I pulled out the platform-specific
  part into the new module I created.

- All the function-guard smashing stuff is very platform-specific so got
  pulled out as well.

Reviewed By: @ottoni

Differential Revision: D1013868
2013-10-18 22:12:08 -07:00
Sean Cannella 12a756085f Better symbol resolution for pprof
Using names more in line with Func::prettyPrint and using full
names for builtins makes it a lot more clear what is going on.

Reviewed By: @hermanventer

Differential Revision: D1016225
2013-10-18 22:12:04 -07:00
Yuval Hager 4b33353789 Support custom reason for status header
Support custom reason for status header

Closes #967
Closes #1183

Reviewed By: afrind

Differential Revision: D1015633

Pulled By: @scannell
2013-10-18 22:11:59 -07:00
Edwin Smith df1ca4c26c Clean up shuffleArgs.
Use smart container, return the move schedule by value,
and do some manual CSE for clarity.

Reviewed By: @jdelong

Differential Revision: D1016082
2013-10-18 22:11:54 -07:00
Eugene Letuchy 0a6adf3bf4 introduce a helper for overwriting an ActRec as cells
... as discussed.

Reviewed By: @jdelong

Differential Revision: D1013186
2013-10-18 22:11:50 -07:00
Jan Oravec b5972e789b Rename ContinuationWaitHandle to AsyncFunctionWaitHandle
- rename ContinuationWaitHandle to AsyncFunctionWaitHandle
- rename onYield hook to onAwait hook

Reviewed By: @billf

Differential Revision: D1016901
2013-10-18 22:11:41 -07:00
Jan Oravec 37ba715ec4 Removed legacy unused callbacks
Remove unused asio_set_on_{started,failed}_callback.

Reviewed By: alexsuhan

Differential Revision: D1016805
2013-10-18 22:11:37 -07:00
seanc 22bc89ab93 Fix CMake warning
Summary: Latest CMake on OS X with brew surfaced this warning and that
this check was not doing what it was originally intended to do.
2013-10-18 20:01:30 -07:00
Jordan DeLong 094ba8ed5b Initialize m_type when ignoring isTypeVar TypeConstraints
This diff shouldn't change behavior at all; it just
initializes these values so that if you call fullName() on a
TypeConstraint where isTypeVar is true you get a predicatable result.

Reviewed By: @dariorussi

Differential Revision: D1015647
2013-10-17 20:27:25 -07:00
Jordan DeLong be934dc214 Modify test/quick/verify-param-type.php to fail in repo mode; disable it
This test is testing that we don't assume that a successful
parameter type hint implies anything about the type of the parameter,
but we explicitly do this in repo mode.

Reviewed By: @dariorussi

Differential Revision: D1015116
2013-10-17 20:27:25 -07:00
Jordan DeLong 250a811e2b Fix bytecode spec for BareThis
It can push null.

Reviewed By: @swtaarrs

Differential Revision: D1015095
2013-10-17 20:27:25 -07:00
Jordan DeLong 94a523a232 Tweak the format of TypeConstraint::fullName() for !isExtended()
This is currently only used to print the name of a type
constraint when an extended type hint is failing.  I'm using it for
tracing in another context, so I want to it to print different things
for "?Foo" vs "Foo $x = null" hints.

Reviewed By: @dariorussi

Differential Revision: D1014903
2013-10-17 20:27:24 -07:00
Jordan DeLong 1db1c1c0b9 Generate StaticArr for constant arrays
Adding Type::StaticArr was breaking the simplification logic for
OpSame, since it was checking for precise equality of types.

Reviewed By: @edwinsmith

Differential Revision: D719215
2013-10-17 20:27:24 -07:00
Jordan DeLong e7ab1d6c48 Some cleanup to TypeConstraint, expose the DataType/MetaType fields
I need access to the DataType field, and accessing metaType()
directly is more convenient than going through the isFoo functions
(and if you use switch it also means we can get warnings when people
add new metatypes).  Some cleanup along the way (e.g. pull
equivDataTypes out of there, group related members a little more,
etc).

Reviewed By: @dariorussi

Differential Revision: D1014535
2013-10-17 20:27:24 -07:00
Jordan DeLong 72a86a583a Fix a bug in TypeConstraint::isSoft
This function returned true if the type had isHHType(), which
it will always if EnableHipHopSyntax=1.  The flag was 0x16 instead of
0x10, and isSoft() just does return m_flags & Soft.

Reviewed By: @dariorussi

Differential Revision: D1014812
2013-10-17 20:27:24 -07:00
Eugene Letuchy bbc51c4a89 make 'abstract async' syntax error only behind !(whole program)
... so that production builds (perflab) work for a bit.
 Reverts commit ab87fc08420d56555ade1c5eec1ff4411edf5804.

Reviewed By: @swtaarrs

Differential Revision: D1013669
2013-10-17 20:27:23 -07:00
Andrey Bannikov 7a6a9aa1eb when performing 'out' command, step over next popr
When the 'out' command is issued and flow is inside a called function that will not return value, debugging should continue from the line following the call. We do that by stepping over a PopR if we encounter one after performing 'out'.

Reviewed By: @hermanventer

Differential Revision: D1016061
2013-10-17 20:27:23 -07:00
bsimmers 345aad19ea Fix catch trace issue with inline collection ops
The CheckBounds instruction used to emit two calls to the throw
helper, and we'd try to reference the same catch trace twice. I considered
supporting that but it's faster to just do a single unsigned comparison
anyway. This diff also fixes a case where we'd incorrectly think we were
specializing SetM with a Pair base.

Reviewed By: @jdelong

Differential Revision: D1013820
2013-10-17 20:27:23 -07:00
Stephen Chen dbd5b4d531 instead of rate, use sum to track hhvm's response code
We added rate for tracking hhvm's response code. But this is not a good stats to
use. Rate is defined as (sum / time period). So that means, if we have 59 500s
in the last 1 minute, the rate will still be 0.

Switching to sum will give us better precision and better metric.

This will make it easier for us to monitor the RC roll out.

Reviewed By: jmarch

Differential Revision: D1015363
2013-10-17 20:27:22 -07:00
Brett Simmers 25c9bf57ef Clean up http header initialization code
This diff fixes a few things I ran into while debugging an unrelated
issue:
- The request counter was global and not synchronized. It's not critical for
  there to be no races on this counter but it's not a perf-sensitive path so I
  can't see any reason to not fix it.
- The HeaderMangle warning is now more informative, including the entire set of
  received headers. It also prints at most one warning per request, though that
  warning may have multiple lines.
- The code to actually put the headers in $_SERVER['HTTP_*'] was looping over
  the vector of values for each header, assigning each one to the same key in
  $_SERVER. Unless I'm missing something really subtle, this is equivalent to
  just assigning the final element of the vector to the key, so I changed it to
  do that.

Reviewed By: @markw65

Differential Revision: D1010458
2013-10-17 20:27:22 -07:00
Edwin Smith ba6bc49e63 Remove dead method IRInstruction::setNumSrcs()
Reviewed By: @ottoni

Differential Revision: D1015523
2013-10-17 20:27:22 -07:00
Edwin Smith 1649218428 Rename Jmp_ to Jmp
Reviewed By: @ottoni

Differential Revision: D1015484
2013-10-17 20:27:22 -07:00
bsimmers ccb3ac68b0 Clean up the runtime option to disable refcount opts
It wasn't disabling everything it should.

Reviewed By: @jdelong

Differential Revision: D1013355
2013-10-17 20:27:21 -07:00
Alex Malyshev 73dfe7a892 Emit an error message when our PHP systemlib doesn't compile
Fixes the terrible "Undefined interface: arrayaccess" error message

Reviewed By: @jdelong

Differential Revision: D1014257
2013-10-17 20:27:21 -07:00
Edwin Smith 2a5577435f Don't print lifetime in codegen
This removes some coupling between linear-scan.cpp and codegen.
The lifetime information is based on the linear numbering that
only matters to linear scan.

Reviewed By: @swtaarrs

Differential Revision: D1013874
2013-10-17 20:27:21 -07:00
Jordan DeLong d2762c0a48 Rename LMANY pop descriptor to MMANY
I think this dates back to a time when member instructions
had arg types called "LA", which eventually got renamed, and now "LA"
means local argument.  Rename this.

Reviewed By: @markw65

Differential Revision: D1011765
2013-10-17 20:27:20 -07:00
Jordan DeLong 1d445d8ed7 Add a U stack flavor, for Uninit nulls on the eval stack
The NullUninit opcode implies that cells on the stack can be
uninit pretty much anywhere, but in practice we only need this for
default arguments to FCallBuiltin.  Make that a bytecode invariant
using stack flavors.

Reviewed By: @markw65

Differential Revision: D1011749
2013-10-17 20:27:20 -07:00
Jordan DeLong c4d323fac8 Add AssertT{L,Stk} opcodes, currently for debugging purposes
They assert in debug builds in the interpreter, and cause the
JIT to assume the types are as specified.  I only added a few types
based on my current needs; we can add more as needed, and I didn't
hook it up to any of our region selection or tracelet analyzer stuff.

Reviewed By: @markw65

Differential Revision: D1011114
2013-10-17 20:27:14 -07:00
Bert Maher 60d0e7dad9 Print function in dot output of CFG trace
It's nice to look at profiled CFG's with TRACE=pgo:5.  This
makes it easier to find which one you want to look at.

Reviewed By: @jdelong

Differential Revision: D1013062
2013-10-17 20:27:13 -07:00
Alan Frindell f68fad38d2 make test_server generic
I had previously copied this file for ProxygenServer.  Instead, make it generic so it can test any server.  The "TestServer" test is now "TestLibEventServer".  The new proxygen test includes this source file (as well as main.cpp), so they could perhaps be a library.  I made two tests virtual because the current proxygen instantiation can't pass them.

Reviewed By: @markw65

Differential Revision: D1004360
2013-10-17 20:27:13 -07:00
Alan Frindell ebe1575c98 refactor socket takeover using compostion
Refactor the takeover logic to not be libevent specific, so it can be reused for ProxygenServer.  Creates a takeover agent which handles the socket takeover procedure and ultimately hands off an fd for the caller to use.

Note: it seems to me that the old LibEventServerWithTakeover::stop() had a concurrency bug, because it accessed the eventBase outside of the dispatcher thread.

Reviewed By: @markw65

Differential Revision: D1004326
2013-10-17 20:27:03 -07:00
Alan Frindell d27ddec787 Refactor server fd inheritance using composition
Collapsing the *WithFd functionality directly into LibEventServer.  ProxygenServer will mirror this capability.  Also changed the LibEventServer ctor to take a ServerOptions parameter.

Reviewed By: @markw65

Differential Revision: D1004307
2013-10-17 18:50:03 -07:00
mwilliams 8ea8e65c21 Fix TranslatorX64::m_mode
We need to ensure that m_mode is reset after each
translation attempt.

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

Reviewed By: @swtaarrs

Differential Revision: D1012330
2013-10-17 18:49:54 -07:00
Jordan DeLong 964a37d43f Remove simplifier case for CheckInitMem
This shouldn't be here, since we don't know what can change
memory locations.

Reviewed By: @swtaarrs

Differential Revision: D1012639
2013-10-17 18:49:42 -07:00
Owen Yamauchi 3680a85130 Miscellaneous ARM fixes to whittle down failure count
- Fix some of the tracelet-guard tests to actually be testing/comparing
  the right thing. I wasn't paying enough attention to byte vs. word
  loads before.

- Don't call EmitLiteralPool unless there are literals. Even if there
  are no literals, if you call that function, vixl emits a "marker"
  instruction so it knows how big the pool is, but that's not needed.

- Add support for stack-chasing through interp-ones of FPushCtor and
  FPushCtorD. Without this, we assert-fail when anything consumes the
  output type of one of these bytecodes, because we've forgotten that
  the output type is Obj.

With this, 180 tests in test/quick fail. The lion's share of them are
due to unimplemented service requests, but there are a few crashes too.
I'll probably go after the unimplemented service requests next.

Reviewed By: @jdelong

Differential Revision: D1009911
2013-10-17 18:49:37 -07:00
Paul Tarjan 905f7e5386 log on invalid php.ini
If you screw up and put a bad config, it should tell you.

Reviewed By: @markw65

Differential Revision: D1013397
2013-10-17 18:49:11 -07:00
Paul Tarjan e3c32c5f8e change test to allow newer libxml2
In versions after 2.7.8 (the one we use) if you parse a poorly formatted xml document, it leaves the bad namespace as part of the node name. In this test, that means it was looking for a function named `ns1:sum`.

I'm making the xml document better formatted. As far as I can tell (from reading their code), zend has this same behavior. They don't have a test with a poorly formatted input.

Here is my cpp test the behaves differently on 2.7.8 and 2.8.0

  #include <libxml/parserInternals.h>
  #include <string.h>
  int main() {
    const char* buf = "<ns1:sum>1</ns1:sum>";
    xmlParserCtxtPtr ctxt = xmlCreateMemoryParserCtxt(buf, strlen(buf));
    ctxt->sax->error = NULL;
    xmlParseDocument(ctxt);
    printf("%s\n", ctxt->myDoc->children->name);
    xmlFreeParserCtxt(ctxt);
  }

compiled with

  /usr/include/libxml2 a.cpp -lxml2 && ./a.out

Reviewed By: @markw65

Differential Revision: D1013435
2013-10-17 18:49:07 -07:00
Paul Tarjan 283579ef6a better empty file warning
Many people have asked what the message you get when you run `hhvm` is. I was thinking of making a real usage thing. Anyone have an idea for the most common use cases? What I have here is better than nothing.

I'm sure there is some fancy C++-ism so I don't need that stupid extra boolean constructor. Input welcome.

Reviewed By: @markw65

Differential Revision: D1013406
2013-10-17 18:49:02 -07:00
bsimmers 2533a2193a Revert "[hphp] easy: parse error for "abstract async""
This reverts commit 061bcc66ac0710fc639cc8c936b9cf68ce45cdf6.

Reviewed By: @elgenie
2013-10-17 18:48:58 -07:00
Paul Tarjan 45fa5837fc don't hardcode name in test
this test has nothing to do with the stderr, so lets not require that we can write to some random file

Reviewed By: @markw65

Differential Revision: D1013443
2013-10-17 18:48:45 -07:00
James Miller 467c1a8024 Make the embedded systemlib a dependency of the binary 2013-10-17 15:54:38 -07:00
Sara Golemon b04bae25f3 Merge pull request #1184 from PocketRent/fix-install
Fix broken make install behaviour
2013-10-17 15:36:08 -07:00
Sean Cannella 8f574018aa Merge pull request #1185 from kandy/patch-2
Travis CI banner url update due to GitHub project name change
2013-10-17 07:32:20 -07:00
Andrii Kasian cae20c2e28 Travis CI banner path update 2013-10-17 08:40:19 +03:00
James Miller 4f3652034d Fix broken make install behaviour
CMake uses rpath to make it easier to run built executables from the build
tree without installing prerequisite libraries first. This means that when
installing, CMake will re-link the binary in order to change the rpath so
it works properly in an install. Unfortunately, it's not smart enough to know
to re-embed the systemlib section, so the installed `hhvm` binary does not
have a systemlib section and doesn't work.

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

This allows `make install` to work again.
2013-10-17 16:31:38 +13:00
Sara Golemon 75a3806bae Master is now working towards 2.3.0 2013-10-16 11:19:10 -07:00
2382 arquivos alterados com 517767 adições e 100416 exclusões
+4 -9
Ver Arquivo
@@ -1,10 +1,5 @@
*.[oad]
*.hhbc
/bin*-g
/bin*-O
/bin/*.so
/bin/hphp_options
/bin/systemlib.php
.mkdir
hphp.log
@@ -41,6 +36,8 @@ hphp.log
/hphp/runtime/ext/*.ext_hhvm.h
/hphp/runtime/ext/*/*.ext_hhvm.cpp
/hphp/runtime/ext/*/*.ext_hhvm.h
/hphp/runtime/ext/*/*/*.ext_hhvm.h
/hphp/runtime/ext/*/*/*.ext_hhvm.cpp
/hphp/runtime/ext_zend_compat/*/*.ext_hhvm.cpp
/hphp/runtime/ext_zend_compat/*/*.ext_hhvm.h
/hphp/runtime/ext_zend_compat/*/*/*.ext_hhvm.cpp
@@ -55,10 +52,6 @@ hphp.log
/hphp/ffi/java/classes
/hphp/ffi/java/hphp_ffi_java.h
# Ignore all makefiles generated for fbcode's third-party repo
/bin/*.mk
!/bin/run.mk
CMakeFiles
CMakeCache.txt
cmake_install.cmake
@@ -68,6 +61,8 @@ install_manifest.txt
/hphp/TAGS
/hphp/third_party/libzip/libzip.dylib
# Generated makefiles
/hphp/runtime/ext_hhvm/Makefile
/hphp/test/Makefile
+3
Ver Arquivo
@@ -0,0 +1,3 @@
[submodule "hphp/submodules/folly"]
path = hphp/submodules/folly
url = git://github.com/facebook/folly.git
+1
Ver Arquivo
@@ -23,4 +23,5 @@ env:
script: hphp/hhvm/hhvm hphp/test/run $TEST_RUN_MODE
notifications:
email: false
irc: "chat.freenode.net#hhvm"
+1 -1
Ver Arquivo
@@ -21,7 +21,7 @@ CHECK_C_SOURCE_RUNS("#include <dlfcn.h>
void testfunc() {}
int main() {
testfunc();
return dyslm(0, "_testfunc") != (void*)0;
return dyslm(0, \"_testfunc\") != (void*)0;
}" LIBDL_NEEDS_UNDERSCORE)
mark_as_advanced(LIBDL_INCLUDE_DIRS LIBDL_LIBRARIES LIBDL_NEEDS_UNDERSCORE)
+31
Ver Arquivo
@@ -0,0 +1,31 @@
# folly-config.h is a generated file from autotools
# We need to do the equivalent checks here and use
# add_definitions as needed
add_definitions(-DFOLLY_NO_CONFIG=1)
INCLUDE(CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES("
extern \"C\" void (*test_ifunc(void))() { return 0; }
void func() __attribute__((ifunc(\"test_ifunc\")));
" FOLLY_IFUNC)
if (FOLLY_IFUNC)
add_definitions("-DHAVE_IFUNC=1")
endif()
set(CMAKE_REQUIRED_LIBRARIES rt)
CHECK_CXX_SOURCE_COMPILES("#include <time.h>
int main() {
clock_gettime((clockid_t)0, NULL);
return 0;
}" HAVE_CLOCK_GETTIME)
if (HAVE_CLOCK_GETTIME)
add_definitions("-DFOLLY_HAVE_CLOCK_GETTIME=1")
endif()
set(CMAKE_REQUIRED_LIBRARIES)
find_path(FEATURES_H_INCLUDE_DIR NAMES features.h)
if (FEATURES_H_INCLUDE_DIR)
include_directories("${FEATURES_H_INCLUDE_DIR}")
add_definitions("-DFOLLY_HAVE_FEATURES_H=1")
endif()
+8 -17
Ver Arquivo
@@ -1,14 +1,5 @@
if(CMAKE_COMPILER_IS_GNUCC)
INCLUDE(CheckCSourceCompiles)
CHECK_C_SOURCE_COMPILES("#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION < 40600
#error Need GCC 4.6.0+
#endif
int main() { return 0; }" HAVE_GCC_46)
if(NOT HAVE_GCC_46)
message(FATAL_ERROR "Need at least GCC 4.6")
endif()
CHECK_C_SOURCE_COMPILES("#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION < 40700
@@ -16,6 +7,10 @@ int main() { return 0; }" HAVE_GCC_46)
#endif
int main() { return 0; }" HAVE_GCC_47)
if (NOT HAVE_GCC_47)
message(FATAL_ERROR "Need at least GCC 4.7")
endif()
CHECK_C_SOURCE_COMPILES("#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION < 40800
#error Not GCC 4.8.0+
@@ -37,18 +32,14 @@ endif()
if($ENV{CXX} MATCHES "icpc")
set(CMAKE_C_FLAGS "-no-ipo -fp-model precise -wd584 -wd1418 -wd1918 -wd383 -wd869 -wd981 -wd424 -wd1419 -wd444 -wd271 -wd2259 -wd1572 -wd1599 -wd82 -wd177 -wd593 -w")
set(CMAKE_CXX_FLAGS "-no-ipo -fp-model precise -wd584 -wd1418 -wd1918 -wd383 -wd869 -wd981 -wd424 -wd1419 -wd444 -wd271 -wd2259 -wd1572 -wd1599 -wd82 -wd177 -wd593 -fno-omit-frame-pointer -ftemplate-depth-120 -Wall -Woverloaded-virtual -Wno-deprecated -w1 -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names")
set(CMAKE_CXX_FLAGS "-no-ipo -fp-model precise -wd584 -wd1418 -wd1918 -wd383 -wd869 -wd981 -wd424 -wd1419 -wd444 -wd271 -wd2259 -wd1572 -wd1599 -wd82 -wd177 -wd593 -fno-omit-frame-pointer -ftemplate-depth-180 -Wall -Woverloaded-virtual -Wno-deprecated -w1 -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names")
else()
set(GNUCC_UNINIT_OPT "")
if(HAVE_GCC_47)
set(GNUCC_UNINIT_OPT "-Wno-maybe-uninitialized")
endif()
set(GNUCC_LOCAL_TYPEDEF_OPT "")
set(GNUCC_48_OPT "")
if(HAVE_GCC_48)
set(GNUCC_LOCAL_TYPEDEF_OPT "-Wno-unused-local-typedefs")
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-120 -Wall -Woverloaded-virtual -Wno-deprecated -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names -Wno-error=array-bounds -Wno-error=switch -std=gnu++0x -Werror=format-security -Wno-unused-result -Wno-sign-compare -Wno-attributes ${GNUCC_UNINIT_OPT} ${GNUCC_LOCAL_TYPEDEF_OPT}")
set(CMAKE_CXX_FLAGS "-fno-gcse -fno-omit-frame-pointer -ftemplate-depth-180 -Wall -Woverloaded-virtual -Wno-deprecated -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names -Wno-error=array-bounds -Wno-error=switch -std=gnu++11 -Werror=format-security -Wno-unused-result -Wno-sign-compare -Wno-attributes -Wno-maybe-uninitialized ${GNUCC_48_OPT}")
endif()
if(CMAKE_COMPILER_IS_GNUCC)
+18 -16
Ver Arquivo
@@ -31,6 +31,11 @@ endif()
find_package(Boost 1.48.0 COMPONENTS system program_options filesystem regex REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
# Boost 1.49 supports a better flat_multimap, but 1.48 is good enough
if (Boost_VERSION GREATER 104899)
add_definitions("-DHAVE_BOOST1_49")
endif()
# features.h
FIND_PATH(FEATURES_HEADER features.h)
@@ -85,13 +90,10 @@ include_directories(${LIBEVENT_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES "${LIBEVENT_LIB}")
CHECK_FUNCTION_EXISTS("evhttp_bind_socket_with_fd" HAVE_CUSTOM_LIBEVENT)
if (NOT HAVE_CUSTOM_LIBEVENT)
unset(HAVE_CUSTOM_LIBEVENT CACHE)
unset(LIBEVENT_INCLUDE_DIR CACHE)
unset(LIBEVENT_LIB CACHE)
unset(LibEvent_FOUND CACHE)
message(FATAL_ERROR "Custom libevent is required with HipHop patches")
endif ()
if(HAVE_CUSTOM_LIBEVENT)
message("Using custom LIBEVENT")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_CUSTOM_LIBEVENT")
endif()
set(CMAKE_REQUIRED_LIBRARIES)
# GD checks
@@ -136,6 +138,7 @@ include_directories("${HPHP_HOME}/hphp/third_party/libmbfl/filter")
include_directories("${HPHP_HOME}/hphp/third_party/lz4")
include_directories("${HPHP_HOME}/hphp/third_party/double-conversion/src")
include_directories("${HPHP_HOME}/hphp/third_party/folly")
include_directories("${HPHP_HOME}/hphp/third_party/libzip")
# ICU
find_package(ICU REQUIRED)
@@ -302,19 +305,17 @@ if (NOT RECENT_CCLIENT)
message(FATAL_ERROR "Your version of c-client is too old, you need 2007")
endif()
CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/linkage.h" auth_gss CCLIENT_NEEDS_PAM)
if (EXISTS "${CCLIENT_INCLUDE_PATH}/linkage.c")
CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/linkage.c" ssl_onceonlyinit CCLIENT_HAS_SSL)
endif()
if (CCLIENT_NEEDS_PAM)
find_package(Libpam REQUIRED)
find_package(Libpam)
if (PAM_INCLUDE_PATH)
include_directories(${PAM_INCLUDE_PATH})
else()
add_definitions(-DSKIP_IMAP_GSS=1)
endif()
if (EXISTS "${CCLIENT_INCLUDE_PATH}/linkage.c")
CONTAINS_STRING("${CCLIENT_INCLUDE_PATH}/linkage.c" ssl_onceonlyinit CCLIENT_HAS_SSL)
endif()
if (NOT CCLIENT_HAS_SSL)
add_definitions(-DSKIP_IMAP_SSL=1)
endif()
@@ -462,6 +463,7 @@ endif()
target_link_libraries(${target} lz4)
target_link_libraries(${target} double-conversion)
target_link_libraries(${target} folly)
target_link_libraries(${target} zip_static)
target_link_libraries(${target} afdt)
target_link_libraries(${target} mbfl)
@@ -475,7 +477,7 @@ endif()
target_link_libraries(${target} ${NCURSES_LIBRARY})
target_link_libraries(${target} ${CCLIENT_LIBRARY})
if (CCLIENT_NEEDS_PAM)
if (PAM_LIBRARY)
target_link_libraries(${target} ${PAM_LIBRARY})
endif()
+40 -5
Ver Arquivo
@@ -68,17 +68,52 @@ macro(MYSQL_SOCKET_SEARCH)
endif()
endmacro()
function(embed_systemlib TARGET DEST SOURCE)
function(embed_systemlib TARGET DEST SOURCE SECTNAME)
if (APPLE)
target_link_libraries(${TARGET} -Wl,-sectcreate,__text,systemlib,${SOURCE})
target_link_libraries(${TARGET} -Wl,-sectcreate,__text,${SECTNAME},${SOURCE})
else()
add_custom_command(TARGET ${TARGET} POST_BUILD
COMMAND "objcopy"
ARGS "--add-section" "systemlib=${SOURCE}" ${DEST}
COMMENT "Embedding systemlib.php in ${TARGET}")
ARGS "--add-section" "${SECTNAME}=${SOURCE}" ${DEST}
COMMENT "Embedding ${SOURCE} in ${TARGET} as ${SECTNAME}")
endif()
# Add the systemlib file to the "LINK_DEPENDS" for the systemlib, this will cause it
# to be relinked and the systemlib re-embedded
set_property(TARGET ${TARGET} APPEND PROPERTY LINK_DEPENDS ${SOURCE})
endfunction(embed_systemlib)
function(embed_all_systemlibs TARGET DEST)
embed_systemlib(${TARGET} ${DEST} ${HPHP_HOME}/hphp/system/systemlib.php systemlib)
auto_sources(SYSTEMLIBS "ext_*.php" "RECURSE" "${HPHP_HOME}/hphp/runtime")
foreach(SLIB ${SYSTEMLIBS})
get_filename_component(SLIB_BN ${SLIB} "NAME_WE")
string(LENGTH ${SLIB_BN} SLIB_BN_LEN)
math(EXPR SLIB_BN_REL_LEN "${SLIB_BN_LEN} - 4")
string(SUBSTRING ${SLIB_BN} 4 ${SLIB_BN_REL_LEN} SLIB_EXTNAME)
string(MD5 SLIB_HASH_NAME ${SLIB_EXTNAME})
string(SUBSTRING ${SLIB_HASH_NAME} 0 12 SLIB_HASH_NAME_SHORT)
embed_systemlib(${TARGET} ${DEST} ${SLIB} "ext.${SLIB_HASH_NAME_SHORT}")
endforeach()
endfunction(embed_all_systemlibs)
# Custom install function that doesn't relink, instead it uses chrpath to change it, if
# it's available, otherwise, it leaves the chrpath alone
function(HHVM_INSTALL TARGET DEST)
get_target_property(LOC ${TARGET} LOCATION)
get_target_property(TY ${TARGET} TYPE)
if (FOUND_CHRPATH)
get_target_property(RPATH ${TARGET} INSTALL_RPATH)
if (NOT RPATH STREQUAL "RPATH-NOTFOUND")
if (RPATH STREQUAL "")
install(CODE "execute_process(COMMAND \"${CHRPATH}\" \"-d\" \"${LOC}\" ERROR_QUIET)")
else()
install(CODE "execute_process(COMMAND \"${CHRPATH}\" \"-r\" \"${RPATH}\" \"${LOC}\" ERROR_QUIET)")
endif()
endif()
endif()
install(CODE "FILE(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/${DEST}\" TYPE ${TY} FILES \"${LOC}\")")
endfunction(HHVM_INSTALL)
function(HHVM_EXTENSION EXTNAME)
list(REMOVE_AT ARGV 0)
add_library(${EXTNAME} SHARED ${ARGV})
@@ -87,5 +122,5 @@ function(HHVM_EXTENSION EXTNAME)
endfunction()
function(HHVM_SYSTEMLIB EXTNAME SOURCE_FILE)
embed_systemlib(${EXTNAME} "${EXTNAME}.so" ${SOURCE_FILE})
embed_systemlib(${EXTNAME} "${EXTNAME}.so" ${SOURCE_FILE} systemlib)
endfunction()
+30 -2
Ver Arquivo
@@ -1,9 +1,18 @@
include(Options)
if (APPLE)
# Do this until cmake has a define for ARMv8
INCLUDE(CheckCXXSourceCompiles)
CHECK_CXX_SOURCE_COMPILES("
#ifndef __AARCH64EL__
#error Not ARMv8
#endif
int main() { return 0; }" IS_AARCH64)
if (APPLE OR IS_AARCH64)
set(HHVM_ANCHOR_SYMS -Wl,-u,_register_libevent_server)
else()
set(HHVM_ANCHOR_SYMS -Wl,-uregister_libevent_server)
set(ENABLE_FASTCGI 1)
set(HHVM_ANCHOR_SYMS -Wl,-uregister_libevent_server,-uregister_fastcgi_server)
endif()
set(HHVM_LINK_LIBRARIES
@@ -14,9 +23,15 @@ set(HHVM_LINK_LIBRARIES
hphp_parser
hphp_zend
hphp_util
hphp_hhbbc
vixl neo
${HHVM_ANCHOR_SYMS})
if(ENABLE_FASTCGI)
LIST(APPEND HHVM_LINK_LIBRARIES hphp_thrift)
LIST(APPEND HHVM_LINK_LIBRARIES hphp_proxygen)
endif()
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
@@ -25,6 +40,15 @@ IF(NOT DEFINED CMAKE_PREFIX_PATH)
message(STATUS "CMAKE_PREFIX_PATH was missing, proceeding anyway")
endif()
# Look for the chrpath tool so we can warn if it's not there
find_program(CHRPATH chrpath)
IF (CHRPATH STREQUAL "CHRPATH-NOTFOUND")
SET(FOUND_CHRPATH OFF)
message(WARNING "chrpath not found, rpath will not be stripped from installed binaries")
else()
SET(FOUND_CHRPATH ON)
endif()
LIST(APPEND CMAKE_PREFIX_PATH "$ENV{CMAKE_PREFIX_PATH}")
if(APPLE)
@@ -96,6 +120,10 @@ if(APPLE)
add_definitions(-DMACOSX_DEPLOYMENT_TARGET=10.6)
endif()
if(ENABLE_FASTCGI)
add_definitions(-DENABLE_FASTCGI=1)
endif ()
# enable the OSS options if we have any
add_definitions(-DHPHP_OSS=1)
+13 -13
Ver Arquivo
@@ -1,46 +1,46 @@
# HipHop VM for PHP [![Build Status](https://travis-ci.org/facebook/hiphop-php.png?branch=master)](https://travis-ci.org/facebook/hiphop-php)
# HHVM [![Build Status](https://travis-ci.org/facebook/hhvm.png?branch=master)](https://travis-ci.org/facebook/hhvm)
HipHop VM (HHVM) is a new open-source virtual machine designed for executing programs written in PHP. HHVM uses a just-in-time compilation approach to achieve superior performance while maintaining the flexibility that PHP developers are accustomed to. HipHop VM (and before it HPHPc) has realized > 5x increase in throughput for Facebook compared with Zend PHP 5.2.
HHVM (aka the HipHop Virtual Machine) is a new open-source virtual machine designed for executing programs written in PHP. HHVM uses a just-in-time compilation approach to achieve superior performance while maintaining the flexibility that PHP developers are accustomed to. To date, HHVM (and its precedessor HPHPc before it) has realized over a 9x increase in web request throughput and over a 5x reduction in memory consumption for Facebook compared with the Zend PHP 5.2 engine + APC.
HipHop is most commonly run as a standalone server, replacing both Apache and modphp.
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.
## FAQ
Our [FAQ](https://github.com/facebook/hiphop-php/wiki/FAQ) has answers to many common questions about HHVM, from [general questions](https://github.com/facebook/hiphop-php/wiki/FAQ#general) to questions geared towards those that want to [use](https://github.com/facebook/hiphop-php/wiki/FAQ#users) or [contribute](https://github.com/facebook/hiphop-php/wiki/FAQ#contributors) to HHVM.
Our [FAQ](https://github.com/facebook/hhvm/wiki/FAQ) has answers to many common questions about HHVM, from [general questions](https://github.com/facebook/hhvm/wiki/FAQ#general) to questions geared towards those that want to [use](https://github.com/facebook/hhvm/wiki/FAQ#users) or [contribute](https://github.com/facebook/hhvm/wiki/FAQ#contributors) to HHVM.
## Installing
You can install a [prebuilt package](https://github.com/facebook/hiphop-php/wiki#installing-pre-built-packages-for-hhvm) or [compile from source](https://github.com/facebook/hiphop-php/wiki#building-hhvm).
You can install a [prebuilt package](https://github.com/facebook/hhvm/wiki#installing-pre-built-packages-for-hhvm) or [compile from source](https://github.com/facebook/hhvm/wiki#building-hhvm).
## Running
You can run standalone programs just by passing them to hhvm: `hhvm my_script.php`.
HipHop bundles in a webserver. So if you want to run on port 80 in the current directory:
HHVM bundles in a webserver. So if you want to run on port 80 in the current directory:
```
sudo hhvm -m server
```
For anything more complicated, you'll want to make a [config.hdf](https://github.com/facebook/hiphop-php/wiki/Runtime-options#server) and run `sudo hhvm -m server -c config.hdf`.
For anything more complicated, you'll want to make a [config.hdf](https://github.com/facebook/hhvm/wiki/Runtime-options#server) and run `sudo hhvm -m server -c config.hdf`.
## Contributing
We'd love to have your help in making HipHop better.
We'd love to have your help in making HHVM better.
Before changes can be accepted a [Contributor License Agreement](http://developers.facebook.com/opensource/cla) ([pdf](https://github.com/facebook/hiphop-php/raw/master/hphp/doc/FB_Individual_CLA.pdf) - print, sign, scan, link) must be signed.
Before changes can be accepted a [Contributor License Agreement](http://developers.facebook.com/opensource/cla) ([pdf](https://github.com/facebook/hhvm/raw/master/hphp/doc/FB_Individual_CLA.pdf) - print, sign, scan, link) must be signed.
If you run into problems, please open an [issue](http://github.com/facebook/hiphop-php/issues), or better yet, [fork us and send a pull request](https://github.com/facebook/hiphop-php/pulls). Join us on [#hhvm on freenode](http://webchat.freenode.net/?channels=hhvm).
If you run into problems, please open an [issue](http://github.com/facebook/hhvm/issues), or better yet, [fork us and send a pull request](https://github.com/facebook/hhvm/pulls). Join us on [#hhvm on freenode](http://webchat.freenode.net/?channels=hhvm).
If you want to help but don't know where to start, try fixing some of the [Zend tests that don't pass](hphp/test/zend/bad). You can run them with [hphp/test/run](hphp/test/run). When they work, move them to [zend/good](hphp/test/zend/good) and send a pull request.
All the open issues tagged [Zend incompatibility](https://github.com/facebook/hiphop-php/issues?labels=zend+incompatibility&page=1&state=open) are real issues reported by the community in existing PHP code and [frameworks](https://github.com/facebook/hiphop-php/wiki/OSS-PHP-Frameworks-Unit-Testing:-General) that could use some attention. Please add appropriate test cases as you make changes; see [here](hphp/test) for more information. Travis-CI is integrated with this GitHub project and will provide test results automatically on all pulls.
All the open issues tagged [Zend incompatibility](https://github.com/facebook/hhvm/issues?labels=zend+incompatibility&page=1&state=open) are real issues reported by the community in existing PHP code and [frameworks](https://github.com/facebook/hhvm/wiki/OSS-PHP-Frameworks-Unit-Testing:-General) that could use some attention. Please add appropriate test cases as you make changes; see [here](hphp/test) for more information. Travis-CI is integrated with this GitHub project and will provide test results automatically on all pulls.
## License
HipHop VM is licensed under the PHP and Zend licenses except as otherwise noted.
HHVM is licensed under the PHP and Zend licenses except as otherwise noted.
## Reporting Crashes
See [Reporting Crashes](https://github.com/facebook/hiphop-php/wiki/Reporting-Crashes) for helpful tips on how to report crashes in an actionable manner.
See [Reporting Crashes](https://github.com/facebook/hhvm/wiki/Reporting-Crashes) for helpful tips on how to report crashes in an actionable manner.
-1
Ver Arquivo
@@ -1 +0,0 @@
This file just exists to keep the bin/ directory in git.
+27 -4
Ver Arquivo
@@ -22,10 +22,14 @@ fi
export CMAKE_PREFIX_PATH=`/bin/pwd`/..
export HPHP_HOME=`/bin/pwd`
# install python-software-properties before trying to add a PPA
sudo apt-get -y update
sudo apt-get install -y python-software-properties
# install apt-fast to speedup later dependency installation
sudo add-apt-repository -y ppa:apt-fast/stable
sudo apt-get update
sudo apt-get install apt-fast
sudo apt-get -y update
sudo apt-get -y install apt-fast
# install the actual dependencies
sudo apt-fast -y update
@@ -33,8 +37,8 @@ sudo apt-fast -y install git-core cmake g++ libboost1.48-dev libmysqlclient-dev
libxml2-dev libmcrypt-dev libicu-dev openssl build-essential binutils-dev \
libcap-dev libgd2-xpm-dev zlib1g-dev libtbb-dev libonig-dev libpcre3-dev \
autoconf libtool libcurl4-openssl-dev libboost-regex1.48-dev libboost-system1.48-dev \
libboost-program-options1.48-dev libboost-filesystem1.48-dev wget memcached \
libreadline-dev libncurses-dev libmemcached-dev libbz2-dev \
libboost-program-options1.48-dev libboost-filesystem1.48-dev libboost-thread1.48-dev \
wget memcached libreadline-dev libncurses-dev libmemcached-dev libbz2-dev \
libc-client2007e-dev php5-mcrypt php5-imagick libgoogle-perftools-dev \
libcloog-ppl0 libelf-dev libdwarf-dev libunwind7-dev subversion &
@@ -43,6 +47,9 @@ git clone git://github.com/bagder/curl.git --quiet &
svn checkout http://google-glog.googlecode.com/svn/trunk/ google-glog --quiet &
wget http://www.canonware.com/download/jemalloc/jemalloc-3.0.0.tar.bz2 --quiet &
# init submodules
git submodule update --init
# wait until all background processes finished
FAIL=0
@@ -60,6 +67,22 @@ else
exit 100
fi
# Leave this install till after the main parallel package install above
# since it adds a non-12.04 package repo and we don't want to
# pull EVERYTHING in, just the newer gcc compiler (and toolchain)
GCC_VER=4.7
if [ "x${TRAVIS}" != "x" ]; then
GCC_VER=4.8
fi
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt-get -y update
sudo apt-get -y install gcc-${GCC_VER} g++-${GCC_VER}
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_VER} 60 \
--slave /usr/bin/g++ g++ /usr/bin/g++-${GCC_VER}
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.6 40 \
--slave /usr/bin/g++ g++ /usr/bin/g++-4.6
sudo update-alternatives --set gcc /usr/bin/gcc-${GCC_VER}
# libevent
cd libevent
git checkout release-1.4.14b-stable
+26
Ver Arquivo
@@ -0,0 +1,26 @@
# HHVM build results
*.hhbc
*.[oa]
/hhvm/hhvm
/hhvm/hphp
# vim swapfiles
.*.swp
.*.swo
# tags files
*/tags
*/TAGS
# logs
*.log
# git patch files
*.diff
# OS X
.DS_Store
._.DS_Store
# gdb
.gdb_history
+11 -46
Ver Arquivo
@@ -16,44 +16,14 @@
#
include(HPHPSetup)
include(FollySetup)
# HHVM Build
SET(USE_HHVM TRUE)
SET(ENV{HHVM} 1)
ADD_DEFINITIONS("-DHHVM -DHHVM_BINARY=1 -DHHVM_PATH=\\\"${HPHP_HOME}/hphp/hhvm/hhvm\\\"")
set(RECURSIVE_SOURCE_SUBDIRS runtime/base runtime/debugger runtime/eval runtime/ext runtime/server runtime/vm)
foreach (dir ${RECURSIVE_SOURCE_SUBDIRS})
auto_sources(files "*.cpp" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
list(APPEND CXX_SOURCES ${files})
auto_sources(files "*.c" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
list(APPEND C_SOURCES ${files})
auto_sources(files "*.S" "RECURSE" "${CMAKE_CURRENT_SOURCE_DIR}/${dir}")
list(APPEND ASM_SOURCES ${files})
endforeach(dir ${RECURSIVE_SOURCE_SUBDIRS})
if(NOT LINUX)
add_definitions(-DNO_HARDWARE_COUNTERS)
list(REMOVE_ITEM CXX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/runtime/vm/debug/elfwriter.cpp)
endif()
# Not working with off-the-shelf libevent
list(REMOVE_ITEM CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/runtime/server/server-name-indication.cpp")
# remove ext_hhvm, and anything in a test folder
foreach (file ${CXX_SOURCES})
if (${file} MATCHES "ext_hhvm")
list(REMOVE_ITEM CXX_SOURCES ${file})
endif()
if (${file} MATCHES "/test/")
list(REMOVE_ITEM CXX_SOURCES ${file})
endif()
endforeach(file ${CXX_SOURCES})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")
add_subdirectory(tools/bootstrap)
add_subdirectory(third_party/libafdt)
add_subdirectory(third_party/libmbfl)
@@ -62,19 +32,11 @@ add_subdirectory(third_party/timelib)
add_subdirectory(third_party/lz4)
add_subdirectory(third_party/double-conversion)
add_subdirectory(third_party/folly)
ADD_LIBRARY(hphp_runtime_static STATIC
${CXX_SOURCES} ${C_SOURCES} ${ASM_SOURCES})
SET_TARGET_PROPERTIES(hphp_runtime_static PROPERTIES OUTPUT_NAME "hphp_runtime")
SET_TARGET_PROPERTIES(hphp_runtime_static PROPERTIES PREFIX "lib")
SET_TARGET_PROPERTIES(hphp_runtime_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>")
hphp_link(hphp_runtime_static)
add_dependencies(hphp_runtime_static hphp_parser)
add_subdirectory("tools/bootstrap")
add_subdirectory(third_party/libzip)
if(ENABLE_FASTCGI)
add_subdirectory(third_party/ti)
add_subdirectory(third_party/thrift)
endif()
add_subdirectory(vixl)
add_subdirectory(neo)
@@ -82,11 +44,14 @@ add_subdirectory(parser)
add_subdirectory(zend)
add_subdirectory(util)
add_subdirectory(hhbbc)
add_subdirectory(compiler)
add_subdirectory(runtime)
add_subdirectory(runtime/ext_hhvm)
add_subdirectory(hhvm)
add_subdirectory(system)
add_subdirectory(hhvm)
if (NOT "$ENV{HPHP_NOTEST}" STREQUAL "1")
add_subdirectory(test)
endif ()
+3 -2
Ver Arquivo
@@ -1,8 +1,9 @@
Next release
- <cool stuff goes here>
- support date.timezone in ini files
- implement fileinfo
- special comparisons for DateTime
"Sausage" 14-Oct-2013
- Fixed issue that caused memory_get_usage to report double the actual usage.
- Direct invocation of callable arrays: $f = [$cls_or_instance, 'method']; $f()
- ASAN clean
- Support dynamically loadable extensions
+8 -13
Ver Arquivo
@@ -66,7 +66,7 @@
#include "hphp/compiler/analysis/live_dict.h"
#include "hphp/compiler/analysis/ref_dict.h"
#include "hphp/runtime/base/builtin-functions.h"
#include "hphp/runtime/vm/runtime.h"
#include "hphp/parser/hphp.tab.hpp"
#include "hphp/parser/location.h"
@@ -2108,7 +2108,6 @@ int AliasManager::collectAliasInfoRecur(ConstructPtr cs, bool unused) {
}
cs->clearVisited();
cs->clearChildOfYield();
StatementPtr s = dpc(Statement, cs);
if (s) {
@@ -2361,9 +2360,6 @@ int AliasManager::collectAliasInfoRecur(ConstructPtr cs, bool unused) {
case Expression::KindOfSimpleFunctionCall:
{
SimpleFunctionCallPtr sfc(spc(SimpleFunctionCall, e));
if (sfc->getName() == "hphp_create_continuation") {
m_inlineAsExpr = false;
}
sfc->updateVtFlags();
}
case Expression::KindOfDynamicFunctionCall:
@@ -2399,9 +2395,6 @@ int AliasManager::collectAliasInfoRecur(ConstructPtr cs, bool unused) {
// expressions. TODO: revisit this later
m_inlineAsExpr = false;
break;
case Expression::KindOfYieldExpression:
spc(YieldExpression, e)->getValueExpression()->setChildOfYield();
break;
case Expression::KindOfUnaryOpExpression:
if (Option::EnableEval > Option::NoEval && spc(UnaryOpExpression, e)->
getOp() == T_EVAL) {
@@ -2537,8 +2530,10 @@ public:
}
private:
#define CONSTRUCT_PARAMS(from) \
#define CONSTRUCT_EXP(from) \
(from)->getScope(), (from)->getLocation()
#define CONSTRUCT_STMT(from) \
(from)->getScope(), (from)->getLabelScope(), (from)->getLocation()
AnalysisResultConstPtr m_ar;
bool m_changed;
@@ -2611,7 +2606,7 @@ private:
ExpressionListPtr el(
new ExpressionList(
CONSTRUCT_PARAMS(target),
CONSTRUCT_EXP(target),
ExpressionList::ListKindComma));
if (target->isUnused()) {
el->setUnused(true);
@@ -2955,7 +2950,7 @@ private:
slistPtr->insertElement(
ExpStatementPtr(
new ExpStatement(
CONSTRUCT_PARAMS(slistPtr), assertion)),
CONSTRUCT_STMT(slistPtr), assertion)),
idx);
}
break;
@@ -3036,12 +3031,12 @@ private:
} else {
ExpStatementPtr newExpStmt(
new ExpStatement(
CONSTRUCT_PARAMS(branch),
CONSTRUCT_STMT(branch),
after));
IfBranchStatementPtr newBranch(
new IfBranchStatement(
CONSTRUCT_PARAMS(branch),
CONSTRUCT_STMT(branch),
ExpressionPtr(), newExpStmt));
branches->addElement(newBranch);
+22 -18
Ver Arquivo
@@ -967,11 +967,14 @@ struct OptVisitor {
AnalysisResultPtr m_ar;
unsigned m_nscope;
JobQueueDispatcher<BlockScope *, OptWorker<When> > *m_dispatcher;
JobQueueDispatcher<OptWorker<When>> *m_dispatcher;
};
template <typename When>
class OptWorker : public JobQueueWorker<BlockScope *, true, true> {
class OptWorker : public JobQueueWorker<BlockScope*,
void*,
true,
true> {
public:
OptWorker() {}
@@ -990,8 +993,8 @@ public:
acc->second += 1;
#endif /* HPHP_INSTRUMENT_PROCESS_PARALLEL */
try {
DepthFirstVisitor<When, OptVisitor > *visitor =
(DepthFirstVisitor<When, OptVisitor >*)m_opaque;
auto visitor =
(DepthFirstVisitor<When, OptVisitor>*) m_context;
{
Lock ldep(BlockScope::s_depsMutex);
Lock lstate(BlockScope::s_jobStateMutex);
@@ -1180,7 +1183,7 @@ void OptWorker<Pre>::onThreadExit() {
} \
if (threadCount <= 0) threadCount = 1; \
this->m_data.m_dispatcher = \
new JobQueueDispatcher<BlockScope *, worker >( \
new JobQueueDispatcher<worker>( \
threadCount, true, 0, false, this); \
} while (0)
@@ -1225,7 +1228,7 @@ template <typename When>
void
AnalysisResult::preWaitCallback(bool first,
const BlockScopeRawPtrQueue &scopes,
void *opaque) {
void *context) {
// default is no-op
}
@@ -1234,7 +1237,7 @@ bool
AnalysisResult::postWaitCallback(bool first,
bool again,
const BlockScopeRawPtrQueue &scopes,
void *opaque) {
void *context) {
// default is no-op
return again;
}
@@ -1299,7 +1302,7 @@ struct BIPairCmp {
template <typename When>
void
AnalysisResult::processScopesParallel(const char *id,
void *opaque /* = NULL */) {
void *context /* = NULL */) {
BlockScopeRawPtrQueue scopes;
getScopesSet(scopes);
@@ -1336,7 +1339,7 @@ AnalysisResult::processScopesParallel(const char *id,
BlockScopeRawPtrQueue enqueued;
again = dfv.visitParallel(scopes, first, enqueued);
preWaitCallback<When>(first, scopes, opaque);
preWaitCallback<When>(first, scopes, context);
#ifdef HPHP_INSTRUMENT_PROCESS_PARALLEL
{
@@ -1390,7 +1393,7 @@ AnalysisResult::processScopesParallel(const char *id,
std::cout << "Number of waiting scopes: " << numWaiting << std::endl;
#endif /* HPHP_INSTRUMENT_PROCESS_PARALLEL */
again = postWaitCallback<When>(first, again, scopes, opaque);
again = postWaitCallback<When>(first, again, scopes, context);
first = false;
} while (again);
dfv.data().stop();
@@ -1562,7 +1565,8 @@ DepthFirstVisitor<InferTypes, OptVisitor>::visitScope(BlockScopeRawPtr scope) {
template<>
bool AnalysisResult::postWaitCallback<InferTypes>(
bool first, bool again, const BlockScopeRawPtrQueue &scopes, void *opaque) {
bool first, bool again,
const BlockScopeRawPtrQueue &scopes, void *context) {
#ifdef HPHP_INSTRUMENT_TYPE_INF
std::cout << "Number of rescheduled: " <<
@@ -1668,12 +1672,12 @@ StatementPtr DepthFirstVisitor<Post, OptVisitor>::visit(StatementPtr stmt) {
return stmt->postOptimize(this->m_data.m_ar);
}
class FinalWorker : public JobQueueWorker<MethodStatementPtr> {
class FinalWorker : public JobQueueWorker<MethodStatementPtr, AnalysisResult*> {
public:
virtual void doJob(MethodStatementPtr m) {
try {
AliasManager am(1);
am.finalSetup(((AnalysisResult*)m_opaque)->shared_from_this(), m);
am.finalSetup(m_context->shared_from_this(), m);
} catch (Exception &e) {
Logger::Error("%s", e.getMessage().c_str());
}
@@ -1682,11 +1686,11 @@ public:
template<>
void AnalysisResult::preWaitCallback<Post>(
bool first, const BlockScopeRawPtrQueue &scopes, void *opaque) {
assert(!Option::ControlFlow || opaque != nullptr);
bool first, const BlockScopeRawPtrQueue &scopes, void *context) {
assert(!Option::ControlFlow || context != nullptr);
if (first && Option::ControlFlow) {
JobQueueDispatcher<FinalWorker::JobType, FinalWorker> *dispatcher
= (JobQueueDispatcher<FinalWorker::JobType, FinalWorker> *) opaque;
auto *dispatcher
= (JobQueueDispatcher<FinalWorker> *) context;
for (BlockScopeRawPtrQueue::const_iterator it = scopes.begin(),
end = scopes.end(); it != end; ++it) {
BlockScopeRawPtr scope = *it;
@@ -1710,7 +1714,7 @@ void AnalysisResult::postOptimize() {
}
if (threadCount <= 0) threadCount = 1;
JobQueueDispatcher<FinalWorker::JobType, FinalWorker> dispatcher(
JobQueueDispatcher<FinalWorker> dispatcher(
threadCount, true, 0, false, this);
processScopesParallel<Post>("PostOptimize", &dispatcher);
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+305 -54
Ver Arquivo
@@ -28,6 +28,9 @@
#include "hphp/runtime/vm/unit.h"
#include "hphp/util/hash.h"
#include <deque>
#include <utility>
namespace HPHP {
DECLARE_BOOST_TYPES(ClosureExpression);
@@ -95,6 +98,7 @@ public:
IterKind kind;
Id id;
};
#define O(name, imm, pop, push, flags) \
void name(imm);
#define NA
@@ -119,6 +123,7 @@ public:
#define AA ArrayData*
#define BA Label&
#define OA unsigned char
#define VSA std::vector<std::string>&
OPCODES
#undef O
#undef NA
@@ -139,6 +144,7 @@ public:
#undef AA
#undef BA
#undef OA
#undef VSA
private:
ConstructPtr m_node;
UnitEmitter& m_ue;
@@ -316,13 +322,246 @@ public:
class Funclet {
public:
Funclet(Thunklet* body, Label* entry) : m_body(body), m_entry(entry) {}
explicit Funclet(Thunklet* body)
: m_body(body) {
}
Thunklet* m_body;
Label* m_entry;
Label m_entry;
};
class FinallyRouter;
DECLARE_BOOST_TYPES(FinallyRouterEntry);
/*
* FinallyRouterEntry represents a single level of the unified stack
* of constructs that are meaningful from the point of view of finally
* implementation. The levels are used to keep track of the information
* such as the actions that can be taken inside a block.
*/
class FinallyRouterEntry {
public:
enum EntryKind {
// Top-level (global) context.
GlobalEntry,
// Function body / method body entry.
FuncBodyEntry,
// Entry for finally fault funclets emitted after the body of
// a function
FuncFaultEntry,
// Try block entry (begins with try ends after catches).
TryFinallyEntry,
// Finally block entry (begins after catches ends after finally)
FinallyEntry,
// Loop OR a break statement.
LoopEntry,
};
typedef Emitter::IterPair IterPair;
typedef std::vector<IterPair> IterVec;
DECLARE_BOOST_TYPES(Action);
/*
* The structure represents a code path that potentially requires
* running finally blocks. A code path has an assigned state ID that
* is used inside switch statements emitted at the end of finally
* blocks. It also has an optional label (the destination to jump
* to after all the required finally blocks are run).
*/
struct Action {
static const int k_unsetState;
explicit Action(FinallyRouter* router);
~Action();
// Manage state ID reuse.
bool isAllocated();
void allocate();
void release();
FinallyRouter* m_router;
// The target to jump to once all the necessary finally blocks
// are run.
Label m_label;
// The state ID that identifies this action inside finally switch
// statements. This is the id assigned to the "state" unnamed
// local variable.
int m_state;
};
FinallyRouterEntry(FinallyRouter* router,
EntryKind kind,
FinallyRouterEntryPtr parent);
~FinallyRouterEntry();
// Helpers used for freeing iterators when appropriate actions
// require that.
void emitIterBreak(Emitter& e,
IterVec& iters,
Label& target);
void emitIterFree(Emitter& e, IterVec& iters);
void emitIterFree(Emitter& e);
// Emission of code snippets commencing actions. Method
// emitXYZ(e, ...) should be used instead of e.XYZ(...) in
// EmitterVisitor.
void emitReturn(Emitter& e, char sym);
void emitReturnImpl(Emitter& e,
char sym,
IterVec& iters);
void emitGoto(Emitter& e, StringData* name);
void emitGotoImpl(Emitter& e,
StringData* name,
IterVec& iters);
void emitBreak(Emitter& e, int depth);
void emitBreakImpl(Emitter& e,
int depth,
IterVec& iters);
void emitContinue(Emitter& e, int depth);
void emitContinueImpl(Emitter& e,
int depth,
IterVec& iters);
// Emit the switch statement in the finally epilogue. Optimizes
// cases where there is either just a fall-through case, or where
// there is a single case other than fall-through.
void emitFinallySwitch(Emitter& e);
// Helper for emitting beginning of single case from the finally
// epilogue.
void emitCase(Emitter& e, std::vector<Label*>& cases, ActionPtr action);
void emitReturnCase(Emitter& e, std::vector<Label*>& cases, char sym);
void emitReturnCaseImpl(Emitter& e, char sym, IterVec& iters);
void emitBreakCase(Emitter& e, std::vector<Label*>& cases, int depth);
void emitBreakCaseImpl(Emitter& e, int depth, IterVec& iters);
void emitContinueCase(Emitter& e, std::vector<Label*>& cases, int depth);
void emitContinueCaseImpl(Emitter& e, int depth, IterVec& iters);
// Helper for establishing the maximal depth of break / continue
// actions that are allocated.
int getBreakContinueDepth();
// Returns the maximal break / continue depth admissable (aka the
// number of nested loops).
int getMaxBreakContinueDepth();
// Methods used for emitting different cases for the finally
// epilogue switch.
void emitGotoCase(Emitter& e, std::vector<Label*>& cases, StringData* name);
void emitGotoCaseImpl(Emitter& e, StringData* name, IterVec& iters);
void emitReturnCases(Emitter& e, std::vector<Label*>& cases);
void emitGotoCases(Emitter& e, std::vector<Label*>& cases);
void emitBreakContinueCases(Emitter& e, std::vector<Label*>& cases);
void emitAllCases(Emitter& e, std::vector<Label*>& cases);
// Methods used for collecting labels corresponding to the cases
// from the finally epilogue. All the labels are accumulated
// inside the cases array. The array is eventually passed to
// e.Switch as the immediate argument.
void collectReturnCases(std::vector<Label*>& cases);
void collectGotoCases(std::vector<Label*>& cases);
void collectBreakContinueCases(std::vector<Label*>& cases);
void collectCase(std::vector<Label*>& cases,
ActionPtr action);
void collectAllCases(std::vector<Label*>& cases);
// The number of cases to be emitted. This is a helper used in
// establishing whether one of the optimized cases can be used.
int getCaseCount();
// Methods used for allocating new finally-aware code-paths.
// When alloc is set to false, the action is merely allocated in
// memory and shared among different entries. When alloc is set to
// true, the action is additionally assigned a state ID.
ActionPtr registerReturn(StatementPtr s, char sym);
ActionPtr registerGoto(StatementPtr s, StringData* name, bool alloc);
ActionPtr registerBreak(StatementPtr s, int depth, bool alloc);
ActionPtr registerContinue(StatementPtr s, int depth, bool alloc);
// Used to indicate that a particular label is present inside
// an entry. Labels don't have corresponding actions, however
// they need to be tracked in order to handle gotos appropriately.
void registerLabel(StatementPtr s, StringData* name);
// Yield / await is not supported inside a finally block for now.
// This method throws a parse time fatal whenever appropriate.
void registerYieldAwait(ExpressionPtr e);
FinallyRouter* m_router;
EntryKind m_kind;
// Only used for loop / break kind of entries.
Id m_iterId;
bool m_iterRef;
// Because of a bug in code emission, functions sometimes have
// inconsistent return flavours. Therefore instead of a single
// return action, there need to be one return action per flavor
// used. Once the bug is removed, this code can be simplified.
std::map<char, ActionPtr> m_returnActions;
// A map of goto actions. Each goto action is identified by the
// name of the destination label.
std::map<StringData*, ActionPtr, string_data_lt> m_gotoActions;
// A map of goto labels occurrning inside the statement represented
// by this entry. This value is used for establishing whether
// a finally block needs to be executed when performing gotos.
std::set<StringData*, string_data_lt> m_gotoLabels;
// Continue actions identified by their depth.
std::map<int, ActionPtr> m_continueActions;
// Break actions identified by their depth.
std::map<int, ActionPtr> m_breakActions;
// The label denoting the beginning of a finally block inside the
// current try. Only used when the entry kind is a try statement.
Label m_finallyLabel;
// The cases that need to be included in the switch statement. Only
// used when kind is set to try statement.
// These are the actions that are invoked inside the protected region
// protected by the try represented by this entry.
std::set<ActionPtr> m_finallyCases;
// The parent entry.
FinallyRouterEntryPtr m_parent;
};
class FinallyRouter {
public:
typedef FinallyRouterEntry::EntryKind EntryKind;
FinallyRouter();
~FinallyRouter();
// The top entry on the unified stack.
FinallyRouterEntryPtr top();
// Create an entry corresponding to the passed in statement s.
// If the statement is insignificant (e.g. is an if statement),
// nullptr is returned.
FinallyRouterEntryPtr createForStatement(StatementPtr s);
// Create a global (top-level) entry.
FinallyRouterEntryPtr createGlobal(StatementPtr s);
// Create an entry for a functiob body.
FinallyRouterEntryPtr createFuncBody(StatementPtr s);
// Create an entry for a fault funclet inside a function body
FinallyRouterEntryPtr createFuncFault(StatementPtr s);
// Helper function for creating entries.
FinallyRouterEntryPtr create(StatementPtr s, EntryKind kind);
// Enter/leave the passed in entry. Note that entries sometimes need be
// to be constructed before they are entered, or need to be accessed
// after they are left. This especially applies to constructs such
// as loops and try blocks.
void enter(FinallyRouterEntryPtr);
void leave(FinallyRouterEntryPtr);
// Functions used for handling state IDs allocation.
// FIXME (#3275259): This should be moved into global / func
// body / fault funclet entries in order to optimize state
// allocation. See the task description for more details.
int allocateState();
void releaseState(int state);
// The stack of all the entered entries.
std::vector<FinallyRouterEntryPtr> m_entries;
// The state IDs currently allocated. See FIXME above.
std::set<int> m_states;
};
class EmitterVisitor {
friend class UnsetUnnamedLocalThunklet;
friend class FuncFinisher;
public:
explicit EmitterVisitor(UnitEmitter& ue);
~EmitterVisitor();
@@ -332,6 +571,7 @@ public:
void visitKids(ConstructPtr c);
void visit(FileScopePtr file);
void assignLocalVariableIds(FunctionScopePtr fs);
void assignFinallyVariableIds();
void fixReturnType(Emitter& e, FunctionCallPtr fn,
Func* builtinFunc = nullptr);
typedef std::vector<int> IndexChain;
@@ -349,7 +589,7 @@ public:
bool evalStackIsUnknown() { return m_evalStackIsUnknown; }
void popEvalStack(char symFlavor, int arg = -1, int pos = -1);
void popSymbolicLocal(Op opcode, int arg = -1, int pos = -1);
void popEvalStackLMany();
void popEvalStackMMany();
void popEvalStackMany(int len, char symFlavor);
void popEvalStackCVMany(int len);
void pushEvalStack(char symFlavor);
@@ -370,16 +610,27 @@ public:
|| isJumpTarget(m_ue.bcPos())
|| (instrFlags(getPrevOpcode()) & TF) == 0);
}
FinallyRouter& getFinallyRouter() { return m_finallyRouter; }
Id getStateLocal() {
DCHECK(m_stateLocal >= 0);
return m_stateLocal;
}
Id getRetLocal() {
DCHECK(m_retLocal >= 0);
return m_retLocal;
}
class IncludeTimeFatalException : public Exception {
public:
ConstructPtr m_node;
bool m_parseFatal;
IncludeTimeFatalException(ConstructPtr node, const char* fmt, ...)
: Exception(), m_node(node) {
: Exception(), m_node(node), m_parseFatal(false) {
va_list ap; va_start(ap, fmt); format(fmt, ap); va_end(ap);
}
virtual ~IncludeTimeFatalException() throw() {}
EXCEPTION_COMMON_IMPL(IncludeTimeFatalException);
void setParseFatal(bool b = true) { m_parseFatal = b; }
};
void pushIterScope(Id id, IterKind kind) {
@@ -437,31 +688,6 @@ private:
FuncEmitter* m_fe;
};
class ControlTargets {
public:
ControlTargets(Id itId, bool itRef, Label& brkTarg, Label& cntTarg)
: m_itId(itId), m_itRef(itRef), m_brkTarg(brkTarg), m_cntTarg(cntTarg)
{}
Id m_itId;
bool m_itRef;
Label& m_brkTarg; // Jump here for "break;" (after doing IterFree)
Label& m_cntTarg; // Jump here for "continue;"
};
class ControlTargetPusher {
public:
ControlTargetPusher(EmitterVisitor* e, Id itId, bool itRef, Label& brkTarg,
Label& cntTarg) : m_e(e) {
e->m_controlTargets.push_front(ControlTargets(itId, itRef, brkTarg,
cntTarg));
}
~ControlTargetPusher() {
m_e->m_controlTargets.pop_front();
}
private:
EmitterVisitor* m_e;
};
class ExnHandlerRegion {
public:
ExnHandlerRegion(Offset start, Offset end) : m_start(start),
@@ -480,18 +706,22 @@ private:
class FaultRegion {
public:
FaultRegion(Offset start, Offset end, Id iterId, IterKind kind)
FaultRegion(Offset start,
Offset end,
Label* func,
Id iterId,
IterKind kind)
: m_start(start)
, m_end(end)
, m_func(func)
, m_iterId(iterId)
, m_iterKind(kind)
{}
, m_iterKind(kind) {}
Offset m_start;
Offset m_end;
Label* m_func;
Id m_iterId;
IterKind m_iterKind;
Label m_func; // note: a pointer to this is handed out to the Funclet
};
class FPIRegion {
@@ -513,9 +743,6 @@ private:
int defI;
};
private:
void emitFatal(Emitter& e, const char* message);
private:
static const size_t kMinStringSwitchCases = 8;
UnitEmitter& m_ue;
@@ -542,16 +769,19 @@ private:
typedef tbb::concurrent_hash_map<const StringData*, int,
StringDataHashCompare> EmittedClosures;
static EmittedClosures s_emittedClosures;
std::deque<ControlTargets> m_controlTargets;
std::deque<Funclet> m_funclets;
std::deque<Funclet*> m_funclets;
std::map<StatementPtr, Funclet*> m_memoizedFunclets;
std::deque<ExnHandlerRegion*> m_exnHandlers;
std::deque<FaultRegion*> m_faultRegions;
std::deque<FPIRegion*> m_fpiRegions;
std::vector<Array> m_staticArrays;
std::set<std::string,stdltistr> m_hoistables;
LocationPtr m_tempLoc;
std::map<StringData*, Label, string_data_lt> m_gotoLabels;
std::vector<Label> m_yieldLabels;
FinallyRouter m_finallyRouter;
Id m_stateLocal;
Id m_retLocal;
MetaInfoBuilder m_metaInfo;
public:
bool checkIfStackEmpty(const char* forInstruction) const;
@@ -570,16 +800,11 @@ public:
void emitAGet(Emitter& e);
void emitCGetL2(Emitter& e);
void emitCGetL3(Emitter& e);
void emitPushL(Emitter& e);
void emitCGet(Emitter& e);
void emitVGet(Emitter& e);
void emitIsset(Emitter& e);
void emitIsNull(Emitter& e);
void emitIsArray(Emitter& e);
void emitIsObject(Emitter& e);
void emitIsString(Emitter& e);
void emitIsInt(Emitter& e);
void emitIsDouble(Emitter& e);
void emitIsBool(Emitter& e);
void emitIsType(Emitter& e, IsTypeOp op);
void emitEmpty(Emitter& e);
void emitUnset(Emitter& e, ExpressionPtr exp = ExpressionPtr());
void emitVisitAndUnset(Emitter& e, ExpressionPtr exp);
@@ -589,7 +814,6 @@ public:
void emitIncDec(Emitter& e, unsigned char cop);
void emitPop(Emitter& e);
void emitConvertToCell(Emitter& e);
void emitFreePendingIters(Emitter& e);
void emitConvertToCellIfVar(Emitter& e);
void emitConvertToCellOrLoc(Emitter& e);
void emitConvertSecondToCell(Emitter& e);
@@ -610,7 +834,6 @@ public:
void emitStringSwitch(Emitter& e, SwitchStatementPtr s,
std::vector<Label>& caseLabels, Label& done,
const SwitchState& state);
void emitIterBreak(Emitter& e, uint64_t n, Label& targ);
void markElem(Emitter& e);
void markNewElem(Emitter& e);
@@ -676,28 +899,55 @@ public:
bool emitCallUserFunc(Emitter& e, SimpleFunctionCallPtr node);
Func* canEmitBuiltinCall(const std::string& name, int numParams);
void emitFuncCall(Emitter& e, FunctionCallPtr node);
void emitFuncCall(Emitter& e, FunctionCallPtr node,
const char* nameOverride = nullptr,
ExpressionListPtr paramsOverride = nullptr);
void emitFuncCallArg(Emitter& e, ExpressionPtr exp, int paramId);
void emitBuiltinCallArg(Emitter& e, ExpressionPtr exp, int paramId,
bool byRef);
void emitBuiltinDefaultArg(Emitter& e, Variant& v, DataType t, int paramId);
void emitClass(Emitter& e, ClassScopePtr cNode, bool topLevel);
void emitTypedef(Emitter& e, TypedefStatementPtr);
void emitForeachListAssignment(Emitter& e, ListAssignmentPtr la,
void emitForeachListAssignment(Emitter& e,
ListAssignmentPtr la,
int vLocalId);
void emitForeach(Emitter& e, ForEachStatementPtr fe);
void emitForeach(Emitter& e,
ForEachStatementPtr fe,
FinallyRouterEntryPtr entry);
void emitRestoreErrorReporting(Emitter& e, Id oldLevelLoc);
void emitMakeUnitFatal(Emitter& e, const std::string& message);
void emitMakeUnitFatal(Emitter& e,
const char* msg,
FatalOp k = FatalOp::Runtime);
void addFunclet(Thunklet* body, Label* entry);
Funclet* addFunclet(Thunklet* body);
Funclet* addFunclet(StatementPtr stmt,
Thunklet* body);
Funclet* getFunclet(StatementPtr stmt);
void emitFunclets(Emitter& e);
struct FaultIterInfo {
Id iterId;
IterKind kind;
};
void newFaultRegion(Offset start, Offset end, Thunklet* t,
void newFaultRegion(Offset start,
Offset end,
Label* entry,
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
void newFaultRegion(StatementPtr stmt,
Offset start,
Offset end,
Label* entry,
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
void newFuncletAndRegion(Offset start,
Offset end,
Thunklet* t,
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
void newFuncletAndRegion(StatementPtr stmt,
Offset start,
Offset end,
Thunklet* t,
FaultIterInfo = FaultIterInfo { -1, KindOfIter });
void newFPIRegion(Offset start, Offset end, Offset fpOff);
void copyOverExnHandlers(FuncEmitter* fe);
@@ -717,6 +967,7 @@ public:
void emitAllHHBC(AnalysisResultPtr ar);
extern "C" {
String hphp_compiler_serialize_code_model_for(String code, String prefix);
Unit* hphp_compiler_parse(const char* code, int codeLen, const MD5& md5,
const char* filename);
Unit* hphp_build_native_func_unit(const HhbcExtFuncInfo* builtinFuncs,
+99 -67
Ver Arquivo
@@ -13,8 +13,11 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/compiler/analysis/file_scope.h"
#include <sys/stat.h>
#include "folly/ScopeGuard.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/compiler/analysis/class_scope.h"
@@ -23,7 +26,6 @@
#include "hphp/compiler/option.h"
#include "hphp/compiler/analysis/constant_table.h"
#include "hphp/compiler/analysis/function_scope.h"
#include <sys/stat.h>
#include "hphp/compiler/parser/parser.h"
#include "hphp/util/logger.h"
#include "hphp/util/util.h"
@@ -73,8 +75,7 @@ FunctionScopePtr FileScope::setTree(AnalysisResultConstPtr ar,
return createPseudoMain(ar);
}
void FileScope::cleanupForError(AnalysisResultConstPtr ar,
int line, const string &msg) {
void FileScope::cleanupForError(AnalysisResultConstPtr ar) {
for (StringToClassScopePtrVecMap::const_iterator iter = m_classes.begin();
iter != m_classes.end(); ++iter) {
BOOST_FOREACH(ClassScopePtr cls, iter->second) {
@@ -90,8 +91,17 @@ void FileScope::cleanupForError(AnalysisResultConstPtr ar,
StringToClassScopePtrVecMap().swap(m_classes);
m_pseudoMain.reset();
m_tree.reset();
}
template <class Meth>
void makeFatalMeth(FileScope& file,
AnalysisResultConstPtr ar,
const std::string& msg,
int line,
Meth meth) {
LocationPtr loc(new Location());
loc->file = m_fileName.c_str();
LabelScopePtr labelScope(new LabelScope());
loc->file = file.getName().c_str();
loc->first(line, 0);
loc->last(line, 0);
BlockScopePtr scope;
@@ -100,16 +110,30 @@ void FileScope::cleanupForError(AnalysisResultConstPtr ar,
SimpleFunctionCallPtr e(
new SimpleFunctionCall(scope, loc, "throw_fatal", false, args,
ExpressionPtr()));
e->setThrowFatal();
ExpStatementPtr exp(new ExpStatement(scope, loc, e));
StatementListPtr stmts(new StatementList(scope, loc));
meth(e);
ExpStatementPtr exp(new ExpStatement(scope, labelScope, loc, e));
StatementListPtr stmts(new StatementList(scope, labelScope, loc));
stmts->addElement(exp);
FunctionScopePtr fs = setTree(ar, stmts);
fs->setOuterScope(shared_from_this());
FunctionScopePtr fs = file.setTree(ar, stmts);
fs->setOuterScope(file.shared_from_this());
fs->getStmt()->resetScope(fs);
fs->getStmt()->setLocation(loc);
setOuterScope(const_cast<AnalysisResult*>(ar.get())->shared_from_this());
file.setOuterScope(const_cast<AnalysisResult*>(ar.get())->shared_from_this());
}
void FileScope::makeFatal(AnalysisResultConstPtr ar,
const std::string& msg,
int line) {
auto meth = [](SimpleFunctionCallPtr e) { e->setThrowFatal(); };
makeFatalMeth(*this, ar, msg, line, meth);
}
void FileScope::makeParseFatal(AnalysisResultConstPtr ar,
const std::string& msg,
int line) {
auto meth = [](SimpleFunctionCallPtr e) { e->setThrowParseFatal(); };
makeFatalMeth(*this, ar, msg, line, meth);
}
bool FileScope::addFunction(AnalysisResultConstPtr ar,
@@ -300,66 +324,73 @@ bool FileScope::insertClassUtil(AnalysisResultPtr ar,
void FileScope::analyzeIncludesHelper(AnalysisResultPtr ar) {
m_includeState = 1;
if (m_pseudoMain) {
StatementList &stmts = *getStmt();
bool hoistOnly = false;
for (int i = 0, n = stmts.getCount(); i < n; i++) {
StatementPtr s = stmts[i];
if (!s) continue;
if (s->is(Statement::KindOfClassStatement) ||
s->is(Statement::KindOfInterfaceStatement)) {
SCOPE_EXIT { m_includeState = 2; };
ClassScopeRawPtr cls(
static_pointer_cast<InterfaceStatement>(s)->getClassScope());
if (hoistOnly) {
const string &parent = cls->getOriginalParent();
if (cls->getBases().size() > (parent.empty() ? 0 : 1)) {
continue;
}
if (!parent.empty()) {
ClassScopeRawPtr c = ar->findClass(parent);
if (!c || (c->isVolatile() &&
!resolveClass(c) && !checkClass(parent))) {
continue;
}
}
if (!m_pseudoMain) return;
StatementList &stmts = *getStmt();
bool hoistOnly = false;
for (int i = 0, n = stmts.getCount(); i < n; i++) {
StatementPtr s = stmts[i];
if (!s) continue;
if (s->is(Statement::KindOfClassStatement) ||
s->is(Statement::KindOfInterfaceStatement)) {
ClassScopeRawPtr cls(
static_pointer_cast<InterfaceStatement>(s)->getClassScope());
if (hoistOnly) {
const string &parent = cls->getOriginalParent();
if (cls->getBases().size() > (parent.empty() ? 0 : 1)) {
continue;
}
if (cls->isVolatile()) {
insertClassUtil(ar, cls, true);
}
continue;
}
if (s->is(Statement::KindOfFunctionStatement)) {
FunctionScopeRawPtr func(
static_pointer_cast<FunctionStatement>(s)->getFunctionScope());
if (func->isVolatile()) m_providedDefs.insert(func);
continue;
}
if (!hoistOnly && s->is(Statement::KindOfExpStatement)) {
ExpressionRawPtr exp(
static_pointer_cast<ExpStatement>(s)->getExpression());
if (exp && exp->is(Expression::KindOfIncludeExpression)) {
FileScopeRawPtr fs(
static_pointer_cast<IncludeExpression>(exp)->getIncludedFile(ar));
if (fs && fs->m_includeState != 1) {
if (!fs->m_includeState) {
if (m_module && fs->m_privateInclude) {
BOOST_FOREACH(BlockScopeRawPtr bs, m_providedDefs) {
fs->m_providedDefs.insert(bs);
}
}
fs->analyzeIncludesHelper(ar);
}
BOOST_FOREACH(BlockScopeRawPtr bs, fs->m_providedDefs) {
m_providedDefs.insert(bs);
}
if (!parent.empty()) {
ClassScopeRawPtr c = ar->findClass(parent);
if (!c || (c->isVolatile() &&
!resolveClass(c) && !checkClass(parent))) {
continue;
}
}
}
hoistOnly = true;
if (cls->isVolatile()) {
insertClassUtil(ar, cls, true);
}
continue;
}
if (s->is(Statement::KindOfFunctionStatement)) {
FunctionScopeRawPtr func(
static_pointer_cast<FunctionStatement>(s)->getFunctionScope());
if (func->isVolatile()) m_providedDefs.insert(func);
continue;
}
if (!hoistOnly && s->is(Statement::KindOfExpStatement)) {
ExpressionRawPtr exp(
static_pointer_cast<ExpStatement>(s)->getExpression());
if (exp && exp->is(Expression::KindOfIncludeExpression)) {
FileScopeRawPtr fs(
static_pointer_cast<IncludeExpression>(exp)->getIncludedFile(ar));
if (fs && fs->m_includeState != 1) {
if (!fs->m_includeState) {
if (m_module && fs->m_privateInclude) {
BOOST_FOREACH(BlockScopeRawPtr bs, m_providedDefs) {
fs->m_providedDefs.insert(bs);
}
}
fs->analyzeIncludesHelper(ar);
}
BOOST_FOREACH(BlockScopeRawPtr bs, fs->m_providedDefs) {
m_providedDefs.insert(bs);
}
continue;
}
}
}
hoistOnly = true;
}
m_includeState = 2;
}
@@ -369,11 +400,9 @@ void FileScope::analyzeIncludes(AnalysisResultPtr ar) {
}
}
void FileScope::visit(AnalysisResultPtr ar,
void (*cb)(AnalysisResultPtr, StatementPtr, void*),
void *data)
{
void *data) {
if (m_pseudoMain) {
cb(ar, m_pseudoMain->getStmt(), data);
}
@@ -388,8 +417,11 @@ const string &FileScope::pseudoMainName() {
FunctionScopePtr FileScope::createPseudoMain(AnalysisResultConstPtr ar) {
StatementListPtr st = m_tree;
LabelScopePtr labelScope(new LabelScope());
FunctionStatementPtr f
(new FunctionStatement(BlockScopePtr(), LocationPtr(),
(new FunctionStatement(BlockScopePtr(),
labelScope,
LocationPtr(),
ModifierExpressionPtr(),
false, pseudoMainName(),
ExpressionListPtr(), TypeAnnotationPtr(),
+6 -2
Ver Arquivo
@@ -62,6 +62,7 @@ public:
IsFoldable = 0x1000,// function can be constant folded
NeedsActRec = 0x2000,// builtin function needs ActRec
AllowOverride = 0x4000,// allow override of systemlib or builtin
NeedsFinallyLocals = 0x8000,
};
typedef boost::adjacency_list<boost::setS, boost::vecS> Graph;
@@ -107,8 +108,11 @@ public:
* are the only functions a parser calls upon analysis results.
*/
FunctionScopePtr setTree(AnalysisResultConstPtr ar, StatementListPtr tree);
void cleanupForError(AnalysisResultConstPtr ar,
int line, const std::string &msg);
void cleanupForError(AnalysisResultConstPtr ar);
void makeFatal(AnalysisResultConstPtr ar,
const std::string& msg, int line);
void makeParseFatal(AnalysisResultConstPtr ar,
const std::string& msg, int line);
bool addFunction(AnalysisResultConstPtr ar, FunctionScopePtr funcScope);
bool addClass(AnalysisResultConstPtr ar, ClassScopePtr classScope);
+5
Ver Arquivo
@@ -354,6 +354,11 @@ bool FunctionScope::needsActRec() const {
return res;
}
bool FunctionScope::needsFinallyLocals() const {
bool res = (m_attribute & FileScope::NeedsFinallyLocals);
return res;
}
bool FunctionScope::mayContainThis() {
return inPseudoMain() || getContainingClass() ||
(isClosure() && !m_modifiers->isStatic());
+2
Ver Arquivo
@@ -226,6 +226,8 @@ public:
bool allowOverride() const;
void setAllowOverride();
bool needsFinallyLocals() const;
/**
* Whether this function is a runtime helper function
*/
@@ -14,42 +14,46 @@
+----------------------------------------------------------------------+
*/
#include "hphp/util/shared-memory-allocator.h"
#include "hphp/util/exception.h"
#ifndef incl_HPHP_LABEL_SCOPE_H_
#define incl_HPHP_LABEL_SCOPE_H_
#include "hphp/compiler/hphp.h"
#include "hphp/util/base.h"
#include <vector>
#include <string>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
const char *SharedMemoryManager::Name = "HPHPSharedMemory";
boost::interprocess::managed_shared_memory *
SharedMemoryManager::Segment = nullptr;
class Statement;
// just to make valgrind cleaner
class SharedMemoryManagerUninitializer {
DECLARE_BOOST_TYPES(Statement);
class LabelScope {
public:
~SharedMemoryManagerUninitializer() {
SharedMemoryManager::Reset();
class LabelInfo {
public:
LabelInfo(StatementPtr s, const std::string& name)
: m_stmt(s), m_name(name) {}
StatementPtr getStatement() const { return m_stmt; }
const std::string& getName() const { return m_name; }
private:
StatementPtr m_stmt;
std::string m_name;
};
const std::vector<LabelInfo>& getLabels() const { return m_labels; }
void addLabel(StatementPtr s, const std::string& label) {
m_labels.push_back(LabelInfo(s, label));
}
private:
std::vector<LabelInfo> m_labels;
};
static SharedMemoryManagerUninitializer s_smm_uninitializer;
void SharedMemoryManager::Init(int size, bool clean) {
try {
if (Segment == nullptr) {
if (clean) {
boost::interprocess::shared_memory_object::remove(Name);
}
Segment = new boost::interprocess::managed_shared_memory
(boost::interprocess::open_or_create, Name, size);
}
} catch (std::exception &e) {
throw Exception("%s", e.what()); // so we have stacktrace
}
}
void SharedMemoryManager::Reset() {
delete Segment;
}
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_LABEL_SCOPE_H_
+2 -1
Ver Arquivo
@@ -623,7 +623,8 @@ public:
e->setLocation(sub->getLocation());
e->setBlockScope(sub->getScope());
ExpStatementPtr exp(
new ExpStatement(sub->getScope(), sub->getLocation(), e));
new ExpStatement(sub->getScope(), sub->getLabelScope(),
sub->getLocation(), e));
sl->insertElement(exp, ix);
}
}
+1
Ver Arquivo
@@ -21,6 +21,7 @@
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/expression/expression.h"
#include "hphp/runtime/base/builtin-functions.h"
#include "hphp/runtime/vm/runtime.h"
#include <boost/format.hpp>
using namespace HPHP;
+148 -2
Ver Arquivo
@@ -14,15 +14,16 @@
+----------------------------------------------------------------------+
*/
#include <stdarg.h>
#include "hphp/compiler/code_generator.h"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/compiler/statement/statement_list.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/analysis/function_scope.h"
#include "hphp/compiler/analysis/analysis_result.h"
#include "hphp/compiler/analysis/variable_table.h"
#include "hphp/runtime/base/zend-printf.h"
#include "hphp/util/util.h"
#include "hphp/util/hash.h"
#include <boost/format.hpp>
@@ -424,3 +425,148 @@ int CodeGenerator::ClassScopeCompare::cmp(const ClassScopeRawPtr &p1,
if (d) return d;
return strcasecmp(p1->getName().c_str(), p2->getName().c_str());
}
void CodeGenerator::printObjectHeader(const std::string className,
int numProperties) {
std::string prefixedClassName;
prefixedClassName.append(m_astPrefix);
prefixedClassName.append(className);
m_astClassNames.push_back(prefixedClassName);
printf("O:%d:\"%s\":%d:{",
(int)prefixedClassName.length(), prefixedClassName.c_str(), numProperties);
}
void CodeGenerator::printObjectFooter() {
printf("}");
m_astClassNames.pop_back();
}
void CodeGenerator::printPropertyHeader(const std::string propertyName) {
auto prefixedClassName = m_astClassNames.back();
auto len = 2+prefixedClassName.length()+propertyName.length();
printf("s:%d:\"", (int)len);
*m_out << (char)0;
printf("%s", prefixedClassName.c_str());
*m_out << (char)0;
printf("%s\";", propertyName.c_str());
}
void CodeGenerator::printValue(double v) {
*m_out << "d:";
if (std::isnan(v)) {
*m_out << "NAN";
} else if (std::isinf(v)) {
if (v < 0) *m_out << '-';
*m_out << "INF";
} else {
char *buf;
if (v == 0.0) v = 0.0; // so to avoid "-0" output
vspprintf(&buf, 0, "%.*H", 14, v);
m_out->write(buf, strlen(buf));
free(buf);
}
*m_out << ';';
}
void CodeGenerator::printValue(int32_t value) {
printf("i:%d;", value);
}
void CodeGenerator::printValue(int64_t value) {
printf("i:%ld;", value);
}
void CodeGenerator::printValue(std::string value) {
printf("s:%d:\"", (int)value.length());
getStream()->write(value.c_str(), value.length());
printf("\";");
}
void CodeGenerator::printModifierVector(std::string value) {
printf("V:6:\"Vector\":1:{");
printObjectHeader("Modifier", 1);
printPropertyHeader("name");
printValue(value);
printObjectFooter();
printf("}");
}
void CodeGenerator::printTypeExpression(std::string value) {
printObjectHeader("TypeExpression", 1);
printPropertyHeader("name");
printValue(value);
printObjectFooter();
}
void CodeGenerator::printExpression(ExpressionPtr expression, bool isRef) {
if (isRef) {
printObjectHeader("UnaryOpExpression", 4);
printPropertyHeader("expression");
expression->outputCodeModel(*this);
printPropertyHeader("operation");
printValue(PHP_REFERENCE_OP);
printPropertyHeader("location");
printLocation(expression->getLocation());
printObjectFooter();
} else {
expression->outputCodeModel(*this);
}
}
void CodeGenerator::printExpressionVector(ExpressionListPtr el) {
printf("V:6:\"Vector\":%d:{", el->getCount());
if (el->getCount() > 0) {
el->outputCodeModel(*this);
}
printf("}");
}
void CodeGenerator::printExpressionVector(ExpressionPtr e) {
printf("V:6:\"Vector\":1:{");
e->outputCodeModel(*this);
printf("}");
}
void CodeGenerator::printAsBlock(StatementPtr s) {
if (s->is(Statement::KindOfBlockStatement)) {
s->outputCodeModel(*this);
} else {
printObjectHeader("BlockStatement", 2);
printPropertyHeader("statements");
if (s->is(Statement::KindOfStatementList)) {
auto sl = static_pointer_cast<StatementList>(s);
printStatementVector(sl);
} else {
printf("V:6:\"Vector\":1:{");
s->outputCodeModel(*this);
printf("}");
}
printPropertyHeader("location");
printLocation(s->getLocation());
printObjectFooter();
}
}
void CodeGenerator::printStatementVector(StatementListPtr sl) {
printf("V:6:\"Vector\":%d:{", sl->getCount());
if (sl->getCount() > 0) {
sl->outputCodeModel(*this);
}
printf("}");
}
void CodeGenerator::printLocation(LocationPtr location) {
if (location == nullptr) return;
printObjectHeader("SourceLocation", 4);
printPropertyHeader("startLine");
printValue(location->line0);
printPropertyHeader("endLine");
printValue(location->line1);
printPropertyHeader("startColumn");
printValue(location->char0);
printPropertyHeader("endColumn");
printValue(location->char1);
printObjectFooter();
}
+27
Ver Arquivo
@@ -24,12 +24,16 @@ namespace HPHP {
DECLARE_BOOST_TYPES(AnalysisResult);
DECLARE_BOOST_TYPES(Statement);
DECLARE_BOOST_TYPES(StatementList);
DECLARE_BOOST_TYPES(Construct);
DECLARE_BOOST_TYPES(BlockScope);
DECLARE_BOOST_TYPES(ClassScope);
DECLARE_BOOST_TYPES(FunctionScope);
DECLARE_BOOST_TYPES(FileScope);
DECLARE_BOOST_TYPES(LoopStatement);
DECLARE_BOOST_TYPES(Location);
DECLARE_BOOST_TYPES(Expression);
DECLARE_BOOST_TYPES(ExpressionList);
class CodeGenerator {
public:
@@ -45,6 +49,7 @@ public:
SystemCPP, // special mode for generating builtin classes
TextHHBC, // HHBC dump in human-readable format
BinaryHHBC, // serialized HHBC
CodeModel, // serialized Code Model classes
};
enum Stream {
@@ -265,12 +270,34 @@ public:
FileScopeRawPtr getLiteralScope() const {
return m_literalScope;
}
/**
* Support for printing AST nodes in PHP serialize() format.
*/
void printObjectHeader(const std::string className, int numProperties);
void printPropertyHeader(const std::string propertyName);
void printObjectFooter();
void printValue(double value);
void printValue(int32_t value);
void printValue(int64_t value);
void printValue(std::string value);
void printModifierVector(std::string value);
void printTypeExpression(std::string value);
void printExpression(ExpressionPtr expression, bool isRef);
void printExpressionVector(ExpressionListPtr el);
void printExpressionVector(ExpressionPtr e);
void printAsBlock(StatementPtr s);
void printStatementVector(StatementListPtr sl);
void printLocation(LocationPtr location);
void setAstClassPrefix(const std::string &prefix) { m_astPrefix = prefix; }
private:
std::string m_filename;
Stream m_curStream;
std::ostream *m_streams[StreamCount];
std::ostream *m_out;
Output m_output;
std::string m_astPrefix;
std::vector<std::string> m_astClassNames;
bool m_verbose;
int m_indentation[StreamCount];
+103
Ver Arquivo
@@ -0,0 +1,103 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
// This file is @generated by tools/code-model/GenerateEnums.sh
#ifndef incl_HPHP_CODE_MODEL_ENUMS_H_
#define incl_HPHP_CODE_MODEL_ENUMS_H_
namespace HPHP {
/** The kinds of operations that IBinaryOpExpressions can perform. */
enum CodeModelBinaryOperator {
PHP_AND_ASSIGN = 1,
PHP_AND = 2,
PHP_ARRAY_ELEMENT = 3,
PHP_ARRAY_PAIR = 4,
PHP_ASSIGNMENT = 5,
PHP_BOOLEAN_AND = 6,
PHP_BOOLEAN_OR = 7,
PHP_CAST = 8,
PHP_CONCAT_ASSIGN = 9,
PHP_CONCAT = 10,
PHP_DIVIDE_ASSIGN = 11,
PHP_DIVIDE = 12,
PHP_INSTANCEOF = 13,
PHP_IS_EQUAL = 14,
PHP_IS_GREATER = 15,
PHP_IS_GREATER_OR_EQUAL = 16,
PHP_IS_IDENTICAL = 17,
PHP_IS_NOT_IDENTICAL = 18,
PHP_IS_NOT_EQUAL = 19,
PHP_IS_SMALLER = 20,
PHP_IS_SMALLER_OR_EQUAL = 21,
PHP_LOGICAL_AND = 22,
PHP_LOGICAL_OR = 23,
PHP_LOGICAL_XOR = 24,
PHP_MINUS_ASSIGN = 25,
PHP_MINUS = 26,
PHP_MODULUS_ASSIGN = 27,
PHP_MODULUS = 28,
PHP_MULTIPLY_ASSIGN = 29,
PHP_MULTIPLY = 30,
PHP_OR_ASSIGN = 31,
PHP_OR = 32,
PHP_PLUS_ASSIGN = 33,
PHP_PLUS = 34,
PHP_SHIFT_LEFT_ASSIGN = 35,
PHP_SHIFT_LEFT = 36,
PHP_SHIFT_RIGHT_ASSIGN = 37,
PHP_SHIFT_RIGHT = 38,
PHP_XOR_ASSIGN = 39,
PHP_XOR = 40,
};
/** The kinds of operations that IUnaryOpExpressions can perform. */
enum CodeModelUnaryOperator {
PHP_ARRAY_CAST_OP = 1,
PHP_ARRAY_APPEND_POINT_OP = 2,
PHP_AWAIT_OP = 3,
PHP_BOOL_CAST_OP = 4,
PHP_BITWISE_NOT_OP = 5,
PHP_CLONE_OP = 6,
PHP_DYNAMIC_VARIABLE_OP = 7,
PHP_ERROR_CONTROL_OP = 8,
PHP_FLOAT_CAST_OP = 9,
PHP_INCLUDE_OP = 10,
PHP_INCLUDE_ONCE_OP = 11,
PHP_INT_CAST_OP = 12,
PHP_MINUS_OP = 13,
PHP_NOT_OP = 14,
PHP_OBJECT_CAST_OP = 15,
PHP_PLUS_OP = 16,
PHP_POST_DECREMENT_OP = 17,
PHP_POST_INCREMENT_OP = 18,
PHP_PRE_DECREMENT_OP = 19,
PHP_PRE_INCREMENT_OP = 20,
PHP_REFERENCE_OP = 21,
PHP_REQUIRE_OP = 22,
PHP_REQUIRE_ONCE_OP = 23,
PHP_STRING_CAST_OP = 24,
PHP_UNSET_CAST_OP = 25,
};
/** Enumerates the kinds of type declaration statements. */
enum CodeModelTypeKind {
PHP_CLASS = 1,
PHP_INTERFACE = 2,
PHP_TRAIT = 3,
};
}
#endif // incl_HPHP_CODE_MODEL_ENUMS_H_
+4 -3
Ver Arquivo
@@ -344,8 +344,8 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
return 1;
}
if (vm.count("version")) {
#ifdef HPHP_VERSION
#undef HPHP_VERSION
#ifdef HHVM_VERSION
#undef HHVM_VERSION
#endif
#ifdef HPHP_COMPILER_STR
@@ -358,7 +358,7 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) {
#define HPHP_COMPILER_STR "HipHop Compiler v"
#endif
#define HPHP_VERSION(v) cout << HPHP_COMPILER_STR #v << "\n";
#define HHVM_VERSION(v) cout << HPHP_COMPILER_STR #v << "\n";
#include "../version" // nolint
cout << "Compiler: " << kCompilerId << "\n";
@@ -596,6 +596,7 @@ int process(const CompilerOptions &po) {
return 1;
}
if (Option::WholeProgram || po.target == "analyze") {
Timer timer(Timer::WallTime, "analyzeProgram");
ar->analyzeProgram();
}
}
+7 -6
Ver Arquivo
@@ -166,10 +166,6 @@ public:
void clearKilled() { m_flags.killed = false; }
bool isKilled() const { return m_flags.killed; }
void setChildOfYield() { m_flags.childOfYield = true; }
void clearChildOfYield() { m_flags.childOfYield = false; }
bool isChildOfYield() const { return m_flags.childOfYield; }
BlockScopeRawPtr getScope() const { return m_blockScope; }
void setBlockScope(BlockScopeRawPtr scope) { m_blockScope = scope; }
FileScopeRawPtr getFileScope() const {
@@ -199,7 +195,8 @@ public:
}
template<typename T>
std::shared_ptr<T> Clone(std::shared_ptr<T> constr, BlockScopePtr scope) {
std::shared_ptr<T> Clone(std::shared_ptr<T> constr,
BlockScopePtr scope) {
if (constr) {
constr = constr->clone();
constr->resetScope(scope);
@@ -247,6 +244,11 @@ public:
const AstWalkerStateVec &start,
ConstructPtr endBefore, ConstructPtr endAfter);
/**
* Generates a serialized Code Model corresponding to this AST.
*/
virtual void outputCodeModel(CodeGenerator &cg) = 0;
/**
* Called when generating code.
*/
@@ -299,7 +301,6 @@ private:
unsigned killed : 1;
unsigned refCounted : 2; // high bit indicates whether its valid
unsigned inited : 2; // high bit indicates whether its valid
unsigned childOfYield : 1; // parent node is yield
} m_flags;
};
protected:
@@ -19,6 +19,7 @@
#include "hphp/compiler/expression/scalar_expression.h"
#include "hphp/compiler/analysis/variable_table.h"
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/expression/static_member_expression.h"
#include "hphp/compiler/analysis/function_scope.h"
@@ -388,6 +389,42 @@ ExpressionPtr ArrayElementExpression::unneeded() {
return Expression::unneeded();
}
///////////////////////////////////////////////////////////////////////////////
void ArrayElementExpression::outputCodeModel(CodeGenerator &cg) {
if (Option::ConvertSuperGlobals && m_global && !m_dynamicGlobal &&
getScope() && (getScope()->is(BlockScope::ProgramScope) ||
getScope()-> getVariables()->
isConvertibleSuperGlobal(m_globalName))) {
cg.printObjectHeader("SimpleVariableExpression", 2);
cg.printPropertyHeader("name");
cg.printValue(m_globalName);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
} else if (m_offset) {
cg.printObjectHeader("BinaryOpExpression", 4);
cg.printPropertyHeader("expression1");
m_variable->outputCodeModel(cg);
cg.printPropertyHeader("expression2");
cg.printExpression(m_offset, false);
cg.printPropertyHeader("operation");
cg.printValue(PHP_ARRAY_ELEMENT);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
} else {
cg.printObjectHeader("UnaryOpExpression", 4);
cg.printPropertyHeader("expression");
m_variable->outputCodeModel(cg);
cg.printPropertyHeader("operation");
cg.printValue(PHP_ARRAY_APPEND_POINT_OP);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -17,6 +17,7 @@
#include "hphp/compiler/expression/array_pair_expression.h"
#include "hphp/compiler/expression/scalar_expression.h"
#include "hphp/compiler/expression/unary_op_expression.h"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/parser/hphp.tab.hpp"
using namespace HPHP;
@@ -122,6 +123,25 @@ bool ArrayPairExpression::canonCompare(ExpressionPtr e) const {
return m_ref == a->m_ref;
}
///////////////////////////////////////////////////////////////////////////////
void ArrayPairExpression::outputCodeModel(CodeGenerator &cg) {
if (m_name) {
cg.printObjectHeader("BinaryOpExpression", 4);
cg.printPropertyHeader("expression1");
m_name->outputCodeModel(cg);
cg.printPropertyHeader("expression2");
cg.printExpression(m_value, m_ref);
cg.printPropertyHeader("operation");
cg.printValue(PHP_ARRAY_PAIR);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
} else {
cg.printExpression(m_value, m_ref);
}
return;
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -26,6 +26,7 @@
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/expression/unary_op_expression.h"
#include "hphp/parser/hphp.tab.hpp"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/analysis/class_scope.h"
#include "hphp/compiler/analysis/function_scope.h"
@@ -306,6 +307,21 @@ TypePtr AssignmentExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return inferAssignmentTypes(ar, type, coerce, m_variable, m_value);
}
///////////////////////////////////////////////////////////////////////////////
void AssignmentExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("BinaryOpExpression", 4);
cg.printPropertyHeader("expression1");
m_variable->outputCodeModel(cg);
cg.printPropertyHeader("expression2");
cg.printExpression(m_value, m_ref);
cg.printPropertyHeader("operation");
cg.printValue(PHP_ASSIGNMENT);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -16,6 +16,7 @@
#include "hphp/compiler/expression/await_expression.h"
#include "hphp/compiler/analysis/function_scope.h"
#include "hphp/compiler/code_model_enums.h"
using namespace HPHP;
@@ -82,6 +83,18 @@ TypePtr AwaitExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return Type::Variant;
}
///////////////////////////////////////////////////////////////////////////////
void AwaitExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("UnaryOpExpression", 2);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("operation");
cg.printValue(PHP_AWAIT_OP);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -21,6 +21,7 @@
#include "hphp/parser/hphp.tab.hpp"
#include "hphp/compiler/expression/scalar_expression.h"
#include "hphp/compiler/expression/constant_expression.h"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/runtime/base/complex-types.h"
#include "hphp/runtime/base/type-conversions.h"
#include "hphp/runtime/base/builtin-functions.h"
@@ -32,6 +33,7 @@
#include "hphp/compiler/expression/simple_variable.h"
#include "hphp/compiler/statement/loop_statement.h"
#include "hphp/runtime/base/tv-arith.h"
#include "hphp/runtime/vm/runtime.h"
using namespace HPHP;
@@ -911,6 +913,76 @@ TypePtr BinaryOpExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return rt;
}
///////////////////////////////////////////////////////////////////////////////
void BinaryOpExpression::outputCodeModel(CodeGenerator &cg) {
if (m_op == T_COLLECTION) {
cg.printObjectHeader("CollectionInitializerExpression", 3);
cg.printPropertyHeader("collection");
m_exp1->outputCodeModel(cg);
cg.printPropertyHeader("arguments");
cg.printExpressionVector(static_pointer_cast<ExpressionList>(m_exp2));
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
return;
}
cg.printObjectHeader("BinaryOpExpression", 4);
cg.printPropertyHeader("expression1");
m_exp1->outputCodeModel(cg);
cg.printPropertyHeader("expression2");
m_exp2->outputCodeModel(cg);
cg.printPropertyHeader("operation");
int op = 0;
switch (m_op) {
case T_PLUS_EQUAL: op = PHP_PLUS_ASSIGN; break;
case T_MINUS_EQUAL: op = PHP_MINUS_ASSIGN; break;
case T_MUL_EQUAL: op = PHP_MULTIPLY_ASSIGN; break;
case T_DIV_EQUAL: op = PHP_DIVIDE_ASSIGN; break;
case T_CONCAT_EQUAL: op = PHP_CONCAT_ASSIGN; break;
case T_MOD_EQUAL: op = PHP_MODULUS_ASSIGN; break;
case T_AND_EQUAL: op = PHP_AND_ASSIGN; break;
case T_OR_EQUAL: op = PHP_OR_ASSIGN; break;
case T_XOR_EQUAL: op = PHP_XOR_ASSIGN; break;
case T_SL_EQUAL: op = PHP_SHIFT_LEFT_ASSIGN; break;
case T_SR_EQUAL: op = PHP_SHIFT_RIGHT_ASSIGN; break;
case T_BOOLEAN_OR: op = PHP_BOOLEAN_OR; break;
case T_BOOLEAN_AND: op = PHP_BOOLEAN_AND; break;
case T_LOGICAL_OR: op = PHP_LOGICAL_OR; break;
case T_LOGICAL_AND: op = PHP_LOGICAL_AND; break;
case T_LOGICAL_XOR: op = PHP_LOGICAL_XOR; break;
case '|': op = PHP_OR; break;
case '&': op = PHP_AND; break;
case '^': op = PHP_XOR; break;
case '.': op = PHP_CONCAT; break;
case '+': op = PHP_PLUS; break;
case '-': op = PHP_MINUS; break;
case '*': op = PHP_MULTIPLY; break;
case '/': op = PHP_DIVIDE; break;
case '%': op = PHP_MODULUS; break;
case T_SL: op = PHP_SHIFT_LEFT; break;
case T_SR: op = PHP_SHIFT_RIGHT; break;
case T_IS_IDENTICAL: op = PHP_IS_IDENTICAL; break;
case T_IS_NOT_IDENTICAL: op = PHP_IS_NOT_IDENTICAL; break;
case T_IS_EQUAL: op = PHP_IS_EQUAL; break;
case T_IS_NOT_EQUAL: op = PHP_IS_NOT_EQUAL; break;
case '<': op = PHP_IS_SMALLER; break;
case T_IS_SMALLER_OR_EQUAL: op = PHP_IS_SMALLER_OR_EQUAL; break;
case '>': op = PHP_IS_GREATER; break;
case T_IS_GREATER_OR_EQUAL: op = PHP_IS_GREATER_OR_EQUAL; break;
case T_INSTANCEOF: op = PHP_INSTANCEOF; break;
default:
assert(false);
}
cg.printValue(op);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -221,6 +221,18 @@ bool ClassConstantExpression::canonCompare(ExpressionPtr e) const {
m_className == static_cast<ClassConstantExpression*>(e.get())->m_className;
}
///////////////////////////////////////////////////////////////////////////////
void ClassConstantExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ClassPropertyExpression", 2);
cg.printPropertyHeader("className");
StaticClassName::outputCodeModel(cg);
cg.printPropertyHeader("propertyName");
cg.printValue(m_varName);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -279,6 +279,19 @@ bool ClosureExpression::hasStaticLocalsImpl(ConstructPtr root) {
return false;
}
///////////////////////////////////////////////////////////////////////////////
void ClosureExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ClosureExpression", 3);
cg.printPropertyHeader("function");
m_func->outputCodeModel(cg);
cg.printPropertyHeader("capturedVariables");
cg.printExpressionVector(m_vars);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -273,6 +273,17 @@ TypePtr ConstantExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return actualType;
}
///////////////////////////////////////////////////////////////////////////////
void ConstantExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("SimpleVariableExpression", 2);
cg.printPropertyHeader("name");
cg.printValue(getNonNSOriginalName());
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -113,6 +113,26 @@ TypePtr DynamicFunctionCall::inferTypes(AnalysisResultPtr ar, TypePtr type,
return Type::Variant;
}
///////////////////////////////////////////////////////////////////////////////
void DynamicFunctionCall::outputCodeModel(CodeGenerator &cg) {
if (m_class || !m_className.empty()) {
cg.printObjectHeader("ClassMethodCallExpression", 4);
cg.printPropertyHeader("className");
StaticClassName::outputCodeModel(cg);
cg.printPropertyHeader("methodExpression");
} else {
cg.printObjectHeader("SimpleFunctionCallExpression", 3);
cg.printPropertyHeader("functionExpression");
}
m_nameExp->outputCodeModel(cg);
cg.printPropertyHeader("arguments");
cg.printExpressionVector(m_params);
cg.printPropertyHeader("location");
cg.printLocation(m_nameExp->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
void DynamicFunctionCall::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
@@ -19,6 +19,7 @@
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/analysis/variable_table.h"
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/code_model_enums.h"
using namespace HPHP;
@@ -87,6 +88,19 @@ TypePtr DynamicVariable::inferTypes(AnalysisResultPtr ar, TypePtr type,
return m_implementedType = Type::Variant;
}
///////////////////////////////////////////////////////////////////////////////
void DynamicVariable::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("UnaryOpExpression", 3);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("operation");
cg.printValue(PHP_DYNAMIC_VARIABLE_OP) ;
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -119,6 +119,21 @@ bool EncapsListExpression::canonCompare(ExpressionPtr e) const {
return m_type == el->m_type;
}
///////////////////////////////////////////////////////////////////////////////
void EncapsListExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("EncapsListExpression", 2);
cg.printPropertyHeader("delimiter");
cg.printValue(m_type);
if (m_exps) {
cg.printPropertyHeader("expressions");
cg.printExpressionVector(m_exps);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-1
Ver Arquivo
@@ -71,7 +71,6 @@ ExpressionPtr Expression::replaceValue(ExpressionPtr rep) {
rep->clearContext(AssignmentRHS);
rep = el;
}
if (isChildOfYield()) rep->setChildOfYield();
if (rep->is(KindOfSimpleVariable) && !is(KindOfSimpleVariable)) {
static_pointer_cast<SimpleVariable>(rep)->setAlwaysStash();
}
+5
Ver Arquivo
@@ -36,6 +36,7 @@
virtual ExpressionPtr clone(); \
virtual TypePtr inferTypes(AnalysisResultPtr ar, TypePtr type, \
bool coerce); \
virtual void outputCodeModel(CodeGenerator &cg); \
virtual void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
#define DECLARE_EXPRESSION_VIRTUAL_FUNCTIONS \
DECLARE_BASE_EXPRESSION_VIRTUAL_FUNCTIONS; \
@@ -349,6 +350,10 @@ public:
return isNoRemove() && m_assertedType;
}
virtual bool allowCellByRef() const {
return false;
}
static ExpressionPtr MakeConstant(AnalysisResultConstPtr ar,
BlockScopePtr scope,
LocationPtr loc,
+9 -14
Ver Arquivo
@@ -33,7 +33,6 @@ using namespace HPHP;
ExpressionList::ExpressionList(EXPRESSION_CONSTRUCTOR_PARAMETERS,
ListKind kind)
: Expression(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(ExpressionList)),
m_outputCount(-1),
m_arrayElements(false), m_collectionType(0), m_kind(kind) {
}
@@ -249,19 +248,6 @@ void ExpressionList::stripConcat() {
}
}
void ExpressionList::setOutputCount(int count) {
assert(count >= 0 && count <= (int)m_exps.size());
m_outputCount = count;
}
int ExpressionList::getOutputCount() const {
return m_outputCount < 0 ? m_exps.size() : m_outputCount;
}
void ExpressionList::resetOutputCount() {
m_outputCount = -1;
}
void ExpressionList::markParam(int p, bool noRefWrapper) {
ExpressionPtr param = (*this)[p];
if (param->hasContext(Expression::InvokeArgument)) {
@@ -478,6 +464,15 @@ bool ExpressionList::canonCompare(ExpressionPtr e) const {
m_kind == l->m_kind;
}
///////////////////////////////////////////////////////////////////////////////
void ExpressionList::outputCodeModel(CodeGenerator &cg) {
for (unsigned int i = 0; i < m_exps.size(); i++) {
ExpressionPtr exp = m_exps[i];
cg.printExpression(exp, exp?exp->hasContext(RefParameter):false);
}
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
-9
Ver Arquivo
@@ -75,14 +75,6 @@ public:
void setCollectionType(int cType);
/**
* When a function call has too many arguments, we only want to output
* max number of arguments, by limiting output count of subexpressions.
*/
void setOutputCount(int count);
int getOutputCount() const;
void resetOutputCount();
virtual bool canonCompare(ExpressionPtr e) const;
/**
@@ -97,7 +89,6 @@ private:
unsigned int checkLitstrKeys() const;
ExpressionPtrVec m_exps;
int m_outputCount;
bool m_arrayElements;
int m_collectionType;
ListKind m_kind;
@@ -283,6 +283,12 @@ TypePtr IncludeExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return UnaryOpExpression::inferTypes(ar, type, coerce);
}
///////////////////////////////////////////////////////////////////////////////
void IncludeExpression::outputCodeModel(CodeGenerator &cg) {
UnaryOpExpression::outputCodeModel(cg);
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+13
Ver Arquivo
@@ -273,6 +273,19 @@ TypePtr ListAssignment::inferTypes(AnalysisResultPtr ar, TypePtr type,
return m_array->inferAndCheck(ar, Type::Variant, false);
}
///////////////////////////////////////////////////////////////////////////////
void ListAssignment::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ListAssignmentExpression", 3);
cg.printPropertyHeader("variables");
cg.printExpressionVector(m_variables);
cg.printPropertyHeader("expression");
m_array->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -131,6 +131,29 @@ TypePtr ModifierExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return TypePtr();
}
///////////////////////////////////////////////////////////////////////////////
void ModifierExpression::outputCodeModel(CodeGenerator &cg) {
cg.printf("V:6:\"Vector\":%d:{", (int)m_modifiers.size());
for (unsigned int i = 0; i < m_modifiers.size(); i++) {
cg.printObjectHeader("Modifier", 1);
cg.printPropertyHeader("name");
switch (m_modifiers[i]) {
case T_PUBLIC: cg.printValue("public"); break;
case T_PROTECTED: cg.printValue("protected"); break;
case T_PRIVATE: cg.printValue("private"); break;
case T_STATIC: cg.printValue("static"); break;
case T_ABSTRACT: cg.printValue("abstract"); break;
case T_FINAL: cg.printValue("final"); break;
case T_ASYNC: cg.printValue("async"); break;
default:
assert(false);
}
cg.printObjectFooter();
}
cg.printf("}");
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -122,7 +122,6 @@ TypePtr NewObjectExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
if (getScope()->isFirstPass()) {
Compiler::Error(Compiler::BadConstructorCall, self);
}
m_params->setOutputCount(0);
}
m_params->inferAndCheck(ar, Type::Some, false);
}
@@ -153,6 +152,25 @@ TypePtr NewObjectExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return Type::Object;
}
///////////////////////////////////////////////////////////////////////////////
void NewObjectExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("NewObjectExpression", m_params == nullptr ? 2 : 3);
if (m_nameExp->is(Expression::KindOfScalarExpression)) {
cg.printPropertyHeader("className");
} else {
cg.printPropertyHeader("classExpression");
}
m_nameExp->outputCodeModel(cg);
if (m_params != nullptr) {
cg.printPropertyHeader("arguments");
cg.printExpressionVector(m_params);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -146,7 +146,6 @@ void ObjectMethodExpression::setInvokeParams(AnalysisResultPtr ar) {
for (int i = 0; i < m_params->getCount(); i++) {
(*m_params)[i]->inferAndCheck(ar, Type::Variant, false);
}
m_params->resetOutputCount();
}
ExpressionPtr ObjectMethodExpression::preOptimize(AnalysisResultConstPtr ar) {
@@ -278,6 +277,28 @@ TypePtr ObjectMethodExpression::inferAndCheck(AnalysisResultPtr ar,
return checkParamsAndReturn(ar, type, coerce, func, false);
}
///////////////////////////////////////////////////////////////////////////////
void ObjectMethodExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ObjectMethodCallExpression(",
m_params == nullptr ? 3 : 4);
cg.printPropertyHeader("object");
m_object->outputCodeModel(cg);
if (m_nameExp->is(Expression::KindOfScalarExpression)) {
cg.printPropertyHeader("methodName");
} else {
cg.printPropertyHeader("methodExpression");
}
m_nameExp->outputCodeModel(cg);
if (m_params != nullptr) {
cg.printPropertyHeader("arguments");
cg.printExpressionVector(m_params);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -332,6 +332,23 @@ ObjectPropertyExpression::postOptimize(AnalysisResultConstPtr ar) {
ExpressionPtr();
}
///////////////////////////////////////////////////////////////////////////////
void ObjectPropertyExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ObjectPropertyExpression(", 3);
cg.printPropertyHeader("object");
m_object->outputCodeModel(cg);
if (m_property->is(Expression::KindOfScalarExpression)) {
cg.printPropertyHeader("propertyName");
} else {
cg.printPropertyHeader("propertyExpression");
}
m_property->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -300,6 +300,45 @@ void ParameterExpression::compatibleDefault() {
}
}
///////////////////////////////////////////////////////////////////////////////
void ParameterExpression::outputCodeModel(CodeGenerator &cg) {
auto propCount = 2;
if (m_attributeList) propCount++;
if (m_modifier != 0) propCount++;
if (m_ref) propCount++;
if (m_defaultValue != nullptr) propCount++;
cg.printObjectHeader("ParameterDeclaration(", propCount);
if (m_attributeList) {
cg.printPropertyHeader("isPassedByReference");
cg.printExpressionVector(m_attributeList);
}
if (m_modifier != 0) {
cg.printPropertyHeader("modifiers");
printf("V:6:\"Vector\":1:{");
switch (m_modifier) {
case T_PUBLIC: cg.printValue("public"); break;
case T_PROTECTED: cg.printValue("protected"); break;
case T_PRIVATE: cg.printValue("private"); break;
default: assert(false);
}
printf("}");
}
if (m_ref) {
cg.printPropertyHeader("isPassedByReference");
cg.printValue(true);
}
cg.printPropertyHeader("name");
cg.printValue(m_name);
if (m_defaultValue) {
cg.printPropertyHeader("expression");
m_defaultValue->outputCodeModel(cg);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+22
Ver Arquivo
@@ -163,6 +163,28 @@ ExpressionPtr QOpExpression::unneededHelper() {
return static_pointer_cast<Expression>(shared_from_this());
}
///////////////////////////////////////////////////////////////////////////////
void QOpExpression::outputCodeModel(CodeGenerator &cg) {
if (m_expYes == nullptr) {
cg.printObjectHeader("ValueIfNullExpression", 3);
cg.printPropertyHeader("expression");
m_condition->outputCodeModel(cg);
cg.printPropertyHeader("valueIfNull");
} else {
cg.printObjectHeader("ConditionalExpression(", 4);
cg.printPropertyHeader("condition");
m_condition->outputCodeModel(cg);
cg.printPropertyHeader("valueIfTrue");
m_expYes->outputCodeModel(cg);
cg.printPropertyHeader("valueIfFalse");
}
m_expNo->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -384,6 +384,45 @@ std::string ScalarExpression::getIdentifier() const {
return "";
}
///////////////////////////////////////////////////////////////////////////////
void ScalarExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ScalarExpression", 2);
cg.printPropertyHeader("value");
switch (m_type) {
case T_CONSTANT_ENCAPSED_STRING:
case T_ENCAPSED_AND_WHITESPACE:
case T_STRING:
case T_NUM_STRING:
cg.printValue(m_value);
break;
case T_LNUMBER:
case T_COMPILER_HALT_OFFSET:
cg.printValue((int64_t)strtoll(m_value.c_str(), nullptr, 0));
break;
case T_LINE:
cg.printValue(String(m_translated).toInt64());
break;
case T_TRAIT_C:
case T_CLASS_C:
case T_NS_C:
case T_METHOD_C:
case T_FUNC_C:
cg.printValue(m_translated);
break;
case T_DNUMBER:
cg.printValue(String(m_value).toDouble());
break;
default:
assert(false);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
void ScalarExpression::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
switch (m_type) {
case T_CONSTANT_ENCAPSED_STRING:
+37 -18
Ver Arquivo
@@ -102,12 +102,17 @@ SimpleFunctionCall::SimpleFunctionCall
const std::string &name, bool hadBackslash, ExpressionListPtr params,
ExpressionPtr cls)
: FunctionCall(EXPRESSION_CONSTRUCTOR_PARAMETER_VALUES(SimpleFunctionCall),
ExpressionPtr(), name, hadBackslash, params, cls),
m_type(FunType::Unknown), m_dynamicConstant(false),
m_builtinFunction(false), m_fromCompiler(false),
m_dynamicInvoke(false), m_transformed(false), m_no_volatile_check(false),
m_safe(0), m_extra(nullptr) {
ExpressionPtr(), name, hadBackslash, params, cls)
, m_type(FunType::Unknown)
, m_dynamicConstant(false)
, m_builtinFunction(false)
, m_dynamicInvoke(false)
, m_transformed(false)
, m_changedToBytecode(false)
, m_optimizable(false)
, m_safe(0)
, m_extra(nullptr)
{
if (!m_class && m_className.empty()) {
m_dynamicInvoke = Option::DynamicInvokeFunctions.find(m_name) !=
Option::DynamicInvokeFunctions.end();
@@ -438,7 +443,7 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
}
case FunType::FBCallUserFuncSafe:
case FunType::FunctionExists:
if (!m_no_volatile_check) {
{
FunctionScopePtr func = ar->findFunction(Util::toLower(symbol));
if (func && func->isUserFunction()) {
func->setVolatile();
@@ -447,7 +452,7 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
}
case FunType::InterfaceExists:
case FunType::ClassExists:
if (!m_no_volatile_check) {
{
ClassScopePtr cls = ar->findClass(Util::toLower(symbol));
if (cls && cls->isUserClass()) {
cls->setVolatile();
@@ -518,7 +523,7 @@ void SimpleFunctionCall::analyzeProgram(AnalysisResultPtr ar) {
markRefParams(m_funcScope, m_name, canInvokeFewArgs());
}
} else if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
if (!m_fromCompiler && m_type == FunType::Unknown &&
if (m_type == FunType::Unknown &&
!m_class && !m_redeclared && !m_dynamicInvoke && !m_funcScope &&
(m_className.empty() ||
(m_classScope &&
@@ -570,7 +575,6 @@ void SimpleFunctionCall::updateVtFlags() {
m_name == "call_user_func_array" ||
m_name == "forward_static_call" ||
m_name == "forward_static_call_array" ||
m_name == "hphp_create_continuation" ||
m_name == "get_called_class") {
f->setNextLSB(true);
}
@@ -604,10 +608,6 @@ bool SimpleFunctionCall::isCallToFunction(const char *name) const {
!getClass() && getClassName().empty();
}
bool SimpleFunctionCall::isCompilerCallToFunction(const char *name) const {
return m_fromCompiler && isCallToFunction(name);
}
bool SimpleFunctionCall::isSimpleDefine(StringData **outName,
TypedValue *outValue) const {
if (!isCallToFunction("define")) return false;
@@ -957,7 +957,7 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) {
}
break;
}
if (!m_no_volatile_check && func->isUserFunction()) {
if (func->isUserFunction()) {
func->setVolatile();
}
if (!func->isVolatile() && m_type == FunType::FunctionExists) {
@@ -972,7 +972,7 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) {
for (ClassScopePtrVec::const_iterator it = classes.begin();
it != classes.end(); ++it) {
ClassScopePtr cls = *it;
if (!m_no_volatile_check && cls->isUserClass()) {
if (cls->isUserClass()) {
cls->setVolatile();
}
if (cls->isInterface()) {
@@ -996,7 +996,7 @@ ExpressionPtr SimpleFunctionCall::preOptimize(AnalysisResultConstPtr ar) {
for (ClassScopePtrVec::const_iterator it = classes.begin();
it != classes.end(); ++it) {
ClassScopePtr cls = *it;
if (!m_no_volatile_check && cls->isUserClass()) {
if (cls->isUserClass()) {
cls->setVolatile();
}
if (!cls->isInterface() && !cls->isTrait()) {
@@ -1041,7 +1041,6 @@ ExpressionPtr SimpleFunctionCall::postOptimize(AnalysisResultConstPtr ar) {
ExpressionPtr(), T_ARRAY, true));
return replaceValue(rep);
}
m_params->resetOutputCount();
}
/*
Dont do this for now. Need to take account of newly created
@@ -1274,6 +1273,26 @@ TypePtr SimpleFunctionCall::inferAndCheck(AnalysisResultPtr ar, TypePtr type,
return rtype;
}
///////////////////////////////////////////////////////////////////////////////
void SimpleFunctionCall::outputCodeModel(CodeGenerator &cg) {
if (m_class || !m_className.empty()) {
cg.printObjectHeader("ClassMethodCallExpression", 4);
cg.printPropertyHeader("className");
StaticClassName::outputCodeModel(cg);
cg.printPropertyHeader("methodName");
} else {
cg.printObjectHeader("SimpleFunctionCallExpression", 3);
cg.printPropertyHeader("functionName");
}
m_nameExp->outputCodeModel(cg);
cg.printPropertyHeader("arguments");
cg.printExpressionVector(m_params);
cg.printPropertyHeader("location");
cg.printLocation(m_nameExp->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+24 -5
Ver Arquivo
@@ -40,9 +40,14 @@ public:
bool isDefineWithoutImpl(AnalysisResultConstPtr ar);
void setValid() { m_valid = true; }
void setFromCompiler() { m_fromCompiler = true; }
void setThrowFatal() { m_type = FunType::ThrowFatal; }
int isFatalFunction() const { return m_type == FunType::ThrowFatal; }
void setThrowParseFatal() { m_type = FunType::ThrowParseFatal; }
bool isParseFatalFunction() const {
return m_type == FunType::ThrowParseFatal;
}
bool isFatalFunction() const {
return isParseFatalFunction() || m_type == FunType::ThrowFatal;
}
int isStaticCompact() const { return m_type == FunType::StaticCompact; }
// define(<literal-string>, <scalar>);
@@ -72,8 +77,21 @@ public:
void updateVtFlags();
void setLocalThis(const std::string &name) { m_localThis = name; }
bool isCallToFunction(const char *name) const;
bool isCompilerCallToFunction(const char *name) const;
void resolveNSFallbackFunc(AnalysisResultConstPtr ar, FileScopePtr fs);
void setOptimizable() {
m_optimizable = true;
}
bool isOptimizable() const {
return m_optimizable;
}
void changeToBytecode() {
m_changedToBytecode = true;
}
virtual bool allowCellByRef() const override {
return m_changedToBytecode;
}
protected:
enum class FunType {
Unknown,
@@ -93,6 +111,7 @@ protected:
GetDefinedVars,
FBCallUserFuncSafe,
ThrowFatal,
ThrowParseFatal,
ClassAlias,
};
@@ -100,11 +119,11 @@ protected:
FunType m_type;
unsigned m_dynamicConstant : 1;
unsigned m_builtinFunction : 1;
unsigned m_fromCompiler : 1;
unsigned m_invokeFewArgsDecision : 1;
unsigned m_dynamicInvoke : 1;
unsigned m_transformed : 1;
unsigned m_no_volatile_check : 1;
unsigned m_changedToBytecode : 1; // true if it morphed into a bytecode
unsigned m_optimizable : 1; // true if it can be morphed into a bytecode
int m_safe;
ExpressionPtr m_safeDef;
+11
Ver Arquivo
@@ -307,6 +307,17 @@ TypePtr SimpleVariable::inferAndCheck(AnalysisResultPtr ar, TypePtr type,
return actual;
}
///////////////////////////////////////////////////////////////////////////////
void SimpleVariable::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("SimpleVariableExpression", 2);
cg.printPropertyHeader("variableName");
cg.printValue(m_name);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -167,6 +167,20 @@ bool StaticClassName::checkPresent() {
///////////////////////////////////////////////////////////////////////////////
void StaticClassName::outputCodeModel(CodeGenerator &cg) {
if (isSelf()) {
cg.printf("self");
} else if (isParent()) {
cg.printf("parent");
} else if (isStatic()) {
cg.printf("static");
} else {
cg.printf("%s", m_origClassName.c_str());
}
}
///////////////////////////////////////////////////////////////////////////////
void StaticClassName::outputPHP(CodeGenerator &cg, AnalysisResultPtr ar) {
if (m_class) {
m_class->outputPHP(cg, ar);
@@ -56,6 +56,7 @@ protected:
std::string m_className;
void updateClassName();
void outputCodeModel(CodeGenerator &cg);
void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
private:
unsigned m_self : 1;
@@ -337,6 +337,22 @@ bool StaticMemberExpression::canonCompare(ExpressionPtr e) const {
return m_className == s->m_className;
}
///////////////////////////////////////////////////////////////////////////////
void StaticMemberExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ClassPropertyExpression", 2);
cg.printPropertyHeader("className");
StaticClassName::outputCodeModel(cg);
if (m_exp->is(Expression::KindOfScalarExpression)) {
cg.printPropertyHeader("propertyName");
} else {
cg.printPropertyHeader("propertyExpression");
}
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -20,6 +20,7 @@
#include "hphp/compiler/analysis/code_error.h"
#include "hphp/compiler/analysis/file_scope.h"
#include "hphp/compiler/statement/statement_list.h"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/compiler/analysis/function_scope.h"
@@ -567,6 +568,80 @@ ExpressionPtr UnaryOpExpression::unneededHelper() {
return static_pointer_cast<Expression>(shared_from_this());
}
///////////////////////////////////////////////////////////////////////////////
void UnaryOpExpression::outputCodeModel(CodeGenerator &cg) {
switch (m_op) {
case T_UNSET:
case T_EXIT:
case T_ARRAY:
case T_ISSET:
case T_EMPTY:
case T_EVAL: {
cg.printObjectHeader("SimpleFunctionCallExpression", 3);
std::string funcName;
switch (m_op) {
case T_UNSET: funcName = "unset"; break;
case T_EXIT: funcName = "exit"; break;
case T_ARRAY: funcName = "array"; break;
case T_ISSET: funcName = "isset"; break;
case T_EMPTY: funcName = "empty"; break;
case T_EVAL: funcName = "eval"; break;
default: break;
}
cg.printPropertyHeader("functionName");
cg.printValue(funcName);
cg.printPropertyHeader("arguments");
printf("V:6:\"Vector\":1:{");
m_exp->outputCodeModel(cg);
printf("}");
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
return;
}
default:
break;
}
cg.printObjectHeader("UnaryOpExpression", 3);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("operation");
int op = 0;
switch (m_op) {
case T_CLONE: op = PHP_CLONE_OP; break;
case T_INC:
op = m_front ? PHP_PRE_INCREMENT_OP : PHP_POST_INCREMENT_OP;
break;
case T_DEC:
op = m_front ? PHP_PRE_DECREMENT_OP : PHP_POST_DECREMENT_OP;
break;
case '+': op = PHP_PLUS_OP; break;
case '-': op = PHP_MINUS_OP; break;
case '!': op = PHP_NOT_OP; break;
case '~': op = PHP_BITWISE_NOT_OP; break;
case T_INT_CAST: op = PHP_INT_CAST_OP; break;
case T_DOUBLE_CAST: op = PHP_FLOAT_CAST_OP; break;
case T_STRING_CAST: op = PHP_STRING_CAST_OP; break;
case T_ARRAY_CAST: op = PHP_ARRAY_CAST_OP; break;
case T_OBJECT_CAST: op = PHP_OBJECT_CAST_OP; break;
case T_BOOL_CAST: op = PHP_BOOL_CAST_OP; break;
case T_UNSET_CAST: op = PHP_UNSET_CAST_OP; break;
case '@': op = PHP_ERROR_CONTROL_OP; break;
case T_INCLUDE: op = PHP_INCLUDE_OP; break;
case T_INCLUDE_ONCE: op = PHP_INCLUDE_ONCE_OP; break;
case T_REQUIRE: op = PHP_REQUIRE_OP; break;
case T_REQUIRE_ONCE: op = PHP_REQUIRE_ONCE_OP; break;
default:
assert(false);
}
cg.printValue(op);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+33
Ver Arquivo
@@ -15,10 +15,17 @@
*/
#include "hphp/compiler/expression/user_attribute.h"
#include "hphp/compiler/expression/expression_list.h"
#include "hphp/compiler/expression/unary_op_expression.h"
#include "hphp/parser/scanner.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(Expression);
DECLARE_BOOST_TYPES(ExpressionList);
DECLARE_BOOST_TYPES(UnaryOpExpression);
// constructors/destructors
UserAttribute::UserAttribute
@@ -51,6 +58,32 @@ TypePtr UserAttribute::inferTypes(AnalysisResultPtr ar, TypePtr type,
return TypePtr();
}
///////////////////////////////////////////////////////////////////////////////
void UserAttribute::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("CodeAttribute", m_exp != nullptr ? 3 : 2);
cg.printPropertyHeader("attributeName");
cg.printValue(m_name);
if (m_exp != nullptr && m_exp->is(Expression::KindOfUnaryOpExpression)) {
UnaryOpExpressionPtr u(static_pointer_cast<UnaryOpExpression>(m_exp));
if (u->getOp() == T_ARRAY) {
ExpressionPtr ex = u->getExpression();
if (ex->is(Expression::KindOfExpressionList)) {
ExpressionListPtr el(static_pointer_cast<ExpressionList>(ex));
cg.printPropertyHeader("expressions");
cg.printExpressionVector(el);
} else {
assert(false);
}
} else {
assert(false);
}
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+15 -1
Ver Arquivo
@@ -50,7 +50,6 @@ void YieldExpression::analyzeProgram(AnalysisResultPtr ar) {
if (m_keyExp) {
m_keyExp->analyzeProgram(ar);
}
m_valExp->setChildOfYield();
m_valExp->analyzeProgram(ar);
m_label.setNew();
@@ -96,6 +95,21 @@ TypePtr YieldExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
return Type::Variant;
}
///////////////////////////////////////////////////////////////////////////////
void YieldExpression::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("YieldExpression", m_keyExp != nullptr ? 3 : 2);
cg.printPropertyHeader("expression");
if (m_keyExp != nullptr) {
cg.printPropertyHeader("key");
m_keyExp->outputCodeModel(cg);
}
cg.printPropertyHeader("value");
m_valExp->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+2 -11
Ver Arquivo
@@ -118,7 +118,6 @@ bool Option::EnableHipHopExperimentalSyntax = false;
bool Option::EnableShortTags = true;
bool Option::EnableAspTags = false;
bool Option::EnableXHP = false;
bool Option::EnableFinallyStatement = false;
int Option::ParserThreadCount = 0;
int Option::GetScannerType() {
@@ -131,10 +130,7 @@ int Option::GetScannerType() {
}
int Option::InvokeFewArgsCount = 6;
bool Option::InvokeWithSpecificArgs = true;
bool Option::FlattenInvoke = true;
int Option::InlineFunctionThreshold = -1;
bool Option::UseVirtualDispatch = false;
bool Option::EliminateDeadCode = true;
bool Option::CopyProp = false;
bool Option::LocalCopyProp = true;
@@ -145,6 +141,7 @@ bool Option::VariableCoalescing = false;
bool Option::ArrayAccessIdempotent = false;
bool Option::DumpAst = false;
bool Option::WholeProgram = true;
bool Option::UseHHBBC = getenv("HHVM_HHBBC");
bool Option::RecordErrors = true;
std::string Option::DocJson;
@@ -153,8 +150,6 @@ bool Option::AllVolatile = false;
StringBag Option::OptionStrings;
bool Option::GenerateCppLibCode = false;
bool Option::GenerateSourceInfo = false;
bool Option::GenerateDocComments = true;
void (*Option::m_hookHandler)(Hdf &config);
@@ -283,16 +278,11 @@ void Option::Load(Hdf &config) {
ParserThreadCount = Process::GetCPUCount();
}
EnableFinallyStatement = config["EnableFinallyStatement"].getBool();
EnableEval = (EvalLevel)config["EnableEval"].getByte(0);
AllDynamic = config["AllDynamic"].getBool(true);
AllVolatile = config["AllVolatile"].getBool();
GenerateCppLibCode = config["GenerateCppLibCode"].getBool(false);
GenerateSourceInfo = config["GenerateSourceInfo"].getBool(false);
GenerateDocComments = config["GenerateDocComments"].getBool(true);
UseVirtualDispatch = config["UseVirtualDispatch"].getBool(false);
EliminateDeadCode = config["EliminateDeadCode"].getBool(true);
CopyProp = config["CopyProp"].getBool(false);
LocalCopyProp = config["LocalCopyProp"].getBool(true);
@@ -303,6 +293,7 @@ void Option::Load(Hdf &config) {
ArrayAccessIdempotent = config["ArrayAccessIdempotent"].getBool(false);
DumpAst = config["DumpAst"].getBool(false);
WholeProgram = config["WholeProgram"].getBool(true);
UseHHBBC = config["UseHHBBC"].getBool(UseHHBBC);
// Temporary, during file-cache migration.
FileCache::UseNewCache = config["UseNewCache"].getBool(false);
+1 -6
Ver Arquivo
@@ -222,7 +222,6 @@ public:
static bool EnableShortTags;
static bool EnableAspTags;
static bool EnableXHP;
static bool EnableFinallyStatement;
static int ParserThreadCount;
static int GetScannerType();
@@ -238,10 +237,7 @@ public:
* Optimizations
*/
static int InvokeFewArgsCount;
static bool InvokeWithSpecificArgs;
static bool FlattenInvoke;
static int InlineFunctionThreshold;
static bool UseVirtualDispatch;
static bool EliminateDeadCode;
static bool CopyProp;
static bool LocalCopyProp;
@@ -252,13 +248,12 @@ public:
/**
* Output options
*/
static bool GenerateCppLibCode;
static bool GenerateSourceInfo;
static bool GenerateDocComments;
static bool ControlFlow;
static bool VariableCoalescing;
static bool DumpAst;
static bool WholeProgram;
static bool UseHHBBC; // see hhbbc/README
static bool RecordErrors;
static std::string DocJson; // filename to dump doc JSON to
+4 -5
Ver Arquivo
@@ -193,14 +193,14 @@ FileCachePtr Package::getFileCache() {
///////////////////////////////////////////////////////////////////////////////
class ParserWorker :
public JobQueueWorker<std::pair<const char *,bool>, true, true> {
public JobQueueWorker<std::pair<const char *,bool>, Package*, true, true> {
public:
bool m_ret;
ParserWorker() : m_ret(true) {}
virtual void doJob(JobType job) {
bool ret;
try {
Package *package = (Package*)m_opaque;
Package *package = m_context;
ret = package->parseImpl(job.first);
} catch (Exception &e) {
Logger::Error("%s", e.getMessage().c_str());
@@ -222,8 +222,7 @@ void Package::addSourceFile(const char *fileName, bool check /* = false */) {
Lock lock(m_mutex);
bool inserted = m_filesToParse.insert(Util::canonicalize(fileName)).second;
if (inserted && m_dispatcher) {
((JobQueueDispatcher<ParserWorker::JobType,
ParserWorker>*)m_dispatcher)->enqueue(
((JobQueueDispatcher<ParserWorker>*)m_dispatcher)->enqueue(
std::make_pair(m_files.add(fileName), check));
}
}
@@ -240,7 +239,7 @@ bool Package::parse(bool check) {
}
if (threadCount <= 0) threadCount = 1;
JobQueueDispatcher<ParserWorker::JobType, ParserWorker>
JobQueueDispatcher<ParserWorker>
dispatcher(threadCount, true, 0, false, this);
m_dispatcher = &dispatcher;
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+178 -30
Ver Arquivo
@@ -100,13 +100,17 @@
#endif
#define NEW_EXP0(cls) \
cls##Ptr(new cls(BlockScopePtr(), getLocation()))
cls##Ptr(new cls(BlockScopePtr(), \
getLocation()))
#define NEW_EXP(cls, e...) \
cls##Ptr(new cls(BlockScopePtr(), getLocation(), ##e))
cls##Ptr(new cls(BlockScopePtr(), \
getLocation(), ##e))
#define NEW_STMT0(cls) \
cls##Ptr(new cls(BlockScopePtr(), getLocation()))
cls##Ptr(new cls(BlockScopePtr(), getLabelScope(), \
getLocation()))
#define NEW_STMT(cls, e...) \
cls##Ptr(new cls(BlockScopePtr(), getLocation(), ##e))
cls##Ptr(new cls(BlockScopePtr(), getLabelScope(), \
getLocation(), ##e))
#define PARSE_ERROR(fmt, args...) HPHP_PARSER_ERROR(fmt, this, ##args)
@@ -151,7 +155,8 @@ StatementListPtr Parser::ParseString(const String& input, AnalysisResultPtr ar,
Parser::Parser(Scanner &scanner, const char *fileName,
AnalysisResultPtr ar, int fileSize /* = 0 */)
: ParserBase(scanner, fileName), m_ar(ar), m_lambdaMode(false),
m_closureGenerator(false), m_nsState(SeenNothing) {
m_closureGenerator(false), m_nsState(SeenNothing),
m_aliasTable(getAutoAliasedClasses(), [&] { return isAutoAliasOn(); }) {
string md5str = Eval::FileRepository::unitMd5(scanner.getMd5());
MD5 md5 = MD5(md5str.c_str());
@@ -174,10 +179,16 @@ bool Parser::parse() {
"Parse error: %s",
errString().c_str());
}
} catch (ParseTimeFatalException &e) {
m_file->cleanupForError(m_ar, e.m_line, e.getMessage());
return true;
} catch (const ParseTimeFatalException& e) {
m_file->cleanupForError(m_ar);
if (e.m_parseFatal) {
m_file->makeParseFatal(m_ar, e.getMessage(), e.m_line);
} else {
m_file->makeFatal(m_ar, e.getMessage(), e.m_line);
}
return false;
}
return true;
}
void Parser::error(const char* fmt, ...) {
@@ -190,19 +201,22 @@ void Parser::error(const char* fmt, ...) {
fatal(&m_loc, msg.c_str());
}
void Parser::fatal(Location *loc, const char *msg) {
throw ParseTimeFatalException(loc->file, loc->line0,
"%s", msg);
void Parser::parseFatal(const Location* loc, const char* msg) {
// we can't use loc->file, as the bison parser doesn't track that in YYLTYPE
auto file = m_file->getName().c_str();
auto exn = ParseTimeFatalException(file, loc->line0, "%s", msg);
exn.setParseFatal();
throw exn;
}
void Parser::fatal(const Location* loc, const char* msg) {
throw ParseTimeFatalException(loc->file, loc->line0, "%s", msg);
}
string Parser::errString() {
return m_error.empty() ? getMessage() : m_error;
}
bool Parser::enableFinallyStatement() {
return Option::EnableFinallyStatement;
}
void Parser::pushComment() {
m_comments.push_back(m_scanner.detachDocComment());
}
@@ -235,6 +249,39 @@ void Parser::completeScope(BlockScopePtr inner) {
}
}
LabelScopePtr Parser::getLabelScope() const {
DCHECK(!m_labelScopes.empty());
DCHECK(!m_labelScopes.back().empty());
DCHECK(m_labelScopes.back().back() != nullptr);
return m_labelScopes.back().back();
}
void Parser::onNewLabelScope(bool fresh) {
if (fresh) {
m_labelScopes.push_back(LabelScopePtrVec());
}
DCHECK(!m_labelScopes.empty());
LabelScopePtr labelScope(new LabelScope());
m_labelScopes.back().push_back(labelScope);
}
void Parser::onScopeLabel(const Token& stmt, const Token& label) {
DCHECK(!m_labelScopes.empty());
DCHECK(!m_labelScopes.back().empty());
for (auto& scope : m_labelScopes.back()) {
scope->addLabel(stmt.stmt, label.text());
}
}
void Parser::onCompleteLabelScope(bool fresh) {
assert(!m_labelScopes.empty());
assert(!m_labelScopes.back().empty());
m_labelScopes.back().pop_back();
if (fresh) {
m_labelScopes.pop_back();
}
}
///////////////////////////////////////////////////////////////////////////////
// variables
@@ -373,7 +420,7 @@ void Parser::onCallParam(Token &out, Token *params, Token &expr, bool ref) {
}
void Parser::onCall(Token &out, bool dynamic, Token &name, Token &params,
Token *cls, bool fromCompiler) {
Token *cls) {
ExpressionPtr clsExp;
if (cls) {
clsExp = cls->exp;
@@ -382,7 +429,6 @@ void Parser::onCall(Token &out, bool dynamic, Token &name, Token &params,
out->exp = NEW_EXP(DynamicFunctionCall, name->exp,
dynamic_pointer_cast<ExpressionList>(params->exp),
clsExp);
assert(!fromCompiler);
} else {
const string &s = name.text();
// strip out namespaces for func_get_args and friends check
@@ -402,8 +448,13 @@ void Parser::onCall(Token &out, bool dynamic, Token &name, Token &params,
(new RealSimpleFunctionCall
(BlockScopePtr(), getLocation(), name->text(), name->num() & 2,
dynamic_pointer_cast<ExpressionList>(params->exp), clsExp));
if (fromCompiler) {
call->setFromCompiler();
if (m_scanner.isHHSyntaxEnabled() && !(name->num() & 2)) {
// If the function name is without any backslashes or
// namespace qualification then we treat this as a candidate
// for optimization via bytecode promotion.
// "idx" is the only function in that class for now but it's
// cheaper to set the bit that to check for the function name
call->setOptimizable();
}
out->exp = call;
@@ -893,7 +944,7 @@ StatementPtr Parser::onFunctionHelper(FunctionType type,
StatementListPtr stmts = stmt->stmt || stmt->num() != 1 ?
dynamic_pointer_cast<StatementList>(stmt->stmt)
: NEW_EXP0(StatementList);
: NEW_STMT0(StatementList);
ExpressionListPtr old_params =
dynamic_pointer_cast<ExpressionList>(params->exp);
@@ -997,7 +1048,8 @@ void Parser::onParam(Token &out, Token *params, Token &type, Token &var,
void Parser::onClassStart(int type, Token &name) {
const Type::TypePtrMap& typeHintTypes =
Type::GetTypeHintTypes(m_scanner.isHHSyntaxEnabled());
if (name.text() == "self" || name.text() == "parent" ||
if (0 == strcasecmp("self", name.text().c_str()) ||
0 == strcasecmp("parent", name.text().c_str()) ||
typeHintTypes.find(name.text()) != typeHintTypes.end()) {
PARSE_ERROR("Cannot use '%s' as class name as it is reserved",
name.text().c_str());
@@ -1618,12 +1670,18 @@ void Parser::onTry(Token &out, Token &tryStmt, Token &className, Token &var,
out->stmt = NEW_STMT(TryStatement, tryStmt->stmt,
dynamic_pointer_cast<StatementList>(stmtList),
finallyStmt->stmt);
if (tryStmt->stmt) {
out->stmt->setLabelScope(stmtList->getLabelScope());
}
}
void Parser::onTry(Token &out, Token &tryStmt, Token &finallyStmt) {
out->stmt = NEW_STMT(TryStatement, tryStmt->stmt,
dynamic_pointer_cast<StatementList>(NEW_STMT0(StatementList)),
finallyStmt->stmt);
if (tryStmt->stmt) {
out->stmt->setLabelScope(tryStmt->stmt->getLabelScope());
}
}
void Parser::onCatch(Token &out, Token &catches, Token &className, Token &var,
@@ -1641,6 +1699,11 @@ void Parser::onCatch(Token &out, Token &catches, Token &className, Token &var,
void Parser::onFinally(Token &out, Token &stmt) {
out->stmt = NEW_STMT(FinallyStatement, stmt->stmt);
// TODO (#3271396) This can be greatly improved. In particular
// even when a finally block exists inside a function it is often
// the case that the unnamed locals state & ret are not needed.
// See task description for further details.
m_file->setAttribute(FileScope::NeedsFinallyLocals);
}
void Parser::onThrow(Token &out, Token &expr) {
@@ -1762,6 +1825,86 @@ void Parser::onTypeSpecialization(Token& type, char specialization) {
///////////////////////////////////////////////////////////////////////////////
// namespace support
//////////////////// AliasTable /////////////////////
Parser::AliasTable::AliasTable(const std::vector<AliasEntry>& autoAliases,
std::function<bool ()> autoOracle) :
m_autoAliases(autoAliases), m_autoOracle(autoOracle),
m_alreadyImported(false) {
if (!m_autoOracle) {
setFalseOracle();
}
}
void Parser::AliasTable::setFalseOracle() {
m_autoOracle = [] () { return false; };
}
/*
* Add the auto-imports to the map.
* This is called by all the other operations, so the auto-import occurs
* on-demand.
*/
void Parser::AliasTable::addAutoImports() {
if (!m_alreadyImported && m_autoOracle()) {
m_alreadyImported = true;
for (auto entry : m_autoAliases) {
m_aliases[entry.alias] = (NameEntry){entry.name, true};
}
}
}
std::string Parser::AliasTable::getName(std::string alias) {
addAutoImports();
auto it = m_aliases.find(alias);
return (m_aliases.end() == it) ? "" : it->second.name;
}
bool Parser::AliasTable::isAliased(std::string alias) {
addAutoImports();
return m_aliases.find(alias) != m_aliases.end();
}
bool Parser::AliasTable::isAutoImported(std::string alias) {
addAutoImports();
auto it = m_aliases.find(alias);
return it != m_aliases.end() && it->second.isAuto;
}
void Parser::AliasTable::map(std::string alias, std::string name) {
addAutoImports();
m_aliases[alias] = (NameEntry){name, false};
}
/*
* To be called when we enter a fresh namespace.
*/
void Parser::AliasTable::clear() {
m_aliases.clear();
m_alreadyImported = false;
}
//////////////////////////////////////////////////////
/*
* We auto-alias classes on HH mode and only if we're in the global namespace.
*/
bool Parser::isAutoAliasOn() {
return m_scanner.isHHSyntaxEnabled() && ("" == m_namespace);
}
std::vector<Parser::AliasTable::AliasEntry> Parser::getAutoAliasedClasses() {
std::vector<AliasTable::AliasEntry> aliases;
aliases.push_back(
(AliasTable::AliasEntry){"Traversable", "HH\\Traversable"});
aliases.push_back(
(AliasTable::AliasEntry){"Iterator", "HH\\Iterator"});
return aliases;
}
void Parser::nns(int token) {
if (m_nsState == SeenNamespaceStatement && token != ';') {
error("No code may exist outside of namespace {}: %s",
@@ -1787,10 +1930,9 @@ void Parser::onNamespaceStart(const std::string &ns,
m_nsState = InsideNamespace;
m_nsFileScope = file_scope;
m_aliases.clear();
pushComment();
m_namespace = ns;
m_aliasTable.clear();
}
void Parser::onNamespaceEnd() {
@@ -1807,12 +1949,17 @@ void Parser::onUse(const std::string &ns, const std::string &as) {
key = ns.substr(pos + 1);
}
}
if (m_aliases.find(key) != m_aliases.end() && m_aliases[key] != ns) {
// It's not an error if the alias already exists but is auto-imported.
// In that case, it gets replaced.
if (m_aliasTable.isAliased(key) && !m_aliasTable.isAutoImported(key) &&
m_aliasTable.getName(key) != ns) {
error("Cannot use %s as %s because the name is already in use: %s",
ns.c_str(), key.c_str(), getMessage().c_str());
return;
}
m_aliases[key] = ns;
m_aliasTable.map(key, ns);
}
std::string Parser::nsDecl(const std::string &name) {
@@ -1829,15 +1976,16 @@ std::string Parser::resolve(const std::string &ns, bool cls) {
alias = ns.substr(0, pos);
}
hphp_string_imap<std::string>::const_iterator iter = m_aliases.find(alias);
if (iter != m_aliases.end()) {
if (m_aliasTable.isAliased(alias)) {
auto name = m_aliasTable.getName(alias);
// Was it a namespace alias?
if (pos != string::npos) {
return iter->second + ns.substr(pos);
return name + ns.substr(pos);
}
// Only classes can appear directly in "use" statements
if (cls) {
return iter->second;
return name;
}
}
@@ -1902,7 +2050,7 @@ void Parser::registerAlias(std::string name) {
size_t pos = name.rfind(NAMESPACE_SEP);
if (pos != string::npos) {
string key = name.substr(pos + 1);
m_aliases[key] = name;
m_aliasTable.map(key, name);
}
}
+95 -14
Ver Arquivo
@@ -17,6 +17,8 @@
#ifndef incl_HPHP_COMPILER_PARSER_H_
#define incl_HPHP_COMPILER_PARSER_H_
#include <functional>
#include "hphp/runtime/base/exceptions.h"
#include "hphp/parser/parser.h"
#include "hphp/compiler/construct.h"
@@ -26,24 +28,26 @@
#include "hphp/compiler/expression/scalar_expression.h"
#include "hphp/compiler/statement/statement.h"
#include "hphp/compiler/statement/statement_list.h"
#include "hphp/util/logger.h"
#ifdef HPHP_PARSER_NS
#undef HPHP_PARSER_NS
#endif
#define HPHP_PARSER_NS Compiler
#define LOG_PARSE_ERROR(file, line, fmt, args...) \
HPHP::Logger::Error( \
"HipHop Fatal error: " fmt " in %s on line %d", \
##args, \
(file), \
(line) \
)
#ifdef HPHP_PARSER_ERROR
#undef HPHP_PARSER_ERROR
#endif
#define HPHP_PARSER_ERROR(fmt, p, args...) \
do { \
if (HPHP::Option::WholeProgram) { \
HPHP::Logger::Error(fmt " %s", ##args, (p)->getMessage(true).c_str()); \
} \
throw HPHP::ParseTimeFatalException((p)->file(), (p)->line1(), \
fmt, ##args); \
} while (0)
#define HPHP_PARSER_ERROR(fmt, p, args...) \
throw HPHP::ParseTimeFatalException((p)->file(), (p)->line1(), fmt, ##args)
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -51,6 +55,7 @@ namespace HPHP {
DECLARE_BOOST_TYPES(Expression);
DECLARE_BOOST_TYPES(Statement);
DECLARE_BOOST_TYPES(StatementList);
DECLARE_BOOST_TYPES(LabelScope);
DECLARE_BOOST_TYPES(Location);
DECLARE_BOOST_TYPES(AnalysisResult);
DECLARE_BOOST_TYPES(BlockScope);
@@ -122,10 +127,10 @@ public:
virtual bool parseImpl();
bool parse();
virtual void error(const char* fmt, ...) ATTRIBUTE_PRINTF(2,3);
virtual bool enableFinallyStatement();
IMPLEMENT_XHP_ATTRIBUTES;
virtual void fatal(Location *loc, const char *msg);
virtual void fatal(const Location* loc, const char* msg);
virtual void parseFatal(const Location* loc, const char* msg);
std::string errString();
// result
@@ -154,8 +159,7 @@ public:
void onStaticMember(Token &out, Token &cls, Token &name);
void onRefDim(Token &out, Token &var, Token &offset);
void onCallParam(Token &out, Token *params, Token &expr, bool ref);
void onCall(Token &out, bool dynamic, Token &name, Token &params,
Token *cls, bool fromCompiler = false);
void onCall(Token &out, bool dynamic, Token &name, Token &params, Token *cls);
void onEncapsList(Token &out, int type, Token &list);
void addEncap(Token &out, Token *list, Token &expr, int type);
void encapRefDim(Token &out, Token &var, Token &offset);
@@ -271,6 +275,36 @@ public:
std::string nsDecl(const std::string &name);
std::string resolve(const std::string &ns, bool cls);
/*
* Get the current label scope. A new label scope is demarcated by
* one of the following: a loop, a switch statement, a finally block,
* a try block or one of the constructs demarcating variables scopes
* (i.e. functions, closures, etc.)
* For every label scope, we keep track of the labels
* that are available inside it. This is required for supporting
* features such as try ... finally.
*/
LabelScopePtr getLabelScope() const;
/*
* Called whenever a new label scope is entered. The fresh parameter
* indicates whether the scope is also a variable scope (i.e. a
* function, a closure, ...) or just a label scope (i.e. a loop body,
* a switch statement, a finally block, ...).
*/
void onNewLabelScope(bool fresh);
/*
* Called whenever a new label is encountered.
*/
void onScopeLabel(const Token& stmt, const Token& label);
/*
* Called whenever a label scope ends. The fresh parameter has the
* same meaning as for onNewLabelScope.
*/
void onCompleteLabelScope(bool fresh);
virtual void invalidateGoto(TStatementPtr stmt, GotoError error);
virtual void invalidateLabel(TStatementPtr stmt);
@@ -305,6 +339,7 @@ private:
FileScopePtr m_file;
std::vector<std::string> m_comments; // for docComment stack
std::vector<BlockScopePtrVec> m_scopes;
std::vector<LabelScopePtrVec> m_labelScopes;
std::vector<FunctionContext> m_funcContexts;
std::vector<std::vector<StatementPtr> > m_prependingStatements;
std::vector<ScalarExpressionPtr> m_compilerHaltOffsetVec;
@@ -366,11 +401,57 @@ private:
SeenNamespaceStatement,
InsideNamespace,
};
/*
* An AliasTable maps aliases to names.
* We use it instead a regular map because it lazily imports a bunch of
* names into the current namespace when appropriate.
*/
class AliasTable {
public:
struct AliasEntry {
std::string alias;
std::string name;
};
AliasTable(const std::vector<AliasEntry>& autoAliases,
std::function<bool ()> autoOracle);
std::string getName(std::string alias);
bool isAliased(std::string alias);
bool isAutoImported(std::string alias);
void map(std::string alias, std::string name);
void clear();
private:
struct NameEntry {
std::string name;
bool isAuto; // Is the name automatically-imported?
};
hphp_string_imap<NameEntry> m_aliases;
// These get imported every time we enter a new namespace.
std::vector<AliasEntry> m_autoAliases;
// Returns true if stuff should be auto-imported.
std::function<bool ()> m_autoOracle;
// Have we already auto-imported names for the current namespace?
// This is useful because auto-imports are done lazily.
bool m_alreadyImported;
void setFalseOracle();
void addAutoImports();
};
NamespaceState m_nsState;
bool m_nsFileScope;
std::string m_namespace; // current namespace
hphp_string_imap<std::string> m_aliases;
AliasTable m_aliasTable;
void registerAlias(std::string name);
bool isAutoAliasOn();
std::vector<AliasTable::AliasEntry> getAutoAliasedClasses();
};
///////////////////////////////////////////////////////////////////////////////
+13
Ver Arquivo
@@ -93,6 +93,19 @@ void BlockStatement::inferTypes(AnalysisResultPtr ar) {
if (m_stmts) m_stmts->inferTypes(ar);
}
///////////////////////////////////////////////////////////////////////////////
void BlockStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("BlockStatement", m_stmts != nullptr ? 2 : 1);
if (m_stmts != nullptr) {
cg.printPropertyHeader("statements");
m_stmts->outputCodeModel(cg);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+15
Ver Arquivo
@@ -75,6 +75,21 @@ StatementPtr BreakStatement::preOptimize(AnalysisResultConstPtr ar) {
void BreakStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void BreakStatement::outputCodeModel(CodeGenerator &cg) {
if (strncmp(m_name, "break", 5)) {
cg.printObjectHeader("BreakStatement", 2);
} else {
cg.printObjectHeader("ContinueStatement", 2);
}
cg.printPropertyHeader("depth");
cg.printValue((int)m_depth);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+20
Ver Arquivo
@@ -118,6 +118,26 @@ void CaseStatement::inferAndCheck(AnalysisResultPtr ar, TypePtr type,
if (m_stmt) m_stmt->inferTypes(ar);
}
///////////////////////////////////////////////////////////////////////////////
void CaseStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 1;
if (m_condition != nullptr) numProps++;
if (m_stmt != nullptr) numProps++;
cg.printObjectHeader("CaseStatement", numProps);
if (m_condition != nullptr) {
cg.printPropertyHeader("condition");
m_condition->outputCodeModel(cg);
}
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+19
Ver Arquivo
@@ -134,6 +134,25 @@ void CatchStatement::inferTypes(AnalysisResultPtr ar) {
if (m_stmt) m_stmt->inferTypes(ar);
}
///////////////////////////////////////////////////////////////////////////////
void CatchStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 3;
if (m_stmt != nullptr) numProps++;
cg.printObjectHeader("CatchStatement", numProps);
cg.printPropertyHeader("className");
cg.printValue(m_origClassName);
cg.printPropertyHeader("variableName");
cg.printValue(m_variable->getName());
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+11
Ver Arquivo
@@ -130,6 +130,17 @@ void ClassConstant::inferTypes(AnalysisResultPtr ar) {
m_exp->inferAndCheck(ar, Type::Some, false);
}
///////////////////////////////////////////////////////////////////////////////
void ClassConstant::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ConstantStatement", 2);
cg.printPropertyHeader("expressions");
cg.printExpressionVector(m_exp);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+54
Ver Arquivo
@@ -31,6 +31,7 @@
#include "hphp/util/util.h"
#include "hphp/compiler/statement/interface_statement.h"
#include "hphp/compiler/statement/use_trait_statement.h"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/compiler/option.h"
#include <sstream>
#include <algorithm>
@@ -211,6 +212,59 @@ void ClassStatement::analyzeProgram(AnalysisResultPtr ar) {
void ClassStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void ClassStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 4;
if (m_attrList != nullptr) numProps++;
if (m_type == T_ABSTRACT || m_type == T_FINAL) numProps++;
if (!m_parent.empty()) numProps++;
if (m_base != nullptr) numProps++;
if (m_stmt != nullptr) numProps++;
if (!m_docComment.empty()) numProps++;
cg.printObjectHeader("TypeStatement", numProps);
if (m_attrList != nullptr) {
cg.printPropertyHeader("attributes");
cg.printExpressionVector(m_attrList);
}
if (m_type == T_ABSTRACT) {
cg.printPropertyHeader("modifiers");
cg.printModifierVector("abstract");
} else if (m_type == T_FINAL) {
cg.printPropertyHeader("modifiers");
cg.printModifierVector("final");
}
cg.printPropertyHeader("kind");
if (m_type == T_TRAIT) {
cg.printValue(PHP_TRAIT);
} else {
cg.printValue(PHP_CLASS);
}
cg.printPropertyHeader("name");
cg.printValue(m_originalName);
//TODO: type parameters (task 3262469)
if (!m_parent.empty()) {
cg.printPropertyHeader("baseClass");
cg.printTypeExpression(m_originalParent);
}
if (m_base != nullptr) {
cg.printPropertyHeader("interfaces");
cg.printExpressionVector(m_base);
}
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
if (!m_docComment.empty()) {
cg.printPropertyHeader("comments");
cg.printValue(m_docComment);
}
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+13
Ver Arquivo
@@ -279,6 +279,19 @@ void ClassVariable::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void ClassVariable::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ClassVariableStatement", 3);
cg.printPropertyHeader("modifiers");
m_modifiers->outputCodeModel(cg);
cg.printPropertyHeader("expressions");
cg.printExpressionVector(m_declaration);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+15
Ver Arquivo
@@ -90,6 +90,21 @@ void DoStatement::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void DoStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("DoStatement", m_stmt != nullptr ? 3 : 2);
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("condition");
m_condition->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+11
Ver Arquivo
@@ -81,6 +81,17 @@ void EchoStatement::inferTypes(AnalysisResultPtr ar) {
m_exp->inferAndCheck(ar, Type::String, false);
}
///////////////////////////////////////////////////////////////////////////////
void EchoStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("EchoStatement", 2);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+11
Ver Arquivo
@@ -96,6 +96,17 @@ void ExpStatement::inferTypes(AnalysisResultPtr ar) {
m_exp->inferAndCheck(ar, Type::Any, false);
}
///////////////////////////////////////////////////////////////////////////////
void ExpStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ExpressionStatement", 2);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -92,6 +92,19 @@ void FinallyStatement::inferTypes(AnalysisResultPtr ar) {
if (m_stmt) m_stmt->inferTypes(ar);
}
///////////////////////////////////////////////////////////////////////////////
void FinallyStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("FinallyStatement", m_stmt == nullptr ? 1 : 2);
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+30
Ver Arquivo
@@ -120,6 +120,36 @@ void ForStatement::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void ForStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 1;
if (m_exp1 != nullptr) numProps++;
if (m_exp2 != nullptr) numProps++;
if (m_exp3 != nullptr) numProps++;
if (m_stmt != nullptr) numProps++;
cg.printObjectHeader("ForStatement", numProps);
if (m_exp1 != nullptr) {
cg.printPropertyHeader("expression1");
m_exp1->outputCodeModel(cg);
}
if (m_exp2 != nullptr) {
cg.printPropertyHeader("expression2");
m_exp2->outputCodeModel(cg);
}
if (m_exp3 != nullptr) {
cg.printPropertyHeader("expression3");
m_exp3->outputCodeModel(cg);
}
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -151,6 +151,30 @@ void ForEachStatement::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void ForEachStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 3;
if (m_name != nullptr) numProps++;
if (m_stmt != nullptr) numProps++;
cg.printObjectHeader("ForeachStatement", numProps);
cg.printPropertyHeader("collection");
m_array->outputCodeModel(cg);
if (m_name != nullptr) {
cg.printPropertyHeader("key");
m_name->outputCodeModel(cg);
}
cg.printPropertyHeader("value");
cg.printExpression(m_value, m_ref);
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -132,6 +132,12 @@ void FunctionStatement::analyzeProgram(AnalysisResultPtr ar) {
void FunctionStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void FunctionStatement::outputCodeModel(CodeGenerator &cg) {
MethodStatement::outputCodeModel(cg);
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+11
Ver Arquivo
@@ -135,6 +135,17 @@ void GlobalStatement::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void GlobalStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("GlobalStatement", 2);
cg.printPropertyHeader("expressions");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+11
Ver Arquivo
@@ -86,6 +86,17 @@ void GotoStatement::setNthKid(int n, ConstructPtr cp) {
void GotoStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void GotoStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("GotoStatement", 2);
cg.printPropertyHeader("label");
cg.printValue(m_label);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -83,6 +83,25 @@ void IfBranchStatement::inferTypes(AnalysisResultPtr ar) {
if (m_stmt) m_stmt->inferTypes(ar);
}
///////////////////////////////////////////////////////////////////////////////
void IfBranchStatement::outputCodeModel(CodeGenerator &cg) {
if (m_condition == nullptr) {
if (m_stmt != nullptr) m_stmt->outputCodeModel(cg);
return;
}
cg.printObjectHeader("ConditionalStatement", 3);
cg.printPropertyHeader("condition");
m_condition->outputCodeModel(cg);
if (m_stmt != nullptr) {
cg.printPropertyHeader("trueBlock");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+35
Ver Arquivo
@@ -216,6 +216,41 @@ void IfStatement::inferTypes(AnalysisResultPtr ar) {
if (m_stmts) m_stmts->inferTypes(ar);
}
///////////////////////////////////////////////////////////////////////////////
void IfStatement::outputCodeModel(CodeGenerator &cg) {
for (int i = 0; i < m_stmts->getCount(); i++) {
IfBranchStatementPtr branch =
dynamic_pointer_cast<IfBranchStatement>((*m_stmts)[i]);
assert(branch != nullptr); // this cast always succeeds, by construction.
auto condition = branch->getCondition();
auto statements = branch->getStmt();
auto numProps = 1;
if (condition != nullptr) numProps++;
if (statements != nullptr) numProps++;
if (i < m_stmts->getCount() - 1) numProps++;
if (i > 0) {
cg.printPropertyHeader("falseBlock");
if (i < m_stmts->getCount() - 1) {
printf("V:6:\"Vector\":1:{");
}
}
if (condition != nullptr) {
cg.printObjectHeader("ConditionalStatement", 3);
cg.printPropertyHeader("condition");
condition->outputCodeModel(cg);
cg.printPropertyHeader("trueBlock");
}
if (statements != nullptr) {
cg.printAsBlock(statements);
}
}
for (int i = 0; i < m_stmts->getCount() - 1; i++) {
cg.printf("}");
cg.printObjectFooter();
}
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -26,6 +26,7 @@
#include "hphp/compiler/analysis/variable_table.h"
#include "hphp/util/util.h"
#include "hphp/compiler/option.h"
#include "hphp/compiler/code_model_enums.h"
#include "hphp/compiler/parser/parser.h"
using namespace HPHP;
@@ -252,6 +253,42 @@ StatementPtr InterfaceStatement::preOptimize(AnalysisResultConstPtr ar) {
void InterfaceStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void InterfaceStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 3;
if (m_attrList != nullptr) numProps++;
if (m_base != nullptr) numProps++;
if (m_stmt != nullptr) numProps++;
if (!m_docComment.empty()) numProps++;
cg.printObjectHeader("TypeStatement", numProps);
if (m_attrList != nullptr) {
cg.printPropertyHeader("attributes");
cg.printExpressionVector(m_attrList);
}
cg.printPropertyHeader("kind");
cg.printValue(PHP_INTERFACE);
cg.printPropertyHeader("name");
cg.printValue(m_originalName);
//TODO: type parameters (task 3262469)
if (m_base != nullptr) {
cg.printPropertyHeader("interfaces");
cg.printExpressionVector(m_base);
}
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
if (!m_docComment.empty()) {
cg.printPropertyHeader("comments");
cg.printValue(m_docComment);
}
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+11
Ver Arquivo
@@ -67,6 +67,17 @@ void LabelStatement::setNthKid(int n, ConstructPtr cp) {
void LabelStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void LabelStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("LabelStatement", 2);
cg.printPropertyHeader("label");
cg.printValue(m_label);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+47 -1
Ver Arquivo
@@ -547,7 +547,8 @@ void MethodStatement::inferFunctionTypes(AnalysisResultPtr ar) {
Variant(Variant::NullInit()));
ReturnStatementPtr returnStmt =
ReturnStatementPtr(
new ReturnStatement(getScope(), getLocation(), constant));
new ReturnStatement(getScope(), getLabelScope(),
getLocation(), constant));
m_stmt->addElement(returnStmt);
}
}
@@ -562,6 +563,51 @@ void MethodStatement::inferFunctionTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void MethodStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 3;
if (m_attrList != nullptr) numProps++;
if (m_ref) numProps++;
if (m_params != nullptr) numProps++;
if (m_retTypeAnnotation != nullptr) numProps++;
if (m_stmt != nullptr) numProps++;
if (!m_docComment.empty()) numProps++;
cg.printObjectHeader("FunctionStatement", numProps);
if (m_attrList != nullptr) {
cg.printPropertyHeader("attributes");
cg.printExpressionVector(m_attrList);
}
cg.printPropertyHeader("modifiers");
m_modifiers->outputCodeModel(cg);
if (m_ref) {
cg.printPropertyHeader("returnsReference");
cg.printValue(m_ref);
}
cg.printPropertyHeader("name");
cg.printValue(m_originalName);
//TODO: type parameters (task 3262469)
if (m_params != nullptr) {
cg.printPropertyHeader("parameters");
cg.printExpressionVector(m_params);
}
if (m_retTypeAnnotation != nullptr) {
cg.printPropertyHeader("returnType");
m_retTypeAnnotation->outputCodeModel(cg);
}
if (m_stmt != nullptr) {
cg.printPropertyHeader("block");
cg.printAsBlock(m_stmt);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
if (!m_docComment.empty()) {
cg.printPropertyHeader("comments");
cg.printValue(m_docComment);
}
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+14
Ver Arquivo
@@ -115,6 +115,20 @@ void ReturnStatement::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void ReturnStatement::outputCodeModel(CodeGenerator &cg) {
auto nump = m_exp ? 2 : 1;
cg.printObjectHeader("ReturnStatement", nump);
if (m_exp) {
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+4 -1
Ver Arquivo
@@ -28,7 +28,10 @@ const char *Statement::Names[] = {
};
Statement::Statement(STATEMENT_CONSTRUCTOR_BASE_PARAMETERS)
: Construct(scope, loc), m_kindOf(kindOf) {
: Construct(scope, loc),
m_kindOf(kindOf),
m_labelScope(labelScope) {
DCHECK(m_labelScope != nullptr);
}
///////////////////////////////////////////////////////////////////////////////
+16 -5
Ver Arquivo
@@ -18,19 +18,23 @@
#define incl_HPHP_STATEMENT_H_
#include "hphp/compiler/expression/expression.h"
#include "hphp/compiler/analysis/label_scope.h"
#include <string>
#define STATEMENT_CONSTRUCTOR_BASE_PARAMETERS \
BlockScopePtr scope, LocationPtr loc, Statement::KindOf kindOf
BlockScopePtr scope, LabelScopePtr labelScope, LocationPtr loc, \
Statement::KindOf kindOf
#define STATEMENT_CONSTRUCTOR_BASE_PARAMETER_VALUES \
scope, loc, kindOf
scope, labelScope, loc, kindOf
#define STATEMENT_CONSTRUCTOR_PARAMETERS \
BlockScopePtr scope, LocationPtr loc
BlockScopePtr scope, LabelScopePtr labelScope, LocationPtr loc
#define STATEMENT_CONSTRUCTOR_PARAMETER_VALUES(kindOf) \
scope, loc, Statement::KindOf##kindOf
scope, labelScope, loc, Statement::KindOf##kindOf
#define DECLARE_BASE_STATEMENT_VIRTUAL_FUNCTIONS \
virtual void analyzeProgram(AnalysisResultPtr ar); \
virtual StatementPtr clone(); \
virtual void inferTypes(AnalysisResultPtr ar); \
virtual void outputCodeModel(CodeGenerator &cg); \
virtual void outputPHP(CodeGenerator &cg, AnalysisResultPtr ar);
#define DECLARE_STATEMENT_VIRTUAL_FUNCTIONS \
DECLARE_BASE_STATEMENT_VIRTUAL_FUNCTIONS; \
@@ -38,12 +42,15 @@
virtual int getKidCount() const; \
virtual void setNthKid(int n, ConstructPtr cp)
#define NULL_STATEMENT() \
BlockStatementPtr(new BlockStatement(getScope(), getLocation(), \
BlockStatementPtr(new BlockStatement(getScope(), \
getLabelScope(), \
getLocation(), \
StatementListPtr()))
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(Statement);
DECLARE_BOOST_TYPES(LabelScope);
#define DECLARE_STATEMENT_TYPES(x) \
x(FunctionStatement), \
@@ -149,10 +156,14 @@ public:
virtual int getRecursiveCount() const { return 1; }
LabelScopePtr getLabelScope() { return m_labelScope; }
void setLabelScope(LabelScopePtr labelScope) { m_labelScope = labelScope; }
protected:
KindOf m_kindOf;
int m_silencerCountMax;
int m_silencerCountCurrent;
LabelScopePtr m_labelScope;
};
///////////////////////////////////////////////////////////////////////////////
+10 -1
Ver Arquivo
@@ -262,7 +262,8 @@ bool StatementList::mergeConcatAssign() {
var, exp1, T_CONCAT_EQUAL));
}
expStmt = ExpStatementPtr
(new ExpStatement(getScope(), getLocation(), exp));
(new ExpStatement(getScope(), getLabelScope(),
getLocation(), exp));
m_stmts[i - length] = expStmt;
for (j = i - (length - 1); i > j; i--) removeElement(j);
@@ -413,6 +414,14 @@ void StatementList::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void StatementList::outputCodeModel(CodeGenerator &cg) {
for (unsigned int i = 0; i < m_stmts.size(); i++) {
m_stmts[i]->outputCodeModel(cg);
}
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+11
Ver Arquivo
@@ -188,6 +188,17 @@ void StaticStatement::inferTypes(AnalysisResultPtr ar) {
scope->getVariables()->clearAttribute(VariableTable::InsideStaticStatement);
}
///////////////////////////////////////////////////////////////////////////////
void StaticStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("StaticStatement", 2);
cg.printPropertyHeader("expressions");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+18
Ver Arquivo
@@ -185,6 +185,24 @@ void SwitchStatement::inferTypes(AnalysisResultPtr ar) {
}
}
///////////////////////////////////////////////////////////////////////////////
void SwitchStatement::outputCodeModel(CodeGenerator &cg) {
auto numProps = 2;
if (m_cases != nullptr) numProps++;
cg.printObjectHeader("SwitchStatement", numProps);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
if (m_cases != nullptr) {
cg.printPropertyHeader("caseStatements");
cg.printStatementVector(m_cases);
}
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
+11
Ver Arquivo
@@ -73,6 +73,17 @@ void ThrowStatement::inferTypes(AnalysisResultPtr ar) {
m_exp->inferAndCheck(ar, Type::Object, false);
}
///////////////////////////////////////////////////////////////////////////////
void ThrowStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("ThrowStatement", 2);
cg.printPropertyHeader("expression");
m_exp->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -103,6 +103,28 @@ void TraitAliasStatement::setNthKid(int n, ConstructPtr cp) {
void TraitAliasStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void TraitAliasStatement::outputCodeModel(CodeGenerator &cg) {
auto propCount = 3;
auto traitName = m_traitName->getString();
if (!traitName.empty()) propCount++;
cg.printObjectHeader("TraitAliasStatement", propCount);
if (!traitName.empty()) {
cg.printPropertyHeader("traitName");
cg.printValue(traitName);
}
cg.printPropertyHeader("methodName1");
m_methodName->outputCodeModel(cg);
cg.printPropertyHeader("modifiers");
m_modifiers->outputCodeModel(cg);
cg.printPropertyHeader("methodName2");
m_newMethodName->outputCodeModel(cg);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions
@@ -107,6 +107,21 @@ void TraitPrecStatement::setNthKid(int n, ConstructPtr cp) {
void TraitPrecStatement::inferTypes(AnalysisResultPtr ar) {
}
///////////////////////////////////////////////////////////////////////////////
void TraitPrecStatement::outputCodeModel(CodeGenerator &cg) {
cg.printObjectHeader("TraitInsteadStatement", 3);
cg.printPropertyHeader("traitName");
m_traitName->outputCodeModel(cg);
cg.printPropertyHeader("methodName");
m_methodName->outputCodeModel(cg);
cg.printPropertyHeader("otherTraitNames");
cg.printExpressionVector(m_otherTraitNames);
cg.printPropertyHeader("location");
cg.printLocation(this->getLocation());
cg.printObjectFooter();
}
///////////////////////////////////////////////////////////////////////////////
// code generation functions

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