Add support for HHBC ops with 5 immediates
[hiphop-php.git] / hphp / runtime / base / variable-serializer.h
blob64a8328533b42676e714314cf100642d74a43172
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 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_VARIABLE_SERIALIZER_H_
18 #define incl_HPHP_VARIABLE_SERIALIZER_H_
20 #include "hphp/runtime/base/string-buffer.h"
21 #include "hphp/runtime/base/string-data.h"
22 #include "hphp/runtime/base/runtime-option.h"
23 #include "hphp/runtime/base/req-containers.h"
24 #include "hphp/runtime/base/tv-mutate.h"
25 #include "hphp/runtime/base/tv-variant.h"
26 #include "hphp/runtime/vm/class.h"
28 #include <boost/noncopyable.hpp>
30 namespace HPHP {
31 ///////////////////////////////////////////////////////////////////////////////
33 /**
34 * Maintaining states during serialization of a variable. We use this single
35 * class to uniformly serialize variables according to different formats.
37 struct VariableSerializer {
38 /**
39 * Supported formats.
41 enum class Type {
42 PrintR, //print_r()
43 VarExport, //var_export()
44 VarDump, //var_dump()
45 DebugDump, //debug_zval_dump()
46 DebuggerDump, //used by hphp debugger to obtain user visible output
47 Serialize, // serialize()
48 Internal, // used internally by the compiler. No compatibility guarantees.
49 JSON, //json_encode()
50 APCSerialize, //used in APC serialization (controlled by switch)
51 DebuggerSerialize, //used by hphp debugger for client<->proxy communication
52 PHPOutput, //used by compiler to output scalar values into byte code
55 /**
56 * Constructor and destructor.
58 explicit VariableSerializer(Type type, int option = 0, int maxRecur = 3);
59 ~VariableSerializer();
60 VariableSerializer(const VariableSerializer&) = delete;
61 VariableSerializer& operator=(const VariableSerializer&) = delete;
63 // Use UnlimitSerializationScope to suspend this temporarily.
64 static __thread int64_t serializationSizeLimit;
66 /**
67 * Top level entry function called by f_ functions.
69 String serialize(const Variant& v, bool ret, bool keepCount = false);
70 String serializeValue(const Variant& v, bool limit);
72 // Serialize with limit size of output, always return the serialized string.
73 // It does not work with Serialize, JSON, APCSerialize, DebuggerSerialize.
74 String serializeWithLimit(const Variant& v, int limit);
76 // for ext_json
77 void setDepthLimit(size_t depthLimit) { m_maxDepth = depthLimit; }
78 // for ext_std_variable
79 void incMaxCount() { m_maxCount++; }
81 Type getType() const { return m_type; }
83 // By default, for Type::Serialize, d/varrays are serialized as normal
84 // arrays. This flag can override that behavior.
85 void keepDVArrays() { m_keepDVArrays = true; }
87 // Force Hack arrays to serialize as PHP arrays
88 void setForcePHPArrays() { m_forcePHPArrays = true; }
90 // Emit a Hack array compat notice on Hack array serialization
91 void setHackWarn() { m_hackWarn = true; }
93 // Emit a Hack array compat notice on PHP array serialization
94 void setPHPWarn() { m_phpWarn = true; }
96 enum class ArrayKind { PHP, Dict, Vec, Keyset, VArray, DArray };
98 private:
99 /**
100 * Type specialized output functions.
102 void write(bool v);
103 void write(char v) { write((int64_t)v);}
104 void write(short v) { write((int64_t)v);}
105 void write(int v) { write((int64_t)v);}
106 void write(int64_t v);
107 void write(double v);
109 void write(const char *v, int len = -1, bool isArrayKey = false,
110 bool noQuotes = false);
112 void write(const String& v);
113 void write(const Object& v);
114 void write(const Variant& v, bool isArrayKey = false);
116 void writeNull();
117 // what to write if recursive level is over limit?
118 void writeOverflow(const TypedValue& tv);
119 void writeRefCount(); // for DebugDump only
121 void writeArrayHeader(int size, bool isVectorData, ArrayKind kind);
122 void writeArrayKey(const Variant& key, ArrayKind kind);
123 void writeArrayValue(
124 const Variant& value,
125 ArrayKind kind
127 void writeCollectionKey(
128 const Variant& key,
129 ArrayKind kind
131 void writeArrayFooter(ArrayKind kind);
132 void writeSerializableObject(const String& clsname, const String& serialized);
135 * Helpers.
137 void indent();
138 void setReferenced(bool referenced) { m_referenced = referenced;}
139 void setRefCount(int count) { m_refCount = count;}
140 bool incNestedLevel(const TypedValue& tv);
141 void decNestedLevel(const TypedValue& tv);
142 void pushObjectInfo(const String& objClass, int objId, char objCode);
143 void popObjectInfo();
144 void pushResourceInfo(const String& rsrcName, int rsrcId);
145 void popResourceInfo();
147 ArrayKind getKind(const ArrayData* arr) const;
149 // Sentinel used to indicate that a member of SavedRefMap has a count but no ID.
150 static constexpr int NO_ID = -1;
152 struct SavedRefMap {
153 ~SavedRefMap();
155 struct MapData : boost::noncopyable {
156 MapData() : m_count(0), m_id(-1) { }
157 int m_count;
158 int m_id;
161 MapData& operator[](const TypedValue& tv) {
162 auto& elm = m_mapping[tv];
163 if (!elm.m_count) tvIncRefGen(tv);
164 return elm;
167 const MapData& operator[](const TypedValue& tv) const {
168 return m_mapping.at(tv);
171 private:
172 struct TvHash {
173 std::size_t operator()(const TypedValue& tv) const {
174 return pointer_hash<void>()(tv.m_data.parr);
178 struct TvEq {
179 bool operator()(const TypedValue& a, const TypedValue& b) const {
180 return a.m_data.parr == b.m_data.parr;
184 req::hash_map<TypedValue, MapData, TvHash, TvEq> m_mapping;
187 Type m_type;
188 int m_option; // type specific extra options
189 StringBuffer *m_buf;
190 int m_indent;
191 SavedRefMap m_refs; // reference ids and counts for objs/arrays
192 int m_valueCount; // Current ref index
193 bool m_referenced; // mark current array element as reference
194 bool m_keepDVArrays; // serialize d/varrays as themselves or arrays
195 bool m_forcePHPArrays; // serialize PHP and Hack arrays as PHP arrays
196 bool m_hackWarn; // warn when attempting on Hack arrays
197 bool m_phpWarn; // warn when attempting on PHP arrays
198 bool m_hasHackWarned; // have we already warned on Hack arrays?
199 bool m_hasPHPWarned; // have we already warned on PHP arrays?
200 int m_refCount; // current variable's reference count
201 String m_objClass; // for object serialization
202 int m_objId; // for object serialization
203 char m_objCode; // for object serialization
204 String m_rsrcName; // for resource serialization
205 int m_rsrcId; // for resource serialization
206 int m_maxCount; // for max recursive levels
207 int m_levelDebugger; // keep track of levels for DebuggerSerialize
208 int m_maxLevelDebugger; // for max level of DebuggerSerialize
209 size_t m_currentDepth; // current depth (nasted objects/arrays)
210 size_t m_maxDepth; // max depth limit before an error (0 -> none)
212 struct ArrayInfo {
213 bool is_object; // nested arrays or objects
214 bool is_vector; // whether current array is a vector
215 bool first_element; // whether this is first array element
216 int indent_delta; // the extra indent to serialize this object
217 int size; // the number of elements in the array
219 req::vector<ArrayInfo> m_arrayInfos;
221 struct ObjectInfo {
222 String objClass;
223 int objId;
224 char objCode;
225 String rsrcName;
226 int rsrcId;
228 req::vector<ObjectInfo> m_objectInfos;
230 // The func parameter will be invoked only if there is no overflow.
231 // Otherwise, writeOverflow will be invoked instead.
232 void preventOverflow(const Object& v, const std::function<void()>& func);
233 void writePropertyKey(const String& prop);
235 void serializeRef(const TypedValue* tv, bool isArrayKey);
236 // Serialize a Variant recursively.
237 // The last param noQuotes indicates to serializer to not put the output in
238 // double quotes (used when printing the output of a __toDebugDisplay() of
239 // an object when it is a string.
240 void serializeVariant(const Variant&,
241 bool isArrayKey = false,
242 bool skipNestCheck = false,
243 bool noQuotes = false);
244 void serializeObject(const Object&);
245 void serializeObject(const ObjectData*);
246 void serializeObjectImpl(const ObjectData* obj);
247 void serializeCollection(ObjectData* obj);
248 void serializeArray(const Array&, bool isObject = false);
249 void serializeArray(const ArrayData*, bool skipNestCheck = false);
250 void serializeArrayImpl(const ArrayData* arr);
251 void serializeResource(const ResourceData*);
252 void serializeResourceImpl(const ResourceData* res);
253 void serializeString(const String&);
255 Array getSerializeProps(const ObjectData* obj) const;
258 inline String internal_serialize(const Variant& v) {
259 VariableSerializer vs{VariableSerializer::Type::Internal};
260 return vs.serializeValue(v, false);
263 // TODO: Move to util/folly?
264 template<typename T> struct TmpAssign {
265 TmpAssign(T& v, const T tmp) : cur(v), save(cur) { cur = tmp; }
266 ~TmpAssign() { cur = save; }
267 T& cur;
268 const T save;
271 struct UnlimitSerializationScope {
272 static constexpr int32_t kTmpLimit = StringData::MaxSize;
273 TmpAssign<int64_t> v{VariableSerializer::serializationSizeLimit, kTmpLimit};
274 TmpAssign<int64_t> rs{RuntimeOption::SerializationSizeLimit, kTmpLimit};
275 TmpAssign<int32_t> rm{RuntimeOption::MaxSerializedStringSize, kTmpLimit};
278 extern const StaticString s_serializedNativeDataKey;
280 ///////////////////////////////////////////////////////////////////////////////
283 #endif // incl_HPHP_VARIABLE_SERIALIZER_H_