migrate to differentiated vector "At" accessors to support future efficiency

This commit is contained in:
Vern Paxson 2021-02-25 13:21:55 -08:00
parent bc4a6c0d07
commit 0118b6ee38
15 changed files with 91 additions and 89 deletions

View file

@ -265,7 +265,7 @@ char* CompositeHash::SingleValHash(bool type_check, char* kp0,
kp1 = reinterpret_cast<char*>(kp+1); kp1 = reinterpret_cast<char*>(kp+1);
for ( unsigned int i = 0; i < vv->Size(); ++i ) for ( unsigned int i = 0; i < vv->Size(); ++i )
{ {
const auto& val = vv->At(i); auto val = vv->ValAt(i);
unsigned int* kp = AlignAndPadType<unsigned int>(kp1); unsigned int* kp = AlignAndPadType<unsigned int>(kp1);
*kp = i; *kp = i;
kp1 = reinterpret_cast<char*>(kp+1); kp1 = reinterpret_cast<char*>(kp+1);
@ -566,7 +566,7 @@ int CompositeHash::SingleTypeKeySize(Type* bt, const Val* v,
VectorVal* vv = const_cast<VectorVal*>(v->AsVectorVal()); VectorVal* vv = const_cast<VectorVal*>(v->AsVectorVal());
for ( unsigned int i = 0; i < vv->Size(); ++i ) for ( unsigned int i = 0; i < vv->Size(); ++i )
{ {
const auto& val = vv->At(i); auto val = vv->ValAt(i);
sz = SizeAlign(sz, sizeof(unsigned int)); sz = SizeAlign(sz, sizeof(unsigned int));
sz = SizeAlign(sz, sizeof(unsigned int)); sz = SizeAlign(sz, sizeof(unsigned int));
if ( val ) if ( val )

View file

@ -277,7 +277,7 @@ const char* assign_to_index(ValPtr v1, ValPtr v2, ValPtr v3,
for ( auto idx = 0u; idx < v_vect->Size(); for ( auto idx = 0u; idx < v_vect->Size();
idx++, first++ ) idx++, first++ )
v1_vect->Insert(first, v_vect->At(idx)); v1_vect->Insert(first, v_vect->ValAt(idx));
} }
else if ( ! v1_vect->Assign(lv->Idx(0)->CoerceToUnsigned(), std::move(v3)) ) else if ( ! v1_vect->Assign(lv->Idx(0)->CoerceToUnsigned(), std::move(v3)) )
@ -619,8 +619,11 @@ ValPtr UnaryExpr::Eval(Frame* f) const
for ( unsigned int i = 0; i < v_op->Size(); ++i ) for ( unsigned int i = 0; i < v_op->Size(); ++i )
{ {
const auto& v_i = v_op->At(i); auto vop = v_op->ValAt(i);
result->Assign(i, v_i ? Fold(v_i.get()) : nullptr); if ( vop )
result->Assign(i, Fold(vop.get()));
else
result->Assign(i, nullptr);
} }
return result; return result;
@ -708,11 +711,12 @@ ValPtr BinaryExpr::Eval(Frame* f) const
for ( unsigned int i = 0; i < v_op1->Size(); ++i ) for ( unsigned int i = 0; i < v_op1->Size(); ++i )
{ {
if ( v_op1->At(i) && v_op2->At(i) ) auto v1_i = v_op1->ValAt(i);
v_result->Assign(i, Fold(v_op1->At(i).get(), v_op2->At(i).get())); auto v2_i = v_op2->ValAt(i);
if ( v1_i && v2_i )
v_result->Assign(i, Fold(v_op1->ValAt(i).get(), v_op2->ValAt(i).get()));
else else
v_result->Assign(i, nullptr); v_result->Assign(i, nullptr);
// SetError("undefined element in vector operation");
} }
return v_result; return v_result;
@ -725,13 +729,12 @@ ValPtr BinaryExpr::Eval(Frame* f) const
for ( unsigned int i = 0; i < vv->Size(); ++i ) for ( unsigned int i = 0; i < vv->Size(); ++i )
{ {
if ( const auto& vv_i = vv->At(i) ) auto vv_i = vv->ValAt(i);
if ( vv_i )
v_result->Assign(i, is_vec1 ? Fold(vv_i.get(), v2.get()) v_result->Assign(i, is_vec1 ? Fold(vv_i.get(), v2.get())
: Fold(v1.get(), vv_i.get())); : Fold(v1.get(), vv_i.get()));
else else
v_result->Assign(i, nullptr); v_result->Assign(i, nullptr);
// SetError("Undefined element in vector operation");
} }
return v_result; return v_result;
@ -1235,12 +1238,8 @@ ValPtr IncrExpr::Eval(Frame* f) const
for ( unsigned int i = 0; i < v_vec->Size(); ++i ) for ( unsigned int i = 0; i < v_vec->Size(); ++i )
{ {
const auto& elt = v_vec->At(i); auto elt = v_vec->ValAt(i);
v_vec->Assign(i, DoSingleEval(f, elt.get()));
if ( elt )
v_vec->Assign(i, DoSingleEval(f, elt.get()));
else
v_vec->Assign(i, nullptr);
} }
op->Assign(f, std::move(v_vec)); op->Assign(f, std::move(v_vec));
@ -1863,18 +1862,13 @@ ValPtr BoolExpr::Eval(Frame* f) const
for ( unsigned int i = 0; i < vec_v1->Size(); ++i ) for ( unsigned int i = 0; i < vec_v1->Size(); ++i )
{ {
const auto& op1 = vec_v1->At(i); const auto op1 = vec_v1->BoolAt(i);
const auto& op2 = vec_v2->At(i); const auto op2 = vec_v2->BoolAt(i);
if ( op1 && op2 )
{
bool local_result = (tag == EXPR_AND_AND) ?
(! op1->IsZero() && ! op2->IsZero()) :
(! op1->IsZero() || ! op2->IsZero());
result->Assign(i, val_mgr->Bool(local_result)); bool local_result =
} (tag == EXPR_AND_AND) ? (op1 && op2) : (op1 || op2);
else
result->Assign(i, nullptr); result->Assign(i, val_mgr->Bool(local_result));
} }
return result; return result;
@ -2225,15 +2219,9 @@ ValPtr CondExpr::Eval(Frame* f) const
for ( unsigned int i = 0; i < cond->Size(); ++i ) for ( unsigned int i = 0; i < cond->Size(); ++i )
{ {
const auto& local_cond = cond->At(i); auto local_cond = cond->BoolAt(i);
auto v = local_cond ? a->ValAt(i) : b->ValAt(i);
if ( local_cond ) result->Assign(i, v);
{
const auto& v = local_cond->IsZero() ? b->At(i) : a->At(i);
result->Assign(i, v);
}
else
result->Assign(i, nullptr);
} }
return result; return result;
@ -2912,8 +2900,8 @@ ValPtr IndexExpr::Eval(Frame* f) const
for ( unsigned int i = 0; i < v_v2->Size(); ++i ) for ( unsigned int i = 0; i < v_v2->Size(); ++i )
{ {
if ( v_v2->At(i)->AsBool() ) if ( v_v2->BoolAt(i) )
v_result->Assign(v_result->Size() + 1, v_v1->At(i)); v_result->Assign(v_result->Size() + 1, v_v1->ValAt(i));
} }
} }
else else
@ -2923,7 +2911,7 @@ ValPtr IndexExpr::Eval(Frame* f) const
// Probably only do this if *all* are negative. // Probably only do this if *all* are negative.
v_result->Resize(v_v2->Size()); v_result->Resize(v_v2->Size());
for ( unsigned int i = 0; i < v_v2->Size(); ++i ) for ( unsigned int i = 0; i < v_v2->Size(); ++i )
v_result->Assign(i, v_v1->At(v_v2->At(i)->CoerceToInt())); v_result->Assign(i, v_v1->ValAt(v_v2->ValAt(i)->CoerceToInt()));
} }
return v_result; return v_result;
@ -2946,7 +2934,7 @@ ValPtr IndexExpr::Fold(Val* v1, Val* v2) const
const ListVal* lv = v2->AsListVal(); const ListVal* lv = v2->AsListVal();
if ( lv->Length() == 1 ) if ( lv->Length() == 1 )
v = vect->At(lv->Idx(0)->CoerceToUnsigned()); v = vect->ValAt(lv->Idx(0)->CoerceToUnsigned());
else else
{ {
size_t len = vect->Size(); size_t len = vect->Size();
@ -2961,7 +2949,7 @@ ValPtr IndexExpr::Fold(Val* v1, Val* v2) const
result->Resize(sub_length); result->Resize(sub_length);
for ( bro_int_t idx = first; idx < last; idx++ ) for ( bro_int_t idx = first; idx < last; idx++ )
result->Assign(idx - first, vect->At(idx)); result->Assign(idx - first, vect->ValAt(idx));
} }
return result; return result;
@ -3764,7 +3752,8 @@ ValPtr ArithCoerceExpr::Fold(Val* v) const
for ( unsigned int i = 0; i < vv->Size(); ++i ) for ( unsigned int i = 0; i < vv->Size(); ++i )
{ {
if ( const auto& elt = vv->At(i) ) auto elt = vv->ValAt(i);
if ( elt )
result->Assign(i, FoldSingleVal(elt.get(), t)); result->Assign(i, FoldSingleVal(elt.get(), t));
else else
result->Assign(i, nullptr); result->Assign(i, nullptr);
@ -4222,7 +4211,11 @@ ValPtr InExpr::Fold(Val* v1, Val* v2) const
bool res; bool res;
if ( is_vector(v2) ) if ( is_vector(v2) )
res = (bool)v2->AsVectorVal()->At(v1->AsListVal()->Idx(0)->CoerceToUnsigned()); {
auto vv2 = v2->AsVectorVal();
auto ind = v1->AsListVal()->Idx(0)->CoerceToUnsigned();
res = ind < vv2->Size() && vv2->ValAt(ind);
}
else else
res = (bool)v2->AsTableVal()->Find({NewRef{}, v1}); res = (bool)v2->AsTableVal()->Find({NewRef{}, v1});

View file

@ -104,23 +104,23 @@ Substring::Vec* Substring::VecFromPolicy(VectorVal* vec)
for ( unsigned int i = 0; i < vec->Size(); ++i ) for ( unsigned int i = 0; i < vec->Size(); ++i )
{ {
const auto& v = vec->At(i); // get the RecordVal auto v = vec->RecordValAt(i);
if ( ! v ) if ( ! v )
continue; continue;
const String* str = v->AsRecordVal()->GetFieldAs<StringVal>(0); const String* str = v->GetFieldAs<StringVal>(0);
auto* substr = new Substring(*str); auto* substr = new Substring(*str);
const VectorVal* aligns = v->AsRecordVal()->GetField(1)->AsVectorVal(); const VectorVal* aligns = v->GetField(1)->AsVectorVal();
for ( unsigned int j = 1; j <= aligns->Size(); ++j ) for ( unsigned int j = 1; j <= aligns->Size(); ++j )
{ {
const RecordVal* align = aligns->AsVectorVal()->At(j)->AsRecordVal(); const RecordVal* align = aligns->AsVectorVal()->RecordValAt(j);
const String* str = align->GetFieldAs<StringVal>(0); const String* str = align->GetFieldAs<StringVal>(0);
int index = align->GetFieldAs<CountVal>(1); int index = align->GetFieldAs<CountVal>(1);
substr->AddAlignment(str, index); substr->AddAlignment(str, index);
} }
bool new_alignment = v->AsRecordVal()->GetFieldAs<BoolVal>(2); bool new_alignment = v->GetFieldAs<BoolVal>(2);
substr->MarkNewAlignment(new_alignment); substr->MarkNewAlignment(new_alignment);
result->push_back(substr); result->push_back(substr);

View file

@ -1326,10 +1326,6 @@ ValPtr ForStmt::DoExec(Frame* f, Val* v, StmtFlowType& flow) const
for ( auto i = 0u; i <= vv->Size(); ++i ) for ( auto i = 0u; i <= vv->Size(); ++i )
{ {
// Skip unassigned vector indices.
if ( ! vv->At(i) )
continue;
// Set the loop variable to the current index, and make // Set the loop variable to the current index, and make
// another pass over the loop body. // another pass over the loop body.
f->SetElement((*loop_vars)[0], val_mgr->Count(i)); f->SetElement((*loop_vars)[0], val_mgr->Count(i));

View file

@ -588,7 +588,7 @@ static void BuildJSON(threading::formatter::JSON::NullDoubleWriter& writer, Val*
auto* vval = val->AsVectorVal(); auto* vval = val->AsVectorVal();
size_t size = vval->SizeVal()->AsCount(); size_t size = vval->SizeVal()->AsCount();
for (size_t i = 0; i < size; i++) for (size_t i = 0; i < size; i++)
BuildJSON(writer, vval->At(i).get(), only_loggable, re); BuildJSON(writer, vval->ValAt(i).get(), only_loggable, re);
writer.EndArray(); writer.EndArray();
break; break;

View file

@ -1299,24 +1299,6 @@ public:
// Returns true if succcessful. // Returns true if succcessful.
bool AddTo(Val* v, bool is_first_init) const override; bool AddTo(Val* v, bool is_first_init) const override;
/**
* Returns the element at a given index or nullptr if it does not exist.
* @param index The position in the vector of the element to return.
* @return The element at the given index or nullptr if the index
* does not exist (it's greater than or equal to vector's current size).
*/
ValPtr At(unsigned int index) const;
/**
* Returns the given element treated as a Count type, to efficiently
* support a common type of vector access if we change the underlying
* vector representation.
* @param index The position in the vector of the element to return.
* @return The element's value, as a Count underlying representation.
*/
bro_uint_t CountAt(unsigned int index) const
{ return At(index)->AsCount(); }
unsigned int Size() const { return vector_val->size(); } unsigned int Size() const { return vector_val->size(); }
// Is there any way to reclaim previously-allocated memory when you // Is there any way to reclaim previously-allocated memory when you
@ -1367,7 +1349,38 @@ public:
*/ */
VectorValPtr Order(Func* cmp_func = nullptr); VectorValPtr Order(Func* cmp_func = nullptr);
ValPtr ValAt(unsigned int index) const { return At(index); }
/**
* Returns the given element in a given underlying representation.
* Enables efficient vector access. Caller must ensure that the
* index lies within the vector's range.
* @param index The position in the vector of the element to return.
* @return The element's underlying value.
*/
bro_uint_t CountAt(unsigned int index) const
{ return (*vector_val)[index].uint_val; }
const RecordVal* RecordValAt(unsigned int index) const
{ return (*vector_val)[index].record_val; }
bool BoolAt(unsigned int index) const
{ return bool((*vector_val)[index].uint_val); }
const StringVal* StringValAt(unsigned int index) const
{ return (*vector_val)[index].string_val; }
const String* StringAt(unsigned int index) const
{ return StringValAt(index)->AsString(); }
protected: protected:
/**
* Returns the element at a given index or nullptr if it does not exist.
* @param index The position in the vector of the element to return.
* @return The element at the given index or nullptr if the index
* does not exist (it's greater than or equal to vector's current size).
*
* Protected to ensure callers pick one of the differentiated accessors
* above, as appropriate, with ValAt() providing the original semantics.
*/
ValPtr At(unsigned int index) const;
void ValDescribe(ODesc* d) const override; void ValDescribe(ODesc* d) const override;
ValPtr DoClone(CloneState* state) override; ValPtr DoClone(CloneState* state) override;

View file

@ -364,11 +364,11 @@ String::Vec* String::VecFromPolicy(VectorVal* vec)
for ( unsigned int i = 0; i < vec->Size(); ++i ) for ( unsigned int i = 0; i < vec->Size(); ++i )
{ {
const auto& v = vec->At(i); // get the RecordVal auto v = vec->StringAt(i);
if ( ! v ) if ( ! v )
continue; continue;
String* string = new String(*(v->AsString())); String* string = new String(*v);
result->push_back(string); result->push_back(string);
} }

View file

@ -456,11 +456,11 @@ refine connection SSH_Conn += {
{ {
for ( unsigned int j = 0; j < server_list->Size(); ++j ) for ( unsigned int j = 0; j < server_list->Size(); ++j )
{ {
if ( *(client_list->At(i)->AsStringVal()->AsString()) == *(server_list->At(j)->AsStringVal()->AsString()) ) if ( *(client_list->StringAt(i)) == *(server_list->StringAt(j)) )
{ {
kex_algorithm_.free(); kex_algorithm_.free();
kex_algorithm_.init((const uint8 *) client_list->At(i)->AsStringVal()->Bytes(), kex_algorithm_.init((const uint8 *) client_list->StringAt(i)->Bytes(),
client_list->At(i)->AsStringVal()->Len()); client_list->StringAt(i)->Len());
// UNTESTED // UNTESTED
if ( update_kex_state_if_equal("rsa1024-sha1", KEX_RSA) ) if ( update_kex_state_if_equal("rsa1024-sha1", KEX_RSA) )

View file

@ -972,7 +972,7 @@ broker::expected<broker::data> val_to_data(const Val* v)
for ( auto i = 0u; i < vec->Size(); ++i ) for ( auto i = 0u; i < vec->Size(); ++i )
{ {
const auto& item_val = vec->At(i); auto item_val = vec->ValAt(i);
if ( ! item_val ) if ( ! item_val )
continue; continue;

View file

@ -443,7 +443,7 @@ bool Manager::PublishEvent(string topic, RecordVal* args)
for ( auto i = 0u; i < vv->Size(); ++i ) for ( auto i = 0u; i < vv->Size(); ++i )
{ {
const auto& val = vv->At(i)->AsRecordVal()->GetField(0); const auto& val = vv->RecordValAt(i)->GetField(0);
auto data_val = static_cast<detail::DataVal*>(val.get()); auto data_val = static_cast<detail::DataVal*>(val.get());
xs.emplace_back(data_val->data); xs.emplace_back(data_val->data);
} }

View file

@ -37,7 +37,7 @@ STACK_OF(X509)* x509_get_untrusted_stack(zeek::VectorVal* certs_vec)
for ( int i = 1; i < (int) certs_vec->Size(); ++i ) // start at 1 - 0 is host cert for ( int i = 1; i < (int) certs_vec->Size(); ++i ) // start at 1 - 0 is host cert
{ {
const auto& sv = certs_vec->At(i); auto sv = certs_vec->ValAt(i);
if ( ! sv ) if ( ! sv )
continue; continue;
@ -232,7 +232,7 @@ function x509_ocsp_verify%(certs: x509_opaque_vector, ocsp_reply: string, root_c
// host certificate // host certificate
unsigned int index = 0; // to prevent overloading to 0pointer unsigned int index = 0; // to prevent overloading to 0pointer
const auto& sv = certs_vec->At(index); auto sv = certs_vec->ValAt(index);
if ( ! sv ) if ( ! sv )
{ {
zeek::emit_builtin_error("undefined value in certificate vector"); zeek::emit_builtin_error("undefined value in certificate vector");
@ -518,7 +518,7 @@ function x509_verify%(certs: x509_opaque_vector, root_certs: table_string_of_str
// host certificate // host certificate
unsigned int index = 0; // to prevent overloading to 0pointer unsigned int index = 0; // to prevent overloading to 0pointer
const auto& sv = certs_vec->At(index); auto sv = certs_vec->ValAt(index);
if ( !sv ) if ( !sv )
{ {
zeek::emit_builtin_error("undefined value in certificate vector"); zeek::emit_builtin_error("undefined value in certificate vector");

View file

@ -1045,7 +1045,7 @@ threading::Value* Manager::ValToLogVal(Val* val, Type* ty)
for ( bro_int_t i = 0; i < lval->val.vector_val.size; i++ ) for ( bro_int_t i = 0; i < lval->val.vector_val.size; i++ )
{ {
lval->val.vector_val.vals[i] = lval->val.vector_val.vals[i] =
ValToLogVal(vec->At(i).get(), ValToLogVal(vec->ValAt(i).get(),
vec->GetType()->Yield().get()); vec->GetType()->Yield().get());
} }

View file

@ -104,7 +104,7 @@ function join_string_vec%(vec: string_vec, sep: string%): string
if ( i > 0 ) if ( i > 0 )
d.Add(sep->CheckString(), 0); d.Add(sep->CheckString(), 0);
const auto& e = v->At(i); auto e = v->ValAt(i);
// If the element is empty, skip it. // If the element is empty, skip it.
if ( ! e ) if ( ! e )

View file

@ -1255,7 +1255,7 @@ Supervisor::NodeConfig Supervisor::NodeConfig::FromRecord(const RecordVal* node)
for ( auto i = 0u; i < scripts_val->Size(); ++i ) for ( auto i = 0u; i < scripts_val->Size(); ++i )
{ {
auto script = scripts_val->At(i)->AsStringVal()->ToStdString(); auto script = scripts_val->StringValAt(i)->ToStdString();
rval.scripts.emplace_back(std::move(script)); rval.scripts.emplace_back(std::move(script));
} }

View file

@ -815,7 +815,7 @@ function paraglob_init%(v: any%) : opaque of paraglob
VectorVal* vv = v->AsVectorVal(); VectorVal* vv = v->AsVectorVal();
for ( unsigned int i = 0; i < vv->Size(); ++i ) for ( unsigned int i = 0; i < vv->Size(); ++i )
{ {
const String* s = vv->At(i)->AsString(); auto s = vv->StringAt(i);
patterns.push_back(std::string(reinterpret_cast<const char*>(s->Bytes()), s->Len())); patterns.push_back(std::string(reinterpret_cast<const char*>(s->Bytes()), s->Len()));
} }
@ -1293,7 +1293,7 @@ function any_set%(v: any%) : bool
VectorVal* vv = v->AsVectorVal(); VectorVal* vv = v->AsVectorVal();
for ( unsigned int i = 0; i < vv->Size(); ++i ) for ( unsigned int i = 0; i < vv->Size(); ++i )
if ( vv->At(i) && vv->At(i)->AsBool() ) if ( vv->BoolAt(i) )
return zeek::val_mgr->True(); return zeek::val_mgr->True();
return zeek::val_mgr->False(); return zeek::val_mgr->False();
@ -1322,7 +1322,7 @@ function all_set%(v: any%) : bool
VectorVal* vv = v->AsVectorVal(); VectorVal* vv = v->AsVectorVal();
for ( unsigned int i = 0; i < vv->Size(); ++i ) for ( unsigned int i = 0; i < vv->Size(); ++i )
if ( ! vv->At(i) || ! vv->At(i)->AsBool() ) if ( ! vv->BoolAt(i) )
return zeek::val_mgr->False(); return zeek::val_mgr->False();
return zeek::val_mgr->True(); return zeek::val_mgr->True();