Teach hhbbc to optimize away LockObj.
[hiphop-php.git] / hphp / hhbbc / representation.h
blobe0aa4f0661c36222c75f174dd7dda620fb4ecd18
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #ifndef incl_HHBBC_REPRESENTATION_H_
17 #define incl_HHBBC_REPRESENTATION_H_
19 #include <list>
20 #include <memory>
21 #include <string>
22 #include <tuple>
23 #include <unordered_map>
24 #include <utility>
25 #include <vector>
27 #include <boost/variant.hpp>
29 #include "hphp/util/atomic-vector.h"
30 #include "hphp/util/compact-vector.h"
31 #include "hphp/util/copy-ptr.h"
32 #include "hphp/util/sha1.h"
34 #include "hphp/runtime/base/user-attributes.h"
35 #include "hphp/runtime/vm/func.h"
36 #include "hphp/runtime/vm/preclass.h"
37 #include "hphp/runtime/vm/type-alias.h"
38 #include "hphp/runtime/vm/type-constraint.h"
40 #include "hphp/hhbbc/bc.h"
41 #include "hphp/hhbbc/misc.h"
42 #include "hphp/hhbbc/src-loc.h"
44 namespace HPHP { namespace HHBBC {
45 namespace php {
47 //////////////////////////////////////////////////////////////////////
49 struct Func;
50 struct ExnNode;
51 struct Unit;
53 //////////////////////////////////////////////////////////////////////
55 struct SrcInfo {
56 LineRange loc;
57 LSString docComment;
60 //////////////////////////////////////////////////////////////////////
63 * A basic block in our factored control flow graph.
65 * Blocks terminate on control flow, except exceptional control flow.
66 * We keep a set of "throw exits" representing all possible early
67 * exits due to exceptional control flow.
69 struct Block {
71 * The id of this block's ExnNode, or NoExnNodeId if there is none.
73 ExnNodeId exnNodeId{NoExnNodeId};
76 * Instructions in the block. Never empty guarantee.
78 BytecodeVec hhbcs;
81 * Edges coming out of blocks are repesented in three ways:
83 * - fallthrough edges (the end of the block unconditionally jumps
84 * to the named block). If fallthroughNS is true, this edge
85 * represents a no-surprise jump.
87 * - throwExit (the edges traversed for exceptions from this block)
89 * - Taken edges (these are encoded in the last instruction in hhbcs).
91 * For the idea behind the factored exit edge thing, see "Efficient
92 * and Precise Modeling of Exceptions for the Analysis of Java
93 * Programs" (http://dl.acm.org/citation.cfm?id=316171).
95 BlockId fallthrough{NoBlockId};
96 BlockId throwExit{NoBlockId};
97 bool catchEntry{false};
98 bool fallthroughNS{false};
99 bool multiPred{false};
100 bool multiSucc{false};
101 bool dead{false};
104 //////////////////////////////////////////////////////////////////////
107 * Exception regions.
109 * Each block in the program body can have a pointer to a node in the
110 * exception handler tree. This means they are in all the "exception
111 * regions" for each node in the tree down to that node. This
112 * information is used to construct exception handling regions at emit
113 * time.
115 * The catch region is described in bytecode.specification. Note though
116 * that although it's not specified there, in addition to an entry offset,
117 * these regions optionally list some information about iterators if the
118 * reason the region is there is to free iterator variables.
120 * Exceptional control flow is also represented more explicitly with
121 * factored exit edges (see php::Block). This tree structure just
122 * exists to get the EHEnts right.
125 struct CatchRegion { BlockId catchEntry;
126 Id iterId; };
128 struct ExnNode {
129 ExnNodeId idx;
130 uint32_t depth;
131 CompactVector<ExnNodeId> children;
132 ExnNodeId parent;
133 CatchRegion region;
136 //////////////////////////////////////////////////////////////////////
139 * Metadata about a parameter to a php function.
141 struct Param {
143 * Default value for this parameter, or KindOfUninit if it has no
144 * default value.
146 Cell defaultValue;
149 * Pointer to the block we'll enter for default-value initialization
150 * of this parameter, or nullptr if this parameter had no default
151 * value initializer.
153 BlockId dvEntryPoint;
156 * Information about the parameter's typehint, if any.
158 * NOTE: this is represented in the repo as a string type name and
159 * some TypeConstraint::Flags.
161 TypeConstraint typeConstraint;
164 * User-visible version of the type constraint as a string.
165 * Propagated for reflection.
167 LSString userTypeConstraint;
170 * Evalable php code that will give the default argument. This is
171 * redundant with the dv initializer, but gets propagated through
172 * for reflection.
174 LSString phpCode;
177 * Each parameter of a func can have arbitrary user attributes.
179 UserAttributeMap userAttributes;
182 * The type of the arguments for builtin functions, or for HNI
183 * functions with a native implementation. folly::none for
184 * non-builtins.
186 folly::Optional<DataType> builtinType;
189 * Whether this parameter is passed as inout.
191 bool inout: 1;
194 * Whether this parameter is passed by reference.
196 bool byRef: 1;
199 * Whether this parameter is a variadic capture.
201 bool isVariadic: 1;
204 template <typename T>
205 struct IntLikeIterator {
206 explicit IntLikeIterator(T v) : val{v} {}
207 T operator *() const { return val; }
208 T operator ++() { return ++val; }
209 bool operator !=(IntLikeIterator other) { return val != other.val; }
210 private:
211 T val;
214 template <typename T>
215 struct IntLikeRange {
216 explicit IntLikeRange(T v) : sz{v} {}
217 template<typename C>
218 explicit IntLikeRange(const C& v) : sz(v.size()) {}
219 IntLikeIterator<T> begin() const { return IntLikeIterator<T>{0}; }
220 IntLikeIterator<T> end() const { return IntLikeIterator<T>{sz}; }
221 private:
222 T sz;
226 * Metadata about a local variable in a function. Name may be
227 * nullptr, for unnamed locals.
229 struct Local {
230 LSString name;
231 uint32_t id : 31;
232 uint32_t killed : 1;
236 * Extra information for function with a HNI native implementation.
238 struct NativeInfo {
240 * Return type from the C++ implementation function, as an optional DataType;
241 * folly::none stands for a Variant return.
243 folly::Optional<DataType> returnType;
247 * Separate out the fields that need special attention when copying,
248 * so that Func can just have default copy/move semantics.
250 struct FuncBase {
251 FuncBase() = default;
252 FuncBase(const FuncBase&);
253 FuncBase(FuncBase&&) = delete;
254 FuncBase& operator=(const FuncBase&) = delete;
257 * All owning pointers to blocks are in this vector, which has the
258 * blocks in an unspecified order. Blocks use BlockIds
259 * to represent control flow arcs. The id of a block is its
260 * index in this vector.
262 CompactVector<copy_ptr<Block>> blocks;
264 auto blockRange() const { return IntLikeRange<BlockId> {blocks}; }
267 * Catch regions form a tree structure. The tree is hanging
268 * off the func here, with children ids. Each block that is
269 * within a catch region has the index into this array of the
270 * inner-most ExnNode protecting it.
272 * Note that this is updated during the concurrent analyze pass.
274 CompactVector<ExnNode> exnNodes;
277 * For HNI-based extensions, additional information for functions
278 * with a native-implementation is here. If this isn't a function
279 * with an HNI-based native implementation, this will be nullptr.
281 std::unique_ptr<NativeInfo> nativeInfo;
285 * Representation of a function, class method, or pseudomain function.
287 struct Func : FuncBase {
289 * An index, so we can lookup auxiliary structures efficiently
291 uint32_t idx;
294 * Basic information about the function.
296 LSString name;
297 SrcInfo srcInfo;
298 Attr attrs;
301 * Parameters, locals, class-refs, and iterators.
303 * There are at least as many locals as parameters (parameters are
304 * also locals---the names of parameters are stored in the locals
305 * vector).
307 IterId numIters;
308 ClsRefSlotId numClsRefSlots;
309 CompactVector<Param> params;
310 CompactVector<Local> locals;
313 * Which unit defined this function. If it is a method, the cls
314 * field will be set to the class that contains it.
316 Unit* unit;
317 Class* cls;
320 * Entry point blocks for default value initializers.
322 * Note that in PHP you can declare functions where some of the
323 * earlier parameters have default values, and later ones don't. In
324 * this case we'll have NoBlockIds after the first valid entry here.
326 CompactVector<BlockId> dvEntries;
329 * Entry point to the function when the number of passed args is
330 * equal to the number of parameters.
332 BlockId mainEntry;
335 * User-visible return type specification as a string. This is only
336 * passed through to expose it to reflection.
338 LSString returnUserType;
341 * If traits are being flattened by hphpc, we keep the original
342 * filename of a function (the file that defined the trait) so
343 * backtraces and things work correctly. Otherwise this is nullptr.
344 * Similarly, if hhbbc did the flattening itself, we need the original
345 * unit, to get to the srcLocs. Once we stop flattening in hphpc, we can
346 * drop the originalFilename.
348 LSString originalFilename;
349 Unit* originalUnit{};
352 * Whether or not this function is a top-level function. (Defined
353 * outside of any other function body.)
355 bool top : 1;
358 * This is the generated function for a closure body. I.e. this
359 * function contains the code that should run when the closure is
360 * invoked.
362 bool isClosureBody : 1;
365 * This is an async function.
367 bool isAsync : 1;
370 * This is a generator.
372 bool isGenerator : 1;
375 * This generator yields key value pairs.
377 bool isPairGenerator : 1;
379 bool isMemoizeWrapper : 1;
380 bool isMemoizeWrapperLSB : 1;
382 bool isMemoizeImpl : 1;
385 * This is a reified function.
387 bool isReified : 1;
389 bool isRxDisabled: 1;
391 bool noContextSensitiveAnalysis: 1;
394 * Return type specified in the source code (ex. "function foo(): Bar").
395 * HHVM checks if the a function's return value matches it's return type
396 * constraint via the VerifyRetType* instructions.
398 TypeConstraint retTypeConstraint;
401 * User attribute list.
403 UserAttributeMap userAttributes;
406 //////////////////////////////////////////////////////////////////////
409 * A class property.
411 * Both static and instance properties use this structure.
413 struct Prop {
414 LSString name;
415 Attr attrs;
416 UserAttributeMap userAttributes;
417 LSString docComment;
419 LSString userType;
420 TypeConstraint typeConstraint;
423 * The default value of the property, for properties with scalar
424 * initializers. May be KindOfUninit in some cases where the
425 * property should not have an initial value (i.e. not even null).
427 Cell val;
431 * A class constant.
433 struct Const {
434 LSString name;
436 // The class that defined this constant.
437 php::Class* cls;
440 * The value will be KindOfUninit if the class constant is defined
441 * using an 86cinit method.
443 * The lack of a value represents an abstract class constant.
445 folly::Optional<Cell> val;
448 * We pass through eval'able php code and a string type constraint,
449 * only for exposure to reflection.
451 LSString phpCode;
452 LSString typeConstraint;
454 bool isTypeconst : 1;
455 bool isNoOverride : 1;
459 * Similar to FuncBase - separate the fields that need special
460 * attention when copying.
462 struct ClassBase {
463 ClassBase() = default;
464 ClassBase(const ClassBase&);
465 ClassBase(ClassBase&&) = delete;
466 ClassBase& operator=(const ClassBase&) = delete;
469 * Methods on the class. If there's an 86cinit, it must be last.
471 CompactVector<std::unique_ptr<php::Func>> methods;
475 * Representation of a php class declaration.
477 struct Class : ClassBase {
479 * Basic information about the class.
481 LSString name;
482 SrcInfo srcInfo;
483 Attr attrs;
486 * The id used to reference the class within its unit
488 int32_t id;
491 * Which unit defined this class.
493 Unit* unit;
496 * Hoistability of this class. See the description in class.h
497 * formation on hoistability.
499 PreClass::Hoistable hoistability;
502 * Name of the parent class.
504 LSString parentName;
507 * If this class represents a closure, this points to the class that
508 * lexically contains the closure, if there was one. If this class
509 * doesn't represent a closure, this will be nullptr.
511 * The significance of this is that closures created lexically
512 * inside of a class run as if they were part of that class context
513 * (with regard to access checks, etc).
515 php::Class* closureContextCls;
518 * Names of inherited interfaces.
520 CompactVector<LowStringPtr> interfaceNames;
523 * Names of used traits, number of declared (i.e., non-trait, non-inherited)
524 * methods, trait alias/precedence rules (if any).
526 * This is using the exact structures from the runtime PreClass. In
527 * WholeProgram mode, we won't see these because traits will already be
528 * flattened.
530 CompactVector<LowStringPtr> usedTraitNames;
531 CompactVector<PreClass::ClassRequirement> requirements;
532 CompactVector<PreClass::TraitPrecRule> traitPrecRules;
533 CompactVector<PreClass::TraitAliasRule> traitAliasRules;
536 * Properties defined on this class.
538 CompactVector<Prop> properties;
541 * Constants defined on this class.
543 CompactVector<Const> constants;
546 * User attributes for this class declaration.
548 UserAttributeMap userAttributes;
551 * The underlying base type, if this is an enum
553 TypeConstraint enumBaseTy;
556 * This is a reified class.
558 bool hasReifiedGenerics : 1;
561 //////////////////////////////////////////////////////////////////////
563 using TypeAlias = ::HPHP::TypeAlias;
565 //////////////////////////////////////////////////////////////////////
567 * A record field
569 struct RecordField {
570 LSString name;
571 Attr attrs;
572 LSString userType;
573 LSString docComment;
574 Cell val;
575 TypeConstraint typeConstraint;
576 UserAttributeMap userAttributes;
579 * Representation of a Hack record
581 struct Record {
582 Unit* unit;
583 SrcInfo srcInfo;
584 LSString name;
585 LSString parentName;
586 Attr attrs;
587 int32_t id;
588 UserAttributeMap userAttributes;
589 CompactVector<RecordField> fields;
592 //////////////////////////////////////////////////////////////////////
594 * Representation of a php file (normal compilation unit).
596 struct Unit {
597 SHA1 sha1;
598 LSString filename;
599 bool isHHFile{false};
600 std::atomic<bool> persistent{true};
601 std::atomic<bool> persistent_pseudomain{false};
602 std::unique_ptr<Func> pseudomain;
603 CompactVector<std::unique_ptr<Func>> funcs;
604 CompactVector<std::unique_ptr<Class>> classes;
605 CompactVector<std::unique_ptr<Record>> records;
606 CompactVector<std::unique_ptr<TypeAlias>> typeAliases;
607 CompactVector<std::pair<SString,SString>> classAliases;
608 CompactVector<SrcLoc> srcLocs;
609 UserAttributeMap metaData;
610 UserAttributeMap fileAttributes;
614 * A php Program is a set of compilation units.
616 struct Program {
617 explicit Program(size_t numUnitsGuess) :
618 nextFuncId(0),
619 nextConstInit(0),
620 constInits(100 + (numUnitsGuess / 4), 0) {
623 std::vector<std::unique_ptr<Unit>> units;
624 std::atomic<uint32_t> nextFuncId;
625 std::atomic<size_t> nextConstInit;
626 AtomicVector<php::Func*> constInits;
629 //////////////////////////////////////////////////////////////////////
631 std::string show(const Func&);
632 std::string show(const Func&, const Block&);
633 std::string show(const Func&, const Bytecode& bc);
634 std::string show(const Class&, bool normalizeClosures = false);
635 std::string show(const Unit&, bool normalizeClosures = false);
636 std::string show(const Program&);
637 std::string local_string(const Func&, LocalId);
639 inline std::string show(const Func* f, const Bytecode& bc) {
640 return show(*f, bc);
643 //////////////////////////////////////////////////////////////////////
645 bool check(const Func&);
646 bool check(const Class&);
647 bool check(const Unit&);
648 bool check(const Program&);
650 //////////////////////////////////////////////////////////////////////
654 #endif