Introduce the "disable_shape_and_tuple_arrays" experiment flag
[hiphop-php.git] / hphp / hhbbc / eval-cell.h
blob170246abfb4f634fbfd69666d3142ee6b156301f
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_EVAL_CELL_H_
17 #define incl_HHBBC_EVAL_CELL_H_
19 #include <stdexcept>
20 #include <exception>
22 #include <folly/ScopeGuard.h>
23 #include <folly/Optional.h>
25 #include "hphp/runtime/base/array-data.h"
26 #include "hphp/runtime/base/execution-context.h"
27 #include "hphp/runtime/base/string-data.h"
28 #include "hphp/runtime/base/tv-refcount.h"
29 #include "hphp/runtime/vm/repo.h"
31 #include "hphp/hhbbc/hhbbc.h"
32 #include "hphp/hhbbc/type-system.h"
34 namespace HPHP { namespace HHBBC {
36 //////////////////////////////////////////////////////////////////////
39 * When constant-evaluating certain operations, it's possible they
40 * will return non-static objects, or throw exceptions (e.g. cellAdd()
41 * with an array and an int).
43 * This routine converts these things back to types. In the case of
44 * an exception it returns TInitCell.
46 template<class Pred>
47 folly::Optional<Type> eval_cell(Pred p) {
48 try {
49 assert(!RuntimeOption::EvalJit);
50 ThrowAllErrorsSetter taes;
52 Cell c = p();
53 if (isRefcountedType(c.m_type)) {
54 switch (c.m_type) {
55 case KindOfString:
57 if (c.m_data.pstr->size() > Repo::get().stringLengthLimit()) {
58 tvDecRefCountable(&c);
59 return TStr;
61 auto const sstr = makeStaticString(c.m_data.pstr);
62 tvDecRefCountable(&c);
63 c = make_tv<KindOfPersistentString>(sstr);
65 break;
66 case KindOfArray:
68 auto const sarr = ArrayData::GetScalarArray(c.m_data.parr);
69 tvDecRefCountable(&c);
70 c = make_tv<KindOfPersistentArray>(sarr);
72 break;
73 case KindOfVec:
75 auto const sarr = ArrayData::GetScalarArray(c.m_data.parr);
76 tvDecRefCountable(&c);
77 c = make_tv<KindOfPersistentVec>(sarr);
79 break;
80 case KindOfDict:
82 auto const sarr = ArrayData::GetScalarArray(c.m_data.parr);
83 tvDecRefCountable(&c);
84 c = make_tv<KindOfPersistentDict>(sarr);
86 break;
87 case KindOfKeyset:
89 auto const sarr = ArrayData::GetScalarArray(c.m_data.parr);
90 tvDecRefCountable(&c);
91 c = make_tv<KindOfPersistentKeyset>(sarr);
93 break;
94 case KindOfUninit:
95 case KindOfNull:
96 case KindOfInt64:
97 case KindOfBoolean:
98 case KindOfDouble:
99 case KindOfPersistentString:
100 case KindOfPersistentArray:
101 case KindOfPersistentVec:
102 case KindOfPersistentDict:
103 case KindOfPersistentKeyset:
104 case KindOfObject:
105 case KindOfResource:
106 case KindOfRef:
107 always_assert(0 && "Impossible constant evaluation occurred");
112 * We need to get rid of statics if we're not actually going to do
113 * constant propagation. When ConstantProp is on, the types we
114 * create here can reflect that we'll be changing bytecode later
115 * to actually make these into non-reference-counted SStr or
116 * SArrs. If we leave the bytecode alone, though, it generally
117 * won't actually be static at runtime.
119 * TODO(#3696042): loosen_statics here should ideally not give up
120 * on the array or string value, just its staticness.
122 auto const t = from_cell(c);
123 return options.ConstantProp ? t : loosen_statics(t);
124 } catch (const Object&) {
125 return folly::none;
126 } catch (const std::exception&) {
127 return folly::none;
128 } catch (...) {
129 always_assert_flog(0, "a non-std::exception was thrown in eval_cell");
133 template<typename Pred>
134 folly::Optional<typename std::result_of<Pred()>::type>
135 eval_cell_value(Pred p) {
136 try {
137 ThrowAllErrorsSetter taes;
138 return p();
139 } catch (const Object&) {
140 return folly::none;
141 } catch (const std::exception&) {
142 return folly::none;
143 } catch (...) {
144 always_assert_flog(0, "a non-std::exception was thrown in eval_cell_value");
148 //////////////////////////////////////////////////////////////////////
152 #endif