mirror of
https://github.com/Icinga/icinga2.git
synced 2025-09-26 02:58:43 +02:00
Expression#GetReference(): ref, not copy, index if possible
to avoid malloc().
This commit is contained in:
parent
a65f2d6b41
commit
5933729590
@ -22,6 +22,15 @@ using namespace icinga;
|
||||
boost::signals2::signal<void (ScriptFrame&, ScriptError *ex, const DebugInfo&)> Expression::OnBreakpoint;
|
||||
boost::thread_specific_ptr<bool> l_InBreakpointHandler;
|
||||
|
||||
RefIndex::RefIndex() : m_Foreign(&m_Own)
|
||||
{ }
|
||||
|
||||
void RefIndex::Set(String own)
|
||||
{
|
||||
m_Own = std::move(own);
|
||||
m_Foreign = &m_Own;
|
||||
}
|
||||
|
||||
Expression::~Expression()
|
||||
{ }
|
||||
|
||||
@ -63,7 +72,7 @@ ExpressionResult Expression::Evaluate(ScriptFrame& frame, DebugHint *dhint) cons
|
||||
}
|
||||
}
|
||||
|
||||
bool Expression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
|
||||
bool Expression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, RefIndex *index, DebugHint **dhint) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -122,9 +131,9 @@ ExpressionResult VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *d
|
||||
return ScriptGlobal::Get(m_Variable);
|
||||
}
|
||||
|
||||
bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
|
||||
bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, RefIndex *index, DebugHint **dhint) const
|
||||
{
|
||||
*index = m_Variable;
|
||||
index->Set(&m_Variable);
|
||||
|
||||
if (frame.Locals && frame.Locals->Contains(m_Variable)) {
|
||||
*parent = frame.Locals;
|
||||
@ -152,7 +161,7 @@ bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value
|
||||
ExpressionResult RefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
||||
{
|
||||
Value parent;
|
||||
String index;
|
||||
RefIndex index;
|
||||
|
||||
if (!m_Operand->GetReference(frame, false, &parent, &index, &dhint))
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Cannot obtain reference for expression.", m_DebugInfo));
|
||||
@ -160,7 +169,7 @@ ExpressionResult RefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint)
|
||||
if (!parent.IsObject())
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Cannot obtain reference for expression because parent is not an object.", m_DebugInfo));
|
||||
|
||||
return new Reference(parent, index);
|
||||
return new Reference(parent, index.Get());
|
||||
}
|
||||
|
||||
ExpressionResult DerefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
||||
@ -177,7 +186,7 @@ ExpressionResult DerefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhin
|
||||
return ref->Get();
|
||||
}
|
||||
|
||||
bool DerefExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
|
||||
bool DerefExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, RefIndex *index, DebugHint **dhint) const
|
||||
{
|
||||
ExpressionResult operand = m_Operand->Evaluate(frame);
|
||||
if (operand.GetCode() != ResultOK)
|
||||
@ -186,7 +195,7 @@ bool DerefExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *pa
|
||||
Reference::Ptr ref = operand.GetValue();
|
||||
|
||||
*parent = ref->GetParent();
|
||||
*index = ref->GetIndex();
|
||||
index->Set(ref->GetIndex());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -449,10 +458,10 @@ ExpressionResult LogicalOrExpression::DoEvaluate(ScriptFrame& frame, DebugHint *
|
||||
ExpressionResult FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
|
||||
{
|
||||
Value self, vfunc;
|
||||
String index;
|
||||
RefIndex index;
|
||||
|
||||
if (m_FName->GetReference(frame, false, &self, &index))
|
||||
vfunc = VMOps::GetField(self, index, frame.Sandboxed, m_DebugInfo);
|
||||
vfunc = VMOps::GetField(self, index.Get(), frame.Sandboxed, m_DebugInfo);
|
||||
else {
|
||||
ExpressionResult vfuncres = m_FName->Evaluate(frame);
|
||||
CHECK_RESULT(vfuncres);
|
||||
@ -611,7 +620,7 @@ ExpressionResult SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint)
|
||||
DebugHint *psdhint = dhint;
|
||||
|
||||
Value parent;
|
||||
String index;
|
||||
RefIndex index;
|
||||
|
||||
if (!m_Operand1->GetReference(frame, true, &parent, &index, &psdhint))
|
||||
BOOST_THROW_EXCEPTION(ScriptError("Expression cannot be assigned to.", m_DebugInfo));
|
||||
@ -620,7 +629,7 @@ ExpressionResult SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint)
|
||||
CHECK_RESULT(operand2);
|
||||
|
||||
if (m_Op != OpSetLiteral) {
|
||||
Value object = VMOps::GetField(parent, index, frame.Sandboxed, m_DebugInfo);
|
||||
Value object = VMOps::GetField(parent, index.Get(), frame.Sandboxed, m_DebugInfo);
|
||||
|
||||
switch (m_Op) {
|
||||
case OpSetAdd:
|
||||
@ -652,7 +661,7 @@ ExpressionResult SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint)
|
||||
}
|
||||
}
|
||||
|
||||
VMOps::SetField(parent, index, operand2.GetValue(), m_OverrideFrozen, m_DebugInfo);
|
||||
VMOps::SetField(parent, index.Get(), operand2.GetValue(), m_OverrideFrozen, m_DebugInfo);
|
||||
|
||||
if (psdhint) {
|
||||
psdhint->AddMessage("=", m_DebugInfo);
|
||||
@ -745,10 +754,10 @@ ExpressionResult IndexerExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dh
|
||||
return VMOps::GetField(operand1.GetValue(), operand2.GetValue(), frame.Sandboxed, m_DebugInfo);
|
||||
}
|
||||
|
||||
bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
|
||||
bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, RefIndex *index, DebugHint **dhint) const
|
||||
{
|
||||
Value vparent;
|
||||
String vindex;
|
||||
RefIndex vindex;
|
||||
DebugHint *psdhint = nullptr;
|
||||
bool free_psd = false;
|
||||
|
||||
@ -765,17 +774,17 @@ bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *
|
||||
|
||||
if (vparent.IsObject()) {
|
||||
Object::Ptr oparent = vparent;
|
||||
has_field = oparent->HasOwnField(vindex);
|
||||
has_field = oparent->HasOwnField(vindex.Get());
|
||||
}
|
||||
|
||||
if (has_field)
|
||||
old_value = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_Operand1->GetDebugInfo());
|
||||
old_value = VMOps::GetField(vparent, vindex.Get(), frame.Sandboxed, m_Operand1->GetDebugInfo());
|
||||
|
||||
if (old_value.IsEmpty() && !old_value.IsString())
|
||||
VMOps::SetField(vparent, vindex, new Dictionary(), m_OverrideFrozen, m_Operand1->GetDebugInfo());
|
||||
VMOps::SetField(vparent, vindex.Get(), new Dictionary(), m_OverrideFrozen, m_Operand1->GetDebugInfo());
|
||||
}
|
||||
|
||||
*parent = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_DebugInfo);
|
||||
*parent = VMOps::GetField(vparent, vindex.Get(), frame.Sandboxed, m_DebugInfo);
|
||||
free_psd = true;
|
||||
} else {
|
||||
ExpressionResult operand1 = m_Operand1->Evaluate(frame);
|
||||
@ -783,11 +792,11 @@ bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *
|
||||
}
|
||||
|
||||
ExpressionResult operand2 = m_Operand2->Evaluate(frame);
|
||||
*index = operand2.GetValue();
|
||||
index->Set(operand2.GetValue());
|
||||
|
||||
if (dhint) {
|
||||
if (psdhint)
|
||||
*dhint = new DebugHint(psdhint->GetChild(*index));
|
||||
*dhint = new DebugHint(psdhint->GetChild(index->Get()));
|
||||
else
|
||||
*dhint = nullptr;
|
||||
}
|
||||
|
@ -176,6 +176,37 @@ private:
|
||||
if (res.GetCode() == ResultBreak) \
|
||||
break; \
|
||||
|
||||
/**
|
||||
* Abstracts a maybe owned String
|
||||
*
|
||||
* @ingroup config
|
||||
*/
|
||||
class RefIndex
|
||||
{
|
||||
public:
|
||||
RefIndex();
|
||||
RefIndex(const RefIndex&) = delete;
|
||||
RefIndex(RefIndex&&) = delete;
|
||||
RefIndex& operator=(const RefIndex&) = delete;
|
||||
RefIndex& operator=(RefIndex&&) = delete;
|
||||
|
||||
inline const String& Get() const noexcept
|
||||
{
|
||||
return *m_Foreign;
|
||||
}
|
||||
|
||||
inline void Set(const String* foreign) noexcept
|
||||
{
|
||||
m_Foreign = foreign;
|
||||
}
|
||||
|
||||
void Set(String own);
|
||||
|
||||
private:
|
||||
const String* m_Foreign;
|
||||
String m_Own;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup config
|
||||
*/
|
||||
@ -191,7 +222,13 @@ public:
|
||||
Expression& operator=(const Expression&) = delete;
|
||||
|
||||
ExpressionResult Evaluate(ScriptFrame& frame, DebugHint *dhint = nullptr) const;
|
||||
virtual bool GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint = nullptr) const;
|
||||
|
||||
/**
|
||||
* Caution! On return `*index` may point to a String somewhere in `this` (or subAST).
|
||||
* Keep `this` alive while using `*index`!
|
||||
*/
|
||||
virtual bool GetReference(ScriptFrame& frame, bool init_dict, Value *parent, RefIndex *index, DebugHint **dhint = nullptr) const;
|
||||
|
||||
virtual const DebugInfo& GetDebugInfo() const;
|
||||
|
||||
virtual ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const = 0;
|
||||
@ -310,7 +347,7 @@ public:
|
||||
|
||||
protected:
|
||||
ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
|
||||
bool GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const override;
|
||||
bool GetReference(ScriptFrame& frame, bool init_dict, Value *parent, RefIndex *index, DebugHint **dhint) const override;
|
||||
|
||||
private:
|
||||
String m_Variable;
|
||||
@ -328,7 +365,7 @@ public:
|
||||
|
||||
protected:
|
||||
ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
|
||||
bool GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const override;
|
||||
bool GetReference(ScriptFrame& frame, bool init_dict, Value *parent, RefIndex *index, DebugHint **dhint) const override;
|
||||
};
|
||||
|
||||
class RefExpression final : public UnaryExpression
|
||||
@ -761,7 +798,7 @@ protected:
|
||||
bool m_OverrideFrozen{false};
|
||||
|
||||
ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
|
||||
bool GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const override;
|
||||
bool GetReference(ScriptFrame& frame, bool init_dict, Value *parent, RefIndex *index, DebugHint **dhint) const override;
|
||||
|
||||
friend void BindToScope(std::unique_ptr<Expression>& expr, ScopeSpecifier scopeSpec);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user