PageRenderTime 55ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/hphp/runtime/base/apc-handle.cpp

https://gitlab.com/iranjith4/hhvm
C++ | 245 lines | 203 code | 20 blank | 22 comment | 20 complexity | 889637c39086642d3c7d3054f7833980 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-2016 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. +----------------------------------------------------------------------+
  15. */
  16. #include "hphp/runtime/base/apc-handle.h"
  17. #include "hphp/runtime/base/apc-typed-value.h"
  18. #include "hphp/runtime/base/apc-string.h"
  19. #include "hphp/runtime/base/apc-array.h"
  20. #include "hphp/runtime/base/apc-object.h"
  21. #include "hphp/runtime/base/apc-collection.h"
  22. #include "hphp/runtime/base/mixed-array.h"
  23. #include "hphp/runtime/ext/apc/ext_apc.h"
  24. #include "hphp/runtime/base/apc-local-array.h"
  25. #include "hphp/runtime/base/apc-local-array-defs.h"
  26. namespace HPHP {
  27. //////////////////////////////////////////////////////////////////////
  28. APCHandle::Pair APCHandle::Create(const Variant& source,
  29. bool serialized,
  30. APCHandleLevel level,
  31. bool unserializeObj) {
  32. auto type = source.getType(); // this gets rid of the ref, if it was one
  33. switch (type) {
  34. case KindOfUninit: {
  35. auto value = APCTypedValue::tvUninit();
  36. return {value->getHandle(), sizeof(APCTypedValue)};
  37. }
  38. case KindOfNull: {
  39. auto value = APCTypedValue::tvNull();
  40. return {value->getHandle(), sizeof(APCTypedValue)};
  41. }
  42. case KindOfBoolean: {
  43. auto value = source.getBoolean() ? APCTypedValue::tvTrue()
  44. : APCTypedValue::tvFalse();
  45. return {value->getHandle(), sizeof(APCTypedValue)};
  46. }
  47. case KindOfInt64: {
  48. auto value = new APCTypedValue(source.getInt64());
  49. return {value->getHandle(), sizeof(APCTypedValue)};
  50. }
  51. case KindOfDouble: {
  52. auto value = new APCTypedValue(source.getDouble());
  53. return {value->getHandle(), sizeof(APCTypedValue)};
  54. }
  55. case KindOfPersistentString:
  56. case KindOfString: {
  57. StringData* s = source.getStringData();
  58. if (serialized) {
  59. // It is priming, and there might not be the right class definitions
  60. // for unserialization.
  61. return APCString::MakeSerializedObject(apc_reserialize(String{s}));
  62. }
  63. if (s->isStatic()) {
  64. auto value = new APCTypedValue(APCTypedValue::StaticStr{}, s);
  65. return APCHandle::Pair{value->getHandle(), sizeof(APCTypedValue)};
  66. }
  67. auto const st = lookupStaticString(s);
  68. if (st) {
  69. auto value = new APCTypedValue(APCTypedValue::StaticStr{}, st);
  70. return {value->getHandle(), sizeof(APCTypedValue)};
  71. }
  72. if (level == APCHandleLevel::Outer && apcExtension::UseUncounted) {
  73. auto st = StringData::MakeUncounted(s->slice());
  74. auto value = new APCTypedValue(APCTypedValue::UncountedStr{}, st);
  75. return {value->getHandle(), st->size() + sizeof(APCTypedValue)};
  76. }
  77. return APCString::MakeSharedString(s);
  78. }
  79. case KindOfPersistentArray:
  80. case KindOfArray: {
  81. auto ad = source.getArrayData();
  82. if (ad->isStatic()) {
  83. auto value = new APCTypedValue(APCTypedValue::StaticArr{}, ad);
  84. return {value->getHandle(), sizeof(APCTypedValue)};
  85. }
  86. return APCArray::MakeSharedArray(source.getArrayData(), level,
  87. unserializeObj);
  88. }
  89. case KindOfObject:
  90. if (source.getObjectData()->isCollection()) {
  91. return APCCollection::Make(source.getObjectData(),
  92. level,
  93. unserializeObj);
  94. }
  95. return unserializeObj ? APCObject::Construct(source.getObjectData()) :
  96. APCString::MakeSerializedObject(apc_serialize(source));
  97. case KindOfResource:
  98. // TODO Task #2661075: Here and elsewhere in the runtime, we convert
  99. // Resources to the empty array during various serialization operations,
  100. // which does not match Zend behavior. We should fix this.
  101. return APCArray::MakeSharedEmptyArray();
  102. case KindOfRef:
  103. case KindOfClass:
  104. return {nullptr, 0};
  105. }
  106. not_reached();
  107. }
  108. Variant APCHandle::toLocal() const {
  109. switch (m_kind) {
  110. case APCKind::Uninit:
  111. case APCKind::Null:
  112. return init_null(); // shortcut.. no point to forward
  113. case APCKind::Bool:
  114. return APCTypedValue::fromHandle(this)->getBoolean();
  115. case APCKind::Int:
  116. return APCTypedValue::fromHandle(this)->getInt64();
  117. case APCKind::Double:
  118. return APCTypedValue::fromHandle(this)->getDouble();
  119. case APCKind::StaticString:
  120. case APCKind::UncountedString:
  121. return Variant{APCTypedValue::fromHandle(this)->getStringData(),
  122. Variant::PersistentStrInit{}};
  123. case APCKind::SharedString:
  124. return Variant::attach(
  125. StringData::MakeProxy(APCString::fromHandle(this))
  126. );
  127. case APCKind::StaticArray:
  128. case APCKind::UncountedArray:
  129. return Variant{APCTypedValue::fromHandle(this)->getArrayData(),
  130. Variant::PersistentArrInit{}};
  131. case APCKind::SerializedArray: {
  132. auto const serArr = APCString::fromHandle(this)->getStringData();
  133. return apc_unserialize(serArr->data(), serArr->size());
  134. }
  135. case APCKind::SharedArray:
  136. case APCKind::SharedPackedArray:
  137. return Variant::attach(
  138. APCLocalArray::Make(APCArray::fromHandle(this))->asArrayData()
  139. );
  140. case APCKind::SerializedObject: {
  141. auto const serObj = APCString::fromHandle(this)->getStringData();
  142. return apc_unserialize(serObj->data(), serObj->size());
  143. }
  144. case APCKind::SharedCollection:
  145. return APCCollection::fromHandle(this)->createObject();
  146. case APCKind::SharedObject:
  147. return APCObject::MakeLocalObject(this);
  148. }
  149. not_reached();
  150. }
  151. void APCHandle::deleteShared() {
  152. assert(checkInvariants());
  153. switch (m_kind) {
  154. case APCKind::Uninit:
  155. case APCKind::Null:
  156. case APCKind::Bool:
  157. return;
  158. case APCKind::Int:
  159. case APCKind::Double:
  160. case APCKind::StaticString:
  161. case APCKind::StaticArray:
  162. delete APCTypedValue::fromHandle(this);
  163. return;
  164. case APCKind::SharedString:
  165. case APCKind::SerializedArray:
  166. case APCKind::SerializedObject:
  167. APCString::Delete(APCString::fromHandle(this));
  168. return;
  169. case APCKind::SharedPackedArray:
  170. case APCKind::SharedArray:
  171. APCArray::Delete(this);
  172. return;
  173. case APCKind::SharedObject:
  174. APCObject::Delete(this);
  175. return;
  176. case APCKind::SharedCollection:
  177. APCCollection::Delete(this);
  178. return;
  179. case APCKind::UncountedArray:
  180. case APCKind::UncountedString:
  181. assert(false);
  182. return;
  183. }
  184. not_reached();
  185. }
  186. bool APCHandle::checkInvariants() const {
  187. switch (m_kind) {
  188. case APCKind::Uninit:
  189. assert(m_type == KindOfUninit);
  190. return true;
  191. case APCKind::Null:
  192. assert(m_type == KindOfNull);
  193. return true;
  194. case APCKind::Bool:
  195. assert(m_type == KindOfBoolean);
  196. return true;
  197. case APCKind::Int:
  198. assert(m_type == KindOfInt64);
  199. return true;
  200. case APCKind::Double:
  201. assert(m_type == KindOfDouble);
  202. return true;
  203. case APCKind::StaticString:
  204. case APCKind::UncountedString:
  205. assert(m_type == KindOfPersistentString);
  206. return true;
  207. case APCKind::StaticArray:
  208. case APCKind::UncountedArray:
  209. assert(m_type == KindOfPersistentArray);
  210. return true;
  211. case APCKind::SharedString:
  212. case APCKind::SharedArray:
  213. case APCKind::SharedPackedArray:
  214. case APCKind::SharedObject:
  215. case APCKind::SharedCollection:
  216. case APCKind::SerializedArray:
  217. case APCKind::SerializedObject:
  218. assert(m_type == kInvalidDataType);
  219. return true;
  220. }
  221. not_reached();
  222. return false;
  223. }
  224. //////////////////////////////////////////////////////////////////////
  225. }