CreateCont opcode optimization - avoid unnecessary reference counting.
Continuation argument values are copied to the continuation object and the locals are unset - in this way we don't need to change the reference coutners.
Esse commit está contido em:
@@ -14,14 +14,14 @@
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef incl_HPHP_TV_HELPERS_H_
|
||||
#define incl_HPHP_TV_HELPERS_H_
|
||||
|
||||
#ifndef incl_HPHP_INSIDE_HPHP_COMPLEX_TYPES_H_
|
||||
#error Directly including 'tv_helpers.h' is prohibited. \
|
||||
Include 'complex_types.h' instead.
|
||||
#endif
|
||||
|
||||
#ifndef incl_HPHP_TV_HELPERS_H_
|
||||
#define incl_HPHP_TV_HELPERS_H_
|
||||
|
||||
#include "hphp/runtime/base/types.h"
|
||||
|
||||
namespace HPHP {
|
||||
@@ -216,11 +216,17 @@ inline void tvDupRef(RefData* fr, TypedValue* to) {
|
||||
}
|
||||
|
||||
// Assumes 'fr' is live and 'to' is dead
|
||||
// NOTE: this helper does not modify to->_count
|
||||
inline void tvDup(const TypedValue* fr, TypedValue* to) {
|
||||
// After this operation, 'fr' is dead and 'to' live.
|
||||
inline void tvTeleport(const TypedValue* fr, TypedValue* to) {
|
||||
assert(tvIsPlausible(fr));
|
||||
to->m_data.num = fr->m_data.num;
|
||||
to->m_type = fr->m_type;
|
||||
}
|
||||
|
||||
// Assumes 'fr' is live and 'to' is dead
|
||||
// NOTE: this helper does not modify to->_count
|
||||
inline void tvDup(const TypedValue* fr, TypedValue* to) {
|
||||
tvTeleport(fr, to);
|
||||
tvRefcountedIncRef(to);
|
||||
}
|
||||
|
||||
|
||||
@@ -383,7 +383,7 @@ void VarEnv::detach(ActRec* fp) {
|
||||
TypedValue** origLocs =
|
||||
!m_restoreLocations.empty()
|
||||
? m_restoreLocations.back()
|
||||
: reinterpret_cast<TypedValue**>(uintptr_t(this) + sizeof(VarEnv));
|
||||
: reinterpret_cast<TypedValue**>(uintptr_t(this) + sizeof(VarEnv));
|
||||
|
||||
for (Id i = 0; i < numLocals; i++) {
|
||||
m_nvTable->resettle(func->localVarName(i), origLocs[i]);
|
||||
@@ -6694,7 +6694,10 @@ static inline void setContVar(const Func* genFunc,
|
||||
c_Continuation* cont) {
|
||||
Id destId = genFunc->lookupVarId(name);
|
||||
if (destId != kInvalidId) {
|
||||
tvDup(src, frame_local(cont->actRec(), destId));
|
||||
// Copy the value of the local to the cont object and set the
|
||||
// local to uninit so that we don't need to change refcounts.
|
||||
tvTeleport(src, frame_local(cont->actRec(), destId));
|
||||
tvWriteUninit(src);
|
||||
} else {
|
||||
ActRec *contFP = cont->actRec();
|
||||
if (!contFP->hasVarEnv()) {
|
||||
|
||||
@@ -1033,8 +1033,10 @@ void HhbcTranslator::emitCreateCont(Id funNameStrId) {
|
||||
// We must generate an AssertLoc because we don't have tracelet
|
||||
// guards on the object type in these outer generator functions.
|
||||
gen(AssertLoc, Type::Gen, LocalId(i), m_tb->fp());
|
||||
auto const loc = gen(IncRef, ldLoc(i));
|
||||
gen(StMem, contAR, cns(-cellsToBytes(params[i] + 1)), loc);
|
||||
// Copy the value of the local to the cont object and set the
|
||||
// local to uninit so that we don't need to change refcounts.
|
||||
gen(StMem, contAR, cns(-cellsToBytes(params[i] + 1)), ldLoc(i));
|
||||
gen(StLoc, LocalId(i), m_tb->fp(), m_tb->genDefUninit());
|
||||
}
|
||||
if (fillThis) {
|
||||
assert(thisId != kInvalidId);
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário