mirror of
https://github.com/zeek/zeek.git
synced 2025-10-11 02:58: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) {
|
const ZAMStmt ZAMCompiler::ConstructRecord(const NameExpr* n, const Expr* e) {
|
||||||
auto rc = e->AsRecordConstructorExpr();
|
auto rc = e->AsRecordConstructorExpr();
|
||||||
|
auto rt = e->GetType()->AsRecordType();
|
||||||
|
auto map = rc->Map();
|
||||||
|
|
||||||
ZInstI z;
|
ZInstI z;
|
||||||
|
|
||||||
if ( rc->Map() ) {
|
if ( map ) {
|
||||||
z = GenInst(OP_CONSTRUCT_KNOWN_RECORD_V, n);
|
// 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 = InternalBuildVals(rc->Op().get());
|
||||||
z.aux->map = *rc->Map();
|
z.aux->map = *map;
|
||||||
}
|
}
|
||||||
else {
|
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());
|
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) )
|
if ( pfs->HasSideEffects(SideEffectsOp::CONSTRUCTION, z.t) )
|
||||||
z.aux->can_change_non_locals = true;
|
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);
|
return AddInst(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1199,35 +1199,49 @@ eval ConstructTableOrSetPre()
|
||||||
|
|
||||||
direct-unary-op Record-Constructor ConstructRecord
|
direct-unary-op Record-Constructor ConstructRecord
|
||||||
|
|
||||||
internal-op Construct-Record
|
# v2 is boolean of whether to initialize fields. For this instruction,
|
||||||
type V
|
# it's always false.
|
||||||
|
op Construct-Direct-Record
|
||||||
|
type Vi
|
||||||
eval EvalConstructRecord(, i)
|
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)
|
macro EvalConstructRecord(map_init, map_accessor)
|
||||||
auto rt = cast_intrusive<RecordType>(z.t);
|
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 aux = z.aux;
|
||||||
auto n = aux->n;
|
auto n = aux->n;
|
||||||
map_init
|
map_init
|
||||||
for ( auto i = 0; i < n; ++i )
|
for ( auto i = 0; i < n; ++i )
|
||||||
{
|
new_r->InitField(map_accessor, aux->ToZVal(frame, 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);
|
|
||||||
}
|
|
||||||
auto& r = frame[z.v1].record_val;
|
auto& r = frame[z.v1].record_val;
|
||||||
Unref(r);
|
Unref(r);
|
||||||
r = new_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
|
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
|
direct-unary-op Vector-Constructor ConstructVector
|
||||||
|
|
||||||
|
|
|
@ -418,6 +418,9 @@ public:
|
||||||
// and type.
|
// and type.
|
||||||
void Add(int i, int slot, TypePtr t) { elems[i].SetInt(slot, t); }
|
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.
|
// Same but for constants.
|
||||||
void Add(int i, ValPtr c) { elems[i].SetConstant(c); }
|
void Add(int i, ValPtr c) { elems[i].SetConstant(c); }
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue