2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 Facebook, Inc. (http://www.facebook.com) |
6 | Copyright (c) 1997-2010 The PHP Group |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
18 #include "hphp/runtime/ext/ext_continuation.h"
19 #include "hphp/runtime/ext/asio/async_function_wait_handle.h"
20 #include "hphp/runtime/base/builtin-functions.h"
22 #include "hphp/runtime/ext/ext_spl.h"
23 #include "hphp/runtime/ext/ext_function.h"
25 #include "hphp/runtime/vm/jit/translator.h"
26 #include "hphp/runtime/vm/jit/translator-inline.h"
27 #include "hphp/runtime/vm/func.h"
28 #include "hphp/runtime/vm/runtime.h"
29 #include "hphp/runtime/base/stats.h"
32 ///////////////////////////////////////////////////////////////////////////////
34 void delete_Continuation(ObjectData
* od
, const Class
*) {
35 auto const cont
= static_cast<c_Continuation
*>(od
);
36 auto const size
= cont
->getObjectSize();
37 auto const base
= cont
->getMallocBase();
38 cont
->~c_Continuation();
39 if (LIKELY(size
<= kMaxSmartSize
)) {
40 return MM().smartFreeSizeLogged(base
, size
);
42 MM().smartFreeSizeBigLogged(base
, size
);
45 ///////////////////////////////////////////////////////////////////////////////
47 c_Continuation::c_Continuation(Class
* cb
)
48 : ExtObjectDataFlags(cb
)
50 , m_key(make_tv
<KindOfInt64
>(-1LL))
51 , m_value(make_tv
<KindOfNull
>())
53 o_subclassData
.u16
= 0;
56 c_Continuation::~c_Continuation() {
57 tvRefcountedDecRef(m_key
);
58 tvRefcountedDecRef(m_value
);
64 // Free locals, but don't trigger the EventHook for FunctionExit
65 // since the continuation function has already been exited. We
66 // don't want redundant calls.
67 ActRec
* ar
= actRec();
68 frame_free_locals_inl_no_hook
<false>(ar
, ar
->m_func
->numLocals());
71 //////////////////////////////////////////////////////////////////////
73 void c_Continuation::t___construct() {}
75 void c_Continuation::suspend(Offset offset
, const Cell
& value
) {
76 assert(actRec()->func()->contains(offset
));
78 cellSet(make_tv
<KindOfInt64
>(++m_index
), m_key
);
79 cellSet(value
, m_value
);
82 void c_Continuation::suspend(Offset offset
, const Cell
& key
,
84 assert(actRec()->func()->contains(offset
));
87 cellSet(value
, m_value
);
88 if (m_key
.m_type
== KindOfInt64
) {
89 int64_t new_index
= m_key
.m_data
.num
;
90 m_index
= new_index
> m_index
? new_index
: m_index
;
94 Variant
c_Continuation::t_current() {
96 return tvAsCVarRef(&m_value
);
99 Variant
c_Continuation::t_key() {
101 return tvAsCVarRef(&m_key
);
104 void c_Continuation::t_next() {
110 s__closure_("{closure}"),
113 void c_Continuation::t_rewind() {
114 this->o_invoke_few_args(s_next
, 0);
117 bool c_Continuation::t_valid() {
122 void c_Continuation::t_send(const Variant
& v
) {
126 void c_Continuation::t_raise(const Variant
& v
) {
130 String
c_Continuation::t_getorigfuncname() {
131 const Func
* origFunc
= actRec()->func();
132 auto const origName
= origFunc
->isClosureBody() ? s__closure_
.get()
134 assert(origName
->isStatic());
135 return String(const_cast<StringData
*>(origName
));
138 String
c_Continuation::t_getcalledclass() {
141 if (actRec()->hasThis()) {
142 called_class
= actRec()->getThis()->getVMClass()->name()->data();
143 } else if (actRec()->hasClass()) {
144 called_class
= actRec()->getClass()->name()->data();
146 called_class
= empty_string
;
152 void c_Continuation::copyContinuationVars(ActRec
* srcFp
) {
153 const auto dstFp
= actRec();
154 const auto func
= dstFp
->func();
155 assert(srcFp
->func() == dstFp
->func());
157 for (Id i
= 0; i
< func
->numLocals(); ++i
) {
158 tvDupFlattenVars(frame_local(srcFp
, i
), frame_local(dstFp
, i
));
161 if (dstFp
->hasThis()) {
162 dstFp
->getThis()->incRefCount();
165 if (LIKELY(srcFp
->m_varEnv
== nullptr)) {
169 if (srcFp
->hasExtraArgs()) {
170 dstFp
->setExtraArgs(srcFp
->getExtraArgs()->clone(dstFp
));
172 assert(srcFp
->hasVarEnv());
173 dstFp
->setVarEnv(srcFp
->getVarEnv()->clone(dstFp
));
177 c_Continuation
*c_Continuation::Clone(ObjectData
* obj
) {
178 auto thiz
= static_cast<c_Continuation
*>(obj
);
179 auto fp
= thiz
->actRec();
181 c_Continuation
* cont
= static_cast<c_Continuation
*>(fp
->getThisOrClass()
182 ? CreateMeth(fp
, thiz
->m_offset
)
183 : CreateFunc(fp
, thiz
->m_offset
));
185 cont
->copyContinuationVars(fp
);
187 cont
->o_subclassData
.u16
= thiz
->o_subclassData
.u16
;
188 cont
->m_index
= thiz
->m_index
;
189 cellSet(thiz
->m_key
, cont
->m_key
);
190 cellSet(thiz
->m_value
, cont
->m_value
);
195 ///////////////////////////////////////////////////////////////////////////////