Smaller c_Continuation
Save 16 bytes in c_Continuation by moving running and done flags to o_subclassData and making labels 2-byte.
Esse commit está contido em:
@@ -98,7 +98,7 @@ void c_ContinuationWaitHandle::Create(c_Continuation* continuation) {
|
||||
|
||||
if (UNLIKELY(continuation->m_index != -1)) {
|
||||
Object e(SystemLib::AllocInvalidOperationExceptionObject(
|
||||
continuation->m_running
|
||||
continuation->running()
|
||||
? "Encountered an attempt to start currently running continuation"
|
||||
: "Encountered an attempt to start tainted continuation"));
|
||||
throw e;
|
||||
@@ -159,7 +159,7 @@ void c_ContinuationWaitHandle::run() {
|
||||
}
|
||||
|
||||
// continuation finished, retrieve result from its m_value
|
||||
if (m_continuation->m_done) {
|
||||
if (m_continuation->done()) {
|
||||
markAsSucceeded(m_continuation->m_value.asTypedValue());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -49,8 +49,9 @@ c_Continuation::c_Continuation(Class* cb) :
|
||||
m_index(-1LL),
|
||||
m_value(Variant::NullInit()),
|
||||
m_received(Variant::NullInit()),
|
||||
m_done(false), m_running(false),
|
||||
m_vmFunc(nullptr), m_label(0ll) {
|
||||
m_origFunc(nullptr),
|
||||
m_label(0) {
|
||||
o_subclassData.u16 = 0;
|
||||
}
|
||||
|
||||
c_Continuation::~c_Continuation() {
|
||||
@@ -66,7 +67,7 @@ c_Continuation::~c_Continuation() {
|
||||
if (ar->hasVarEnv()) {
|
||||
ar->getVarEnv()->detach(ar);
|
||||
} else {
|
||||
frame_free_locals_inl(ar, m_vmFunc->numLocals());
|
||||
frame_free_locals_inl(ar, ar->m_func->numLocals());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +75,7 @@ void c_Continuation::t___construct() {}
|
||||
|
||||
void c_Continuation::t_update(int64_t label, CVarRef value) {
|
||||
m_label = label;
|
||||
assert(m_label == label); // check m_label for truncation
|
||||
m_value.assignVal(value);
|
||||
}
|
||||
|
||||
@@ -128,7 +130,7 @@ void c_Continuation::t_rewind() {
|
||||
|
||||
bool c_Continuation::t_valid() {
|
||||
const_assert(false);
|
||||
return !m_done;
|
||||
return !done();
|
||||
}
|
||||
|
||||
void c_Continuation::t_send(CVarRef v) {
|
||||
@@ -140,7 +142,11 @@ void c_Continuation::t_raise(CVarRef v) {
|
||||
}
|
||||
|
||||
String c_Continuation::t_getorigfuncname() {
|
||||
return String(const_cast<StringData*>(m_origFuncName));
|
||||
static auto const closureName = StringData::GetStaticString("{closure}");
|
||||
auto const origName = m_origFunc->isClosureBody() ? closureName
|
||||
: m_origFunc->name();
|
||||
assert(origName->isStatic());
|
||||
return String(const_cast<StringData*>(origName));
|
||||
}
|
||||
|
||||
String c_Continuation::t_getcalledclass() {
|
||||
|
||||
@@ -38,22 +38,18 @@ class c_Continuation : public ExtObjectData {
|
||||
virtual void sweep();
|
||||
void operator delete(void* p) {
|
||||
c_Continuation* this_ = (c_Continuation*)p;
|
||||
DELETEOBJSZ(sizeForLocalsAndIters(this_->m_vmFunc->numLocals(),
|
||||
this_->m_vmFunc->numIterators()))(this_);
|
||||
DELETEOBJSZ((char*)(this_->m_arPtr + 1) - (char*)p)(this_);
|
||||
}
|
||||
|
||||
explicit c_Continuation(Class* cls = c_Continuation::s_cls);
|
||||
~c_Continuation();
|
||||
|
||||
public:
|
||||
void init(const Func* vmFunc,
|
||||
const StringData* origFuncName,
|
||||
void init(const Func* origFunc,
|
||||
ObjectData* thisPtr,
|
||||
ArrayData* args) noexcept {
|
||||
m_vmFunc = const_cast<Func*>(vmFunc);
|
||||
assert(m_vmFunc);
|
||||
m_origFuncName = origFuncName;
|
||||
assert(m_origFuncName->isStatic());
|
||||
m_origFunc = const_cast<Func*>(origFunc);
|
||||
assert(m_origFunc);
|
||||
|
||||
if (thisPtr != nullptr) {
|
||||
m_obj = thisPtr;
|
||||
@@ -64,6 +60,17 @@ public:
|
||||
m_args = args;
|
||||
}
|
||||
|
||||
bool done() const { return o_subclassData.u8[0]; }
|
||||
bool running() const { return o_subclassData.u8[1]; }
|
||||
void setDone(bool done) { o_subclassData.u8[0] = done; }
|
||||
void setRunning(bool running) { o_subclassData.u8[1] = running; }
|
||||
static constexpr uint doneOffset() {
|
||||
return offsetof(c_Continuation, o_subclassData);
|
||||
}
|
||||
static constexpr uint runningOffset() {
|
||||
return offsetof(c_Continuation, o_subclassData) + 1;
|
||||
}
|
||||
|
||||
void t___construct();
|
||||
void t_update(int64_t label, CVarRef value);
|
||||
Object t_getwaithandle();
|
||||
@@ -101,15 +108,15 @@ public:
|
||||
void call_raise(ObjectData* e);
|
||||
|
||||
inline void preNext() {
|
||||
if (m_done) {
|
||||
if (done()) {
|
||||
throw_exception(Object(SystemLib::AllocExceptionObject(
|
||||
"Continuation is already finished")));
|
||||
}
|
||||
if (m_running) {
|
||||
if (running()) {
|
||||
throw_exception(Object(SystemLib::AllocExceptionObject(
|
||||
"Continuation is already running")));
|
||||
}
|
||||
m_running = true;
|
||||
setRunning(true);
|
||||
++m_index;
|
||||
}
|
||||
|
||||
@@ -126,13 +133,10 @@ public:
|
||||
int64_t m_index;
|
||||
Variant m_value;
|
||||
Variant m_received;
|
||||
const StringData* m_origFuncName;
|
||||
bool m_done;
|
||||
bool m_running;
|
||||
Func *m_origFunc;
|
||||
|
||||
int32_t m_label;
|
||||
int m_localsOffset;
|
||||
Func *m_vmFunc;
|
||||
int64_t m_label;
|
||||
ActRec* m_arPtr;
|
||||
|
||||
p_ContinuationWaitHandle m_waitHandle;
|
||||
|
||||
@@ -7036,12 +7036,7 @@ VMExecutionContext::createContinuationHelper(const Func* origFunc,
|
||||
);
|
||||
cont->incRefCount();
|
||||
cont->setNoDestruct();
|
||||
|
||||
static auto const closureName = StringData::GetStaticString("{closure}");
|
||||
auto const origName = origFunc->isClosureBody() ? closureName
|
||||
: origFunc->name();
|
||||
|
||||
cont->init(genFunc, origName, thisPtr, args);
|
||||
cont->init(origFunc, thisPtr, args);
|
||||
|
||||
// The ActRec corresponding to the generator body lives as long as the object
|
||||
// does. We set it up once, here, and then just change FP to point to it when
|
||||
@@ -7290,7 +7285,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopContReceive(PC& pc) {
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopContRetC(PC& pc) {
|
||||
NEXT();
|
||||
c_Continuation* cont = frame_continuation(m_fp);
|
||||
cont->m_done = true;
|
||||
cont->setDone(true);
|
||||
tvSetIgnoreRef(m_stack.topC(), cont->m_value.asTypedValue());
|
||||
m_stack.popC();
|
||||
|
||||
@@ -7333,7 +7328,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopContValid(PC& pc) {
|
||||
NEXT();
|
||||
TypedValue* tv = m_stack.allocTV();
|
||||
tvWriteUninit(tv);
|
||||
tvAsVariant(tv) = !this_continuation(m_fp)->m_done;
|
||||
tvAsVariant(tv) = !this_continuation(m_fp)->done();
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopContCurrent(PC& pc) {
|
||||
@@ -7348,14 +7343,14 @@ inline void OPTBLD_INLINE VMExecutionContext::iopContCurrent(PC& pc) {
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopContStopped(PC& pc) {
|
||||
NEXT();
|
||||
this_continuation(m_fp)->m_running = false;
|
||||
this_continuation(m_fp)->setRunning(false);
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopContHandle(PC& pc) {
|
||||
NEXT();
|
||||
c_Continuation* cont = this_continuation(m_fp);
|
||||
cont->m_running = false;
|
||||
cont->m_done = true;
|
||||
cont->setRunning(false);
|
||||
cont->setDone(true);
|
||||
cont->m_value.setNull();
|
||||
|
||||
Variant exn = tvAsVariant(m_stack.topTV());
|
||||
|
||||
@@ -5135,17 +5135,17 @@ void CodeGenerator::cgLinkContVarEnv(IRInstruction* inst) {
|
||||
void CodeGenerator::cgContPreNext(IRInstruction* inst) {
|
||||
auto contReg = m_regs[inst->src(0)].reg();
|
||||
|
||||
const Offset doneOffset = CONTOFF(m_done);
|
||||
static_assert((doneOffset + 1) == CONTOFF(m_running),
|
||||
"m_done should immediately precede m_running");
|
||||
// Check m_done and m_running at the same time
|
||||
m_as.test_imm32_disp_reg32(0x0101, doneOffset, contReg);
|
||||
const Offset doneOffset = c_Continuation::doneOffset();
|
||||
static_assert((doneOffset + 1) == c_Continuation::runningOffset(),
|
||||
"done should immediately precede running");
|
||||
// Check done and running at the same time
|
||||
m_as.test_imm16_disp_reg16(0x0101, doneOffset, contReg);
|
||||
emitFwdJcc(CC_NZ, inst->taken());
|
||||
|
||||
// ++m_index
|
||||
m_as.add_imm64_disp_reg64(0x1, CONTOFF(m_index), contReg);
|
||||
// m_running = true
|
||||
m_as.store_imm8_disp_reg(0x1, CONTOFF(m_running), contReg);
|
||||
// running = true
|
||||
m_as.store_imm8_disp_reg(0x1, c_Continuation::runningOffset(), contReg);
|
||||
}
|
||||
|
||||
void CodeGenerator::cgContStartedCheck(IRInstruction* inst) {
|
||||
|
||||
@@ -788,15 +788,17 @@ class RawMemSlot {
|
||||
: m_offset(offset), m_size(size), m_type(type), m_allowExtra(allowExtra) { }
|
||||
|
||||
static RawMemSlot& GetContLabel() {
|
||||
static RawMemSlot m(CONTOFF(m_label), Transl::sz::qword, Type::Int);
|
||||
static RawMemSlot m(CONTOFF(m_label), Transl::sz::dword, Type::Int);
|
||||
return m;
|
||||
}
|
||||
static RawMemSlot& GetContDone() {
|
||||
static RawMemSlot m(CONTOFF(m_done), Transl::sz::byte, Type::Bool);
|
||||
static RawMemSlot m(c_Continuation::doneOffset(), Transl::sz::byte,
|
||||
Type::Bool);
|
||||
return m;
|
||||
}
|
||||
static RawMemSlot& GetContRunning() {
|
||||
static RawMemSlot m(CONTOFF(m_running), Transl::sz::byte, Type::Bool);
|
||||
static RawMemSlot m(c_Continuation::runningOffset(), Transl::sz::byte,
|
||||
Type::Bool);
|
||||
return m;
|
||||
}
|
||||
static RawMemSlot& GetContARPtr() {
|
||||
|
||||
@@ -1794,6 +1794,12 @@ struct X64Assembler {
|
||||
sz::byte);
|
||||
}
|
||||
|
||||
void emitIM16(X64Instr op, RegNumber br, RegNumber ir, int s,
|
||||
int disp, ssize_t imm) ALWAYS_INLINE {
|
||||
emitCMX(op, 0, br, ir, s, disp, reg::noreg, false, imm, true,
|
||||
sz::word);
|
||||
}
|
||||
|
||||
void emitIM32(X64Instr op, RegNumber br, RegNumber ir, int s,
|
||||
int disp, ssize_t imm) ALWAYS_INLINE {
|
||||
emitCMX(op, 0, br, ir, s, disp, reg::noreg, false, imm, true,
|
||||
@@ -2039,6 +2045,12 @@ public:
|
||||
inline void name ## _imm32_reg32(int64_t imm, RegNumber rdest) { \
|
||||
emitIR32(instr_ ## name, rdest, safe_cast<int32_t>(imm)); \
|
||||
} \
|
||||
/* op imm, disp(rdest) */ \
|
||||
inline void name ## _imm16_disp_reg16(int64_t imm, int disp, \
|
||||
RegNumber rdest) { \
|
||||
emitIM16(instr_ ## name, rdest, reg::noreg, \
|
||||
sz::byte, disp, safe_cast<int16_t>(imm)); \
|
||||
} \
|
||||
/* opl imm, disp(rdest) */ \
|
||||
inline void name ## _imm32_disp_reg32(int64_t imm, int disp, \
|
||||
RegNumber rdest) { \
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário