Continuation::send() uses m_received field to transfer the value inside
the continuation. This field remains set until the continuation is
iterated the next time.
Unset this field early by ContReceive so that the memory can be
reclaimed.
ZendPack::unpack() always returns a signed int32_t,
regardless of actual storage type being unpacked. For 32bit
unsigned types ('L', 'N', 'V', and 'I'(on I32 systems)) this
means overflowing in the helper and we have to explicitly
recast it to a uint64_t to get the data back out.
For LNV, this was already handled, it was missed for I.
Tx64 only translates CGetS when you do it with the context
class the same as the class being looked up, to avoid the need for
accessibility checks. The IR can translate it more often, but was
using its fast path even when it was not safe to do so: if a previous
(safe) access had allocated a targetcache entry, later accesses would
be able to get to the property without an access check. For now just
limit the optimiation to safe cases.
They both returned the late static bound class, not the context
class. This meant that eg "constant('self::FOO')" was actually
returning what "constant('static::FOO')" should have done.
In addition, we often want the Class*, not its name, so
change them to return Class*. The remaining places that then
read the name from the Class* should be fixed to use the Class*
directly (in a later diff).
Finally, noticed that while "defined()" was recently fixed to
support "static::", "constant()" was not. Pulled out a common
function to find the correct Class*.
In the case where m_this was already in a register,
and known to be non-zero, we would fail to zero the ActRec's
m_this field, which could result in a dangling reference
to $this being captured by debug_backtrace.
Put the store on the presumably cold path. Fix DecRefThis to
do the same.
The interpreter fix was different than the jit/ir fix because ##translateFPushObjMethodD()##'s ##i.inputs[0]->rtt.valueClass()## is null (with a TODO in the code to make it not null). It then goes into the slowpath.
Another one like this and I think I should have a different attribute for static closures :(
The only places where ReturnStatement is constructed are:
- onReturn(check_yield=true) -> not allowed in generator
- onReturn(check_yield=false) -> coming from transform_yield_break, right after creating hphp_continuation_done()
- MethodStatement, end of function call -> hphp_continuation_done() is created at end of generator in prepare_generator()
Emitter is emitting ContExit in ReturnStatements used in generators. As
can be seen from the analysis above, it's always preceded by emitting
ContDone from hphp_continuation_done(). Let's emit ContDone inside the
ReturnStatement directly and kill usage of hphp_continuation_done().
transform_yield_break() becomes a simple onReturn(check_yield=false), so
let's inline it into onYield and create ReturnStatement directly. After
this change, check_yield flag is always true and can be killed.
ContExit was also used after emitting a generator method in case the end
of method is still reachable. ContDone is added so that the generator is
properly closed. I believe this is never actually used, as MethodStatement
creates ReturnStatement at the end of method anyway.
Unhack the parser and introduce YieldExpression that emits the
equivalent set of opcodes that were emitted by bunch of
expressions/statements generated by parser before.
YieldExpression expects evaluation stack to contain just the value
being yielded, so {,List}AssignmentExpression need to evaluate RHS
first. The previous code had the same behavior.
This will let us consolidate continuation-related opcodes and make
them less tied with continuation objects.
Most of this is pretty boring and mechanical. I added
VectorProp and VectorElem flags to help deal with the increasing
number of vector-related opcodes.
I added the check for this in the interpreter but ##f_array_map## re-enteres the VM via a different path than FCall. Here is the equivilent check for the VM.
PHP added this in 5.4 so that you can say your closure shouldn't capture ##$this##. https://wiki.php.net/rfc/closures
Should we add it? Many of their unit tests use it.
Instead of putting a boolean somewhere I used the same attr framework and set the static bit there. Thoughts? It only needs one change in the ##FPushFunc##.
In Zend 5.3 they decided that closures should inherit the ##$this## from the containing scope. This brings us close to paraity with them. The remaining thing is to make
function() use ($this) {}
fatal after we purge it from WWW.
TestExtCurl was failing in the fbmake build, because for some
reason the other TestServer was being used. AFAICT it's within the
compiler's rights to do whatever it wants here, though.
The simplifier was not promoting the boolean to integer in some
cases. I hit this for the add-zero case, and code inspection revealed
similar bugs in sub-zero and multiply-one cases.
Any vector instructions that take a pointer to a base and might modify
it are now flagged with MayModifyStack. Any that actually do modify the stack
(this can be determined by looking at the input types) will produe two dests:
their original result and a new StkPtr. getStackValue calls into VectorEffects
to extract the new type and/or value. The instructions currently assume that
the stack cell they might be modifying is already synced to memory. This may
change in the future when we don't have to do a full SpillStack before the
helpers.
This mimics what TranslatorX64 does in translateSetMArray,
but it does it with fewer helpers and (often) fewer instructions in
translated code. I also found a bug in both jits and the interpreter
when dealing with arrays that hold refs to themselves. The new test
case exercises the fix, which involved a bit of refactoring of the
refcounting logic.
Enabling VectorTranslator while punting to tx64 is no longer a
regression so I removed the punt in emit().
uidna_openUTS46 overwrites its error code argument only if
there is actually an error. Hence, if the variable is not initialized to
zero it may seem to the calling code that an error has ocurred. This
diff initializes the variable and re-enables the failing test.
Bad memory allocation, the buffer needs to be large enough to fit all
the data we've decompressed so far plus the extra storage we're
incrementally allocationg, not just the incremental part.
This diff implements VectorTranslator::emitPropSpecialized and uses it
in three places: emitProp, emitSetProp, and emitCGetProp. The new test case in
test_code_run.cpp used to crash TranslatorX64; now it throws a fatal to keep
things simple. VectorTranslator has better control flow support at its disposal
and is able to get that case right.
Replace "collection" with "collections" in various file names since
we typically use the plural form in conversation and documentation.
Add set() and removeAt() methods needed for collection interfaces. Also
add the KeyedIterable and KeyedIterator interfaces.
Add __construct() methods for collections
This diff eliminates setOpEqual() and appendOpEqual() from Variant, and
it also removes several methods from ObjectData: o_assign_op(), o_argval(),
setDummy(), init(), cloneDynamic(), o_setPublicWithRef(), o_i_set(),
getRedeclaredParent(), and o_propForIteration().
This diff also makes several methods in ObjectData non-virtual: destruct(),
o_toIterArray(), and o_getDynamicProperties(). To achieve this, some of the
logic from Instance was moved to ObjectData.
Finally, this diff gets rid of "hhvm/externals_stubs.cpp" and
"runtime/eval/eval.cpp".
DecRef needs to be the last use of its source, since it might
destruct it. In the new test case, the second cast expression was
reusing the result of the first (through CSE) after it had been
DecReffed and destroyed.
Extend cgConv with support for converting to an array. Except for the trival cases of converting null to an empty array and converting arrays to arrays, which are handled in Simplifier, the conversion is delegated to a helper that calls tvCastToArrayInPlace on its input parameter and then returns the embedded array that results from the call. The helper also increases the ref count of operand to convert since tvCastToArrayInPlace assumes that updating the typed value passed to it will result in one fewer referenced to the argument.
In HPHPc it didn't allow closures to be cloned but in HHVM it did. When I migrated to a C++ closure then i left the HPHPc code. Zend 5.4 allows them to be cloned so lets go with this.
This actually was pretty broken already. If you defined a new function in the ##create_function## string it would return that function but it wouldn't move it to the right unit so it can't execute. A big mess. For example:
$ cat a.php
<?php
$a = create_function('', 'function b() { return 3; }');
$a();
var_dump(b());
$ php a.php
HipHop Fatal error: Undefined function: b in /data/users/ptarjan/hphp/hphp/a.php on line 4
$ hhvm a.php
int(3)