mirror of
https://github.com/zeek/zeek.git
synced 2025-10-10 18:48:20 +00:00
ZAM optimizations for record creation
This commit is contained in:
parent
6fc8397cbf
commit
94efeda228
3 changed files with 82 additions and 20 deletions
|
@ -1100,16 +1100,34 @@ const ZAMStmt ZAMCompiler::ConstructSet(const NameExpr* n, const Expr* e) {
|
|||
|
||||
const ZAMStmt ZAMCompiler::ConstructRecord(const NameExpr* n, const Expr* e) {
|
||||
auto rc = e->AsRecordConstructorExpr();
|
||||
auto rt = e->GetType()->AsRecordType();
|
||||
auto map = rc->Map();
|
||||
|
||||
ZInstI z;
|
||||
|
||||
if ( rc->Map() ) {
|
||||
z = GenInst(OP_CONSTRUCT_KNOWN_RECORD_V, n);
|
||||
if ( map ) {
|
||||
// Compute whether we need at least one of the default field
|
||||
// initializations. We don't need so if every one of the fields
|
||||
// with such an initializer is already covered in the map (meaning
|
||||
// it has an explicit initialization value).
|
||||
auto& ci = rt->CreationInits();
|
||||
zeek_uint_t common = 0;
|
||||
for ( auto& c : ci )
|
||||
for ( auto r : *map )
|
||||
if ( c.first == r )
|
||||
++common;
|
||||
|
||||
auto need_init = common != ci.size();
|
||||
|
||||
z = GenInst(OP_CONSTRUCT_KNOWN_RECORD_Vi, n, need_init);
|
||||
z.aux = InternalBuildVals(rc->Op().get());
|
||||
z.aux->map = *rc->Map();
|
||||
z.aux->map = *map;
|
||||
}
|
||||
else {
|
||||
z = GenInst(OP_CONSTRUCT_RECORD_V, n);
|
||||
// Constructors that don't need maps are explicitly initializing
|
||||
// every field, so they don't need default initializations, hence
|
||||
// "false" in the following.
|
||||
z = GenInst(OP_CONSTRUCT_DIRECT_RECORD_Vi, n, false);
|
||||
z.aux = InternalBuildVals(rc->Op().get());
|
||||
}
|
||||
|
||||
|
@ -1118,6 +1136,33 @@ const ZAMStmt ZAMCompiler::ConstructRecord(const NameExpr* n, const Expr* e) {
|
|||
if ( pfs->HasSideEffects(SideEffectsOp::CONSTRUCTION, z.t) )
|
||||
z.aux->can_change_non_locals = true;
|
||||
|
||||
// If one of the initialization values is an unspecified vector (which
|
||||
// in general we can't know until run-time) then we'll need to
|
||||
// "concretize" it. We first see whether this is a possibility, since
|
||||
// it usually isn't, by counting up how many of the record fields are
|
||||
// vectors.
|
||||
std::vector<int> vector_fields; // holds indices of the vector fields
|
||||
for ( int i = 0; i < z.aux->n; ++i ) {
|
||||
auto field_ind = map ? (*map)[i] : i;
|
||||
if ( rt->GetFieldType(field_ind)->Tag() == TYPE_VECTOR )
|
||||
vector_fields.push_back(field_ind);
|
||||
}
|
||||
|
||||
auto inst = AddInst(z);
|
||||
|
||||
if ( vector_fields.empty() )
|
||||
// Common case of no vector fields, we're done.
|
||||
return inst;
|
||||
|
||||
// Need to add a separate instruction for concretizing the fields.
|
||||
z = GenInst(OP_CONCRETIZE_VECTOR_FIELDS_V, n);
|
||||
z.t = e->GetType();
|
||||
int nf = static_cast<int>(vector_fields.size());
|
||||
z.aux = new ZInstAux(nf);
|
||||
z.aux->elems_has_slots = false; // we're storing field offsets, not slots
|
||||
for ( int i = 0; i < nf; ++i )
|
||||
z.aux->Add(i, vector_fields[i]);
|
||||
|
||||
return AddInst(z);
|
||||
}
|
||||
|
||||
|
|
|
@ -1199,35 +1199,49 @@ eval ConstructTableOrSetPre()
|
|||
|
||||
direct-unary-op Record-Constructor ConstructRecord
|
||||
|
||||
internal-op Construct-Record
|
||||
type V
|
||||
# v2 is boolean of whether to initialize fields. For this instruction,
|
||||
# it's always false.
|
||||
op Construct-Direct-Record
|
||||
type Vi
|
||||
eval EvalConstructRecord(, i)
|
||||
|
||||
# v2 is boolean of whether to initialize fields.
|
||||
op Construct-Known-Record
|
||||
type Vi
|
||||
eval EvalConstructRecord(auto& map = aux->map;, map[i])
|
||||
|
||||
macro EvalConstructRecord(map_init, map_accessor)
|
||||
auto rt = cast_intrusive<RecordType>(z.t);
|
||||
auto new_r = new RecordVal(rt);
|
||||
auto new_r = new RecordVal(rt, z.v2 ? RecordVal::RV_FULL_INIT : RecordVal::RV_SLOTS_INIT);
|
||||
auto aux = z.aux;
|
||||
auto n = aux->n;
|
||||
map_init
|
||||
for ( auto i = 0; i < n; ++i )
|
||||
{
|
||||
auto v_i = aux->ToVal(frame, i);
|
||||
auto ind = map_accessor;
|
||||
if ( v_i && v_i->GetType()->Tag() == TYPE_VECTOR &&
|
||||
v_i->GetType<VectorType>()->IsUnspecifiedVector() )
|
||||
{
|
||||
const auto& t_ind = rt->GetFieldType(ind);
|
||||
v_i->AsVectorVal()->Concretize(t_ind->Yield());
|
||||
}
|
||||
new_r->Assign(ind, v_i);
|
||||
}
|
||||
new_r->InitField(map_accessor, aux->ToZVal(frame, i));
|
||||
auto& r = frame[z.v1].record_val;
|
||||
Unref(r);
|
||||
r = new_r;
|
||||
|
||||
internal-op Construct-Known-Record
|
||||
# Special instruction for concretizing vectors that are fields in a
|
||||
# newly-constructed record. "aux" holds which fields in the record to
|
||||
# inspect.
|
||||
op Concretize-Vector-Fields
|
||||
op1-read
|
||||
type V
|
||||
eval EvalConstructRecord(auto& map = aux->map;, map[i])
|
||||
eval auto rt = cast_intrusive<RecordType>(z.t);
|
||||
auto r = frame[z.v1].record_val;
|
||||
auto aux = z.aux;
|
||||
auto n = aux->n;
|
||||
for ( auto i = 0; i < n; ++i )
|
||||
{
|
||||
auto v_i = r->GetField(aux->elems[i].IntVal());
|
||||
ASSERT(v_i);
|
||||
if ( v_i->GetType<VectorType>()->IsUnspecifiedVector() )
|
||||
{
|
||||
const auto& t_i = rt->GetFieldType(i);
|
||||
v_i->AsVectorVal()->Concretize(t_i->Yield());
|
||||
}
|
||||
}
|
||||
|
||||
direct-unary-op Vector-Constructor ConstructVector
|
||||
|
||||
|
|
|
@ -418,6 +418,9 @@ public:
|
|||
// and type.
|
||||
void Add(int i, int slot, TypePtr t) { elems[i].SetInt(slot, t); }
|
||||
|
||||
// Same, but for non-slot integers.
|
||||
void Add(int i, int v_i) { elems[i].SetInt(v_i); }
|
||||
|
||||
// Same but for constants.
|
||||
void Add(int i, ValPtr c) { elems[i].SetConstant(c); }
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue