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.
Since TypedValue::operator= is dangerous, something like
tvTeleport is usually what you want to use, but it doesn't work with
temporary TypedValues (e.g. return values of things like make_tv or
cellAdd), because it took the arguments by pointer. This also means
we can change it to take parameters by value later without updating
callsites. This diff does the tvDup family and changes tvTeleport to
tvCopy. I'll gradually get the other ones done, but I just need these
for now to work with temporaries for changing SetOp to not use Variant
arithmetic.
Some simple changes for HPHP to help make it clang friendly
---hphp/compiler/package.cpp
---hphp/compiler/package.h
---hphp/runtime/ext/ext_curl.cpp
---hphp/runtime/ext/pdo_mysql.cpp
---hphp/tools/tc-print/offline-x86-code.h
---hphp/util/async_func.cpp
---hphp/util/async_func.h
---hphp/util/compression.cpp
---hphp/util/compression.h
---hphp/util/db_conn.cpp
---hphp/util/db_conn.h
Deleted unused private fields
~~~hphp/compiler/analysis/symbol_table.h
Static assert had to be outside the union
+++hphp/runtime/TARGETS
Added clang specific flag to supress unneded declaration warning
~~~hphp/runtime/base/datatype.h
Use of logical '&&' with constant operand. Added !=0 to remove warning,
~~~hphp/runtime/base/string_data.h
Static fields cannot be declared in an anonymous struct/union
~~~hphp/runtime/ext/bcmath/TARGETS
Moved gcc specific flag from preprocessor_flags to compiler_specific_flags
~---hphp/runtime/ext/pdo_mysql.cpp
Removed unnecessary self asignment for row_count
~~~hphp/runtime/vm/bytecode.h
Added default return statement
~---hphp/runtime/vm/jit/codegen.cpp
spillSlotsToSize was unused
~~~hphp/runtime/vm/jit/irtranslator.cpp
~~~hphp/runtime/vm/jit/linearscan.cpp
The c++ standard states default arguments shall not be specified in the
parameter-declaration-clause of a lambda-declarator.
~~~hphp/runtime/vm/jit/vectortranslator-internal.h
Clang had some issues determining the correct cast when these macros were used
A simple '!= 0' check was added to make things explicit for clang.
~~~hphp/tools/tc-print/perf-events.h
Added parens to make clang happy
+++hphp/util/asm-x64.h
The constexpr needed to be initialized
+++hphp/util/base.h
Clang also supports tr1 libraries
~~~hphp/util/bits.h
Again, clang had issues with implicit casting to bool.
added != 0 check
~~~hphp/util/malloc_size_class.h
Ambiguous operator precedence. Added parentheses.
~~~hphp/util/thread_local.h
Misspelled function
Apparently VarEnv's m_previous is not used for anything. Let's kill its
maintenance and avoid 2 native calls per Continuation
next()/send()/raise() calls.
Move all the stack unwinding code to its own module, delete
some redundant enumerations, document a few things. Gets rid of most
of the remnants of the old setjmp/longjmp-based implementation at the
enterVM level but doesn't do much to the unwinder itself (coming in
separate diff to hopefully be easier to review).
Remove unnecessary optimization that can be achieved in a more general
way and simplify continuation creation code.
VMExecutionContext::createContinuationHelper was renamed to
VMExecutionContext::createCont{Func,Meth}. The createContFunc no longer
takes this/class arguments, the createContMeth transfers them in one
Type::Ctx pointer that is used natively by ActRec's m_this. Since the
whole logic of this function is to set this single field, the logic is
now simpler.
Interpreter: iopCreateCont() just passes the m_this field of the parent
ActRec.
Translator: CreateCont opcode loads m_this field using LdCtx opcode.
This opcode optimizes into LdThis, which optimizes into
DefInlineFP->SpillFrame->object and allows frame to be eliminated, a
case previously covered by InlineCreateCont.
This diff uncovered a bug in trace builder, where LdCtx in static
methods could be optimized into LdThis, if the method was called thru
object. Fixed.
I need to walk a live eval stack, handling FPI regions and
generators, and duplicating that logic in yet another place seems
wrong. This makes the Stack::toString stuff use a reusable one---at
some point I'll see if the unwinder can use it as well, but it works
also for my use case. Also, Stack::toString was broken for mutable
array iterators---fixes that. And use a union now for struct Iter.
And don't include bytecode.h from func.h.
The codebase had several namespace-level static data definitions and function definitions. Using namespace-level "static" in a .h file is near-always a bad idea, as follows:
- for simple types, static is implied. Example: "const int x = 42;" is the same as "static const int x = 42;"
- for aggregate types, static linkage implies that a copy of the aggregate will appear in every compilation unit that includes the header.
- for functions, static means the function will have a separate body generated in each compilation unit including the header.
- in several places functions were defined 'static inline', which is just as bad. 'inline' is just a hint which means the function may end up having a body (and actually more due to 'static').
True, gnu's linker has means to remove duplicate definition, but that's not always guaranteed or possible (think e.g. static functions that define static data inside, ouch). So static is useless at best and pernicious at worst. We should never, ever use static at namespace level in headers. I will create a bootcamp task for a lint rule.
I expected the performance to be neutral after the change, but in fact there's a significant drop in instruction count and therefore a measurable reduction in CPU time: https://our.intern.facebook.com/intern/perflab/details.php?eq_id=431903
If it's an AR for a constructor, the high-order bit is set, and it gets printed
as -2 billion. This is confusing; at first I thought it was a bug. Print it out
in a readable way.
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
PolicyArray splits the ArrayData implementation in two parts. ArrayShell implements the baroque ArrayData implementation in terms of a much smaller statically-bound core that concerns itself exclusively with the storage strategy for the array. This way the two aspects can be worked on separately, and different stores can be easily plugged into the given ArrayShell.
To give a better perspective, the featured SimpleArrayStore has about 340 lines all told (including solid documentation), whereas ArrayShell has some 1100 lines. The shell can be reused with other stores of unbounded sophistication. The store needs to implement only 22 primitives, some of which are trivial. Basically a new store implementation saves 1100 of difficult-to-get-right lines of code right off the bat, and only needs to focus on implementing 22 well-defined primitives.
Things to watch for when reviewing:
- Is the store API small/expressive enough? What should be added/removed?
- Are various forms of duplication present? If so, how could code be factored better?
- Any subtle change in semantics from HphpArray and friends that should be minded?
Known issues:
* Currently ArrayShell is defined as:
class ArrayShell : public ArrayData, private SimpleArrayStore { ... };
when in fact it should be:
template <class StorePolicy>
class ArrayShell : public ArrayData, private StorePolicy { ... };
Extenuating circumstances related to allocator design prevent use of templates at this point. I'll work on these in parallel with the review.
* growNoResize is almost always prefaced by a test-and-grow. This sequence should be encoded in a function.
* The growth policy is spread all over the place in a subtle form of duplication.
* The current store design makes almost no effort to be particularly efficient.
I did an experiment turning off all stack checks, and it
looks like it does cost something. This seemed like an easy way to
turn it off some of the time, but maybe we should resurrect the SEGV
handler.
Sets up the translator analyze pass to create a Tracelet for
the callee at every statically-known FCall. If the callee has an
appropriate shape (in this diff, it must be a function consisting of
"return $this->foo" for a declared property), we can inline it in
HHIR. Restructures the IR relating to frames some so we can eliminate
the stores relating to ActRec in this simple case (see the comments in
dce.cpp and hhbctranslator.cpp for details). Includes partial support
for inlining callees with locals, but it's disabled for now because
they will keep the frame live.
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.
I've found several bugs recently due to the TypedValue plausible
check being too loose. Our DataType enum values are now sparse,
and we miss garbage that happens to fall inside the [-10, 127]
range, which is >50% of possible garbage values.
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.
This diff removes initializing stores to TypedValue._count, renames
_count to m_aux, and makes m_aux a union with members typed
and named according to their specialized uses. The few remaining
uses of that field for random tweaks are more obvious and easy to
grep for.
TypedValue no longer extends Value, (allowing m_data to move to a
different offset in the future), and Variant now extends TypedValue,
so we only have to maintain one definition.
HphpArray now explicitly uses TypedValue.m_pad instead of overlapping
TypedValue with an anonymous struct, again so we don't have to maintain
another structure to match TypedValue's layout.
The JIT's were using offsetof(TypedValue, _count) all over the place
for access to String/Array/Object/RefData::_count. Instead, use
FAST_REFCOUNT_OFFSET.
It's not ok for the unwinder to use a reference to elements
living in the m_faults array, since the unwinder can re-enter the VM
when calling destructors (or the FunctionExit hook). If one of those
re-entries does exception handling, it can modify m_faults.
Additionally, gets rid of VMPrepareThrow and instead just throw Object
and use the same case as we do when exceptions came from an extension.
I had to fix an assembler test catch handler to actually catch to keep
the assertion about m_faults on re-entry correct.
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.