When object support was first added to HHVM, a class named "Instance"
was introduced (deriving from ObjectData) to represent instances of user
defined classes. Since then, things have evolved and HPHPc and HPHPi have
been retired, and now there really is no needed to have ObjectData and
Instance be separate classes anymore.
As a first step towards merging ObjectData and Instance together, this diff
puts their definitions in the same .h file and puts their implementations
in the same .cpp file. A few small changes were necessary to fix issues
with cyclical includes: (1) Repo/emitter related parts of class.cpp and
class.h were moved to class-emit.cpp and class-emit.h; (2) the contents of
"vm/core_types.h" was moved to "base/types.h"; and (3) a few functions that
didn't appear to be hot were moved from .h files and the corresponding .cpp
files.
This diff removes the Marker opcode, replacing it with a BCMarker
struct in each IRInstruction. This gives us fewer redundant lines in IRTrace
dumps and allows for more straightforward control of which IRInstructions are
associated with which bytecodes. I took this opportunity to do some more
cleanup of ir dumps as well, and it's now possible to interpOne every codegen
punt.
Replace NameDef with a new struct of runtime-resolved typedef
information. This needs to include more than Class* or Typedef*,
because we might have nullable type aliases, or a non-nullable alias
to a nullable typedef, or vice versa. Switch to the new
TypeAnnotation stuff in TypedefStatement instead of just strings so
support for this isn't weird (shapes are outside of this for now
though---see the hack in parser.cpp). Also fixes support for type
aliases to mixed.
Because stronger types are better types, and this will make
future refactoring easier. I considered trying to purge the Opcode
type from the codebase too but that would be a much bigger project.
The value of m_feMap is never used. Keys are used to assert when there
is an attempt to define a function with already existing name. It does
this job poorly because it is not an authoritative source of existing
function names. When the top-level function is defined, setCached() is
called, which already checks for duplicates, so let's rely on it.
Contains some structures to use for communicating between
compilation region selectors and the JIT. For now includes two
debugging-oriented region selectors, one that uses a single HHBC
opcode at a time, and one that blindly pushes in the whole CFG for a
method using the Verifier::GraphBuilder.
Throws the aliased class into a target cache slot for the new
name. Handles errors when you try to re-alias a class, but doesn't
restrict a few other cases zend does:
- If you implement an interface twice, zend complains (one of the
alias tests checks this). I tried turning it on, but we violate
it in systemlib currently so I left it off.
- class_alias_014.php does some namespace stuff I don't quite grok.
(@ptarjan let me know what to do if it's easy).
- inter_007.php uses class_alias, but is testing a warning that
happens even with out it. (We don't raise this warning.)
- zend raises a warning if you try to class_alias a non-user-defined
class; I left this out.
I was going to #include translator.h in a header I had for
talking to the region selector thing and decided to just get this over
with instead. (It shouldn't need to #include that.) Found a few
other unused things to remove while at it.
This was barely a demonstrable win in sandbox mode when I first wrote
it and it's not even used in hhir. It's probably been bitrotting and is causing
crashes for some people. Time to say goodbye.
Will be needed for array_filter/array_map etc
This sets things up so that if we define a builtin in systemlib, we rename
the corresponding c++ builtin with the prefix __builtin_, so its still available
(in case the php builtin wants to delegate some edge cases, and to make
it easy to run comparisons between the php and c++ implementations).
Also did a little reorganization to get rid of Func::isPHPBuiltin,
and use an Attr to identify functions as builtins. C++ builtins can
still be identified by checking the Func::info() method. This is needed
to allow builtin methods defined in php (such as array_map) to lookup their
arguments in the correct context.
The Func*'s in the native func unit are all persistent, which means
that we can strip them, and skip the Unit::merge call on every
request. But we didnt set the flag to compact the unit if the only
things that needed stripping were Func*'s. Fixed that, and also fixed
it so all the builtins are marked persistent even in non-repo-auth
mode (funcs are not if rename function is enabled, because we implement
fb_rename_function by swapping target cache entries).
I was learning from @jdelong and he said that you should use
double quotes for local includes and angle brackets for library
includes. I asked why our code was the way it was, and he said he wanted
to clean it up. I beat him to it :)
Conflicts:
hphp/runtime/base/server/admin_request_handler.cpp
hphp/runtime/vm/named_entity.h
This func took 2 params and ignored the second one. While I was there I made the functions call eachother. Hopefully inlining is smart enough to let me clean this code.
I got a bit carried away, but I think this is better.
This cleans up the code a lot, and takes it out of various hot
paths. It will impact perf for requests where intercepts are used,
but no longer penalizes requests that don't use intercepts.
This is a partial step towards merging the HPHP::VM namespace
up into its parent. To keep it reviewable/mergeable I'm not doing
everything at once here, but most of the code I've touched seems
improved. I've drawn an invisible line around the jit, Unit and
its cohort (Class, Func, PreClass, etc.); we'll get back to them
soon.
Make the targetcache the one true home for constants,
so we dont need to (also) insert them all into
VMExecutionContext::m_constants (which is now gone).
By also making "non-volatile" constants persistent, we save
initializing most of them at all in RepoAuthoritative mode.
The CreateCl translation dereferenced its targetcache handle
at compile time instead of in the TC, so we could get "class
undefined" errors if the targetcache slot in the thread that jitted it
didn't happen to have that closure defined. Fix that, combine the two
helper calls, and use nativecalls so we get register precoloring.
While investigating why gcc-4.7.1 is slower than gcc-4.6.2,
I noticed that under 4.6.2 the tbb code was being inlined into
Unit::GetNamedEntity, but under 4.7.1 it wasn't. Perf showed that
the inclusive time for GetNamedEntity was about .4% higher under
gcc-4.7.1.
Meanwhile, after various code changes, gcc-4.6.2 is no longer
inlining the tbb code either. Playing with the inlining options,
I wasnt able to get either version of gcc to inline it anymore,
but using __attribute__((__flatten__)) works for both. But that
also causes a bunch of other, slow-path code to be inlined, so
split it into a hot and a cold function, and flatten the hot
function.
Perf shows about a .2% win for Unit::GetNamedEntiry under gcc-4.6.2
Only in RepoAuthoritative mode, where units can't be
deallocated. I have a semi-reproducable bug where a unit's m_bc
region is getting corrupted (only occasionally in perflab).
Presumably moving it out of the malloc'd heap will make the bug
corrupt something else, so this probably doesn't really help much, but
it seemed like having a separate region for some cold, read-only,
process-lifetime metadata might make sense.
Adds runtime support for non-class typehints. Typedefs are
introduced using type statements, and autoloaded via a new autoload
map entry. Shapes are parsed but the structure is currently thrown
away and treated as arrays at runtime. This extends the NamedEntity
structure to sometimes cache 'NameDefs', which are either Typedef*'s
or Class*'s. VerifyParamType now has to check for typedefs if an
object fails a class check, or when checking non-Object types against
a non-primitive type name that isn't a class.
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.
The translator does better in a number of places when it
knows an AttrUnqiue Class* at translation time - even if it
doesnt know for sure that it will be defined when we enter the
tracelet. Now that we autoload (nearly) everything, we enter
a lot of tracelets where an AttrUnique Class* has been seen
(during warmup) but is not yet defined (in this request).
I added lookupUniqueClass while working on the new autoloader
to find such Classes, and allow us to do a better translation,
but never got around to using it.
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)
I found some byte-wide padding in Unit and UnitEmitter that we can
use to store the mergeOnly flag, instead of m_returnValue's unused
_count field. This is one step towards eliminating TV._count.
This turns the output into three columns: tx64 asm, hhir asm,
then pretty-printed hhir with asm inline. This should help us figure
out what the ir is doing wrong when it makes bigger code. I also
compacted the output of Trace::print a bit and changed it to print
unlikely blocks at the very end.
This diff refactors some of the VM's logic for iterators (with a focus on
mutable iteration), delivering several improvements:
1) MIterCtx was renamed to MArrayIter, and the m_key and m_val fields
were eliminated.
2) Eliminated the need for MArrayIter to dynamically allocate a
MutableArrayIter object, and removed other layers of indirection as
well.
3) Reduced the size of HPHP::VM::Iter from 64 bytes down to 32 bytes.
4) Removed the "if (siPastEnd())" check when adding a new element to an
HphpArray or a ZendArray.
5) Moved all of the iterator logic into a single .cpp file.
This diff reworks FullPos's to point to current element instead of pointing
to the next element. It also splits up the IterFree instruction into two
instructions (IterFree and MIterFree). These changes allowed various logic
to be simplified and data structures to be reduced in size. There is
definitely more opportunity for refactoring, but I know the JIT helpers for
iteration have been carefully tuned and so I'll leave further refactoring
for future diffs.
Finally, I spent a little time cleaning up the bytecode spec a bit, mostly
with respect to iteration.
This change is mostly for FB internal organizational reasons.
Building is not effected beyond the fact that the target now
lands in hphp/hhvm/hhvm rather than src/hhvm/hhvm.