Coverage Report

Created: 2026-09-03 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/eval/eval/evaluator_stack.h
Line
Count
Source
1
#ifndef THIRD_PARTY_CEL_CPP_EVAL_EVAL_EVALUATOR_STACK_H_
2
#define THIRD_PARTY_CEL_CPP_EVAL_EVAL_EVALUATOR_STACK_H_
3
4
#include <algorithm>
5
#include <cstddef>
6
#include <memory>
7
#include <type_traits>
8
#include <utility>
9
10
#include "absl/base/attributes.h"
11
#include "absl/base/dynamic_annotations.h"
12
#include "absl/base/nullability.h"
13
#include "absl/base/optimization.h"
14
#include "absl/log/absl_check.h"
15
#include "absl/meta/type_traits.h"
16
#include "absl/types/optional.h"
17
#include "absl/types/span.h"
18
#include "common/value.h"
19
#include "eval/eval/attribute_trail.h"
20
#include "internal/align.h"
21
#include "internal/new.h"
22
23
namespace google::api::expr::runtime {
24
25
// CelValue stack.
26
// Implementation is based on vector to allow passing parameters from
27
// stack as Span<>.
28
class EvaluatorStack {
29
 public:
30
16.9k
  explicit EvaluatorStack(size_t max_size) { Reserve(max_size); }
31
32
  EvaluatorStack(const EvaluatorStack&) = delete;
33
  EvaluatorStack(EvaluatorStack&&) = delete;
34
35
16.9k
  ~EvaluatorStack() {
36
16.9k
    if (max_size() > 0) {
37
16.9k
      const size_t n = size();
38
16.9k
      std::destroy_n(values_begin_, n);
39
16.9k
      std::destroy_n(attributes_begin_, n);
40
16.9k
      cel::internal::SizedDelete(data_, SizeBytes(max_size_));
41
16.9k
    }
42
16.9k
  }
43
44
  EvaluatorStack& operator=(const EvaluatorStack&) = delete;
45
  EvaluatorStack& operator=(EvaluatorStack&&) = delete;
46
47
  // Return the current stack size.
48
17.1M
  size_t size() const {
49
17.1M
    ABSL_DCHECK_GE(values_, values_begin_);
50
17.1M
    ABSL_DCHECK_LE(values_, values_begin_ + max_size_);
51
17.1M
    ABSL_DCHECK_GE(attributes_, attributes_begin_);
52
17.1M
    ABSL_DCHECK_LE(attributes_, attributes_begin_ + max_size_);
53
17.1M
    ABSL_DCHECK_EQ(values_ - values_begin_, attributes_ - attributes_begin_);
54
55
17.1M
    return values_ - values_begin_;
56
17.1M
  }
57
58
  // Return the maximum size of the stack.
59
50.8k
  size_t max_size() const {
60
50.8k
    ABSL_DCHECK_GE(values_, values_begin_);
61
50.8k
    ABSL_DCHECK_LE(values_, values_begin_ + max_size_);
62
50.8k
    ABSL_DCHECK_GE(attributes_, attributes_begin_);
63
50.8k
    ABSL_DCHECK_LE(attributes_, attributes_begin_ + max_size_);
64
50.8k
    ABSL_DCHECK_EQ(values_ - values_begin_, attributes_ - attributes_begin_);
65
66
50.8k
    return max_size_;
67
50.8k
  }
68
69
  // Returns true if stack is empty.
70
0
  bool empty() const {
71
0
    ABSL_DCHECK_GE(values_, values_begin_);
72
0
    ABSL_DCHECK_LE(values_, values_begin_ + max_size_);
73
0
    ABSL_DCHECK_GE(attributes_, attributes_begin_);
74
0
    ABSL_DCHECK_LE(attributes_, attributes_begin_ + max_size_);
75
0
    ABSL_DCHECK_EQ(values_ - values_begin_, attributes_ - attributes_begin_);
76
77
0
    return values_ == values_begin_;
78
0
  }
79
80
18.5M
  bool full() const {
81
18.5M
    ABSL_DCHECK_GE(values_, values_begin_);
82
18.5M
    ABSL_DCHECK_LE(values_, values_begin_ + max_size_);
83
18.5M
    ABSL_DCHECK_GE(attributes_, attributes_begin_);
84
18.5M
    ABSL_DCHECK_LE(attributes_, attributes_begin_ + max_size_);
85
18.5M
    ABSL_DCHECK_EQ(values_ - values_begin_, attributes_ - attributes_begin_);
86
87
18.5M
    return values_ == values_end_;
88
18.5M
  }
89
90
  // Attributes stack size.
91
  ABSL_DEPRECATED("Use size()")
92
0
  size_t attribute_size() const { return size(); }
93
94
  // Check that stack has enough elements.
95
15.8M
  bool HasEnough(size_t size) const { return this->size() >= size; }
96
97
  // Dumps the entire stack state as is.
98
33.9k
  void Clear() {
99
33.9k
    if (max_size() > 0) {
100
33.9k
      const size_t n = size();
101
33.9k
      std::destroy_n(values_begin_, n);
102
33.9k
      std::destroy_n(attributes_begin_, n);
103
104
33.9k
      ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(
105
33.9k
          values_begin_, values_begin_ + max_size_, values_, values_begin_);
106
33.9k
      ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(attributes_begin_,
107
33.9k
                                         attributes_begin_ + max_size_,
108
33.9k
                                         attributes_, attributes_begin_);
109
110
33.9k
      values_ = values_begin_;
111
33.9k
      attributes_ = attributes_begin_;
112
33.9k
    }
113
33.9k
  }
114
115
  // Gets the last size elements of the stack.
116
  // Checking that stack has enough elements is caller's responsibility.
117
  // Please note that calls to Push may invalidate returned Span object.
118
12.6M
  absl::Span<const cel::Value> GetSpan(size_t size) const {
119
12.6M
    ABSL_DCHECK(HasEnough(size));
120
121
12.6M
    return absl::Span<const cel::Value>(values_ - size, size);
122
12.6M
  }
123
124
  // Gets the last size attribute trails of the stack.
125
  // Checking that stack has enough elements is caller's responsibility.
126
  // Please note that calls to Push may invalidate returned Span object.
127
1.27M
  absl::Span<const AttributeTrail> GetAttributeSpan(size_t size) const {
128
1.27M
    ABSL_DCHECK(HasEnough(size));
129
130
1.27M
    return absl::Span<const AttributeTrail>(attributes_ - size, size);
131
1.27M
  }
132
133
  // Peeks the last element of the stack.
134
  // Checking that stack is not empty is caller's responsibility.
135
4.28M
  cel::Value& Peek() {
136
4.28M
    ABSL_DCHECK(HasEnough(1));
137
138
4.28M
    return *(values_ - 1);
139
4.28M
  }
140
141
  // Peeks the last element of the stack.
142
  // Checking that stack is not empty is caller's responsibility.
143
0
  const cel::Value& Peek() const {
144
0
    ABSL_DCHECK(HasEnough(1));
145
0
146
0
    return *(values_ - 1);
147
0
  }
148
149
  // Peeks the last element of the attribute stack.
150
  // Checking that stack is not empty is caller's responsibility.
151
0
  const AttributeTrail& PeekAttribute() const {
152
0
    ABSL_DCHECK(HasEnough(1));
153
0
154
0
    return *(attributes_ - 1);
155
0
  }
156
157
  // Peeks the last element of the attribute stack.
158
  // Checking that stack is not empty is caller's responsibility.
159
2.45M
  AttributeTrail& PeekAttribute() {
160
2.45M
    ABSL_DCHECK(HasEnough(1));
161
162
2.45M
    return *(attributes_ - 1);
163
2.45M
  }
164
165
18.5M
  void Pop() {
166
18.5M
    ABSL_DCHECK(!empty());
167
168
18.5M
    --values_;
169
18.5M
    values_->~Value();
170
18.5M
    --attributes_;
171
18.5M
    attributes_->~AttributeTrail();
172
173
18.5M
    ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(values_begin_, values_begin_ + max_size_,
174
18.5M
                                       values_ + 1, values_);
175
18.5M
    ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(attributes_begin_,
176
18.5M
                                       attributes_begin_ + max_size_,
177
18.5M
                                       attributes_ + 1, attributes_);
178
18.5M
  }
179
180
  // Clears the last size elements of the stack.
181
  // Checking that stack has enough elements is caller's responsibility.
182
13.9M
  void Pop(size_t size) {
183
13.9M
    ABSL_DCHECK(HasEnough(size));
184
185
32.5M
    for (; size > 0; --size) {
186
18.5M
      Pop();
187
18.5M
    }
188
13.9M
  }
189
190
  template <typename V, typename A,
191
            typename = std::enable_if_t<
192
                std::conjunction_v<std::is_convertible<V, cel::Value>,
193
                                   std::is_convertible<A, AttributeTrail>>>>
194
18.5M
  void Push(V&& value, A&& attribute) {
195
18.5M
    ABSL_DCHECK(!full());
196
197
18.5M
    if (ABSL_PREDICT_FALSE(full())) {
198
0
      Grow();
199
0
    }
200
201
18.5M
    ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(values_begin_, values_begin_ + max_size_,
202
18.5M
                                       values_, values_ + 1);
203
18.5M
    ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(attributes_begin_,
204
18.5M
                                       attributes_begin_ + max_size_,
205
18.5M
                                       attributes_, attributes_ + 1);
206
207
18.5M
    ::new (static_cast<void*>(values_++)) cel::Value(std::forward<V>(value));
208
18.5M
    ::new (static_cast<void*>(attributes_++))
209
18.5M
        AttributeTrail(std::forward<A>(attribute));
210
18.5M
  }
Unexecuted instantiation: void google::api::expr::runtime::EvaluatorStack::Push<cel::BoolValue, std::__1::nullopt_t const&, void>(cel::BoolValue&&, std::__1::nullopt_t const&)
void google::api::expr::runtime::EvaluatorStack::Push<cel::Value, google::api::expr::runtime::AttributeTrail, void>(cel::Value&&, google::api::expr::runtime::AttributeTrail&&)
Line
Count
Source
194
2.74M
  void Push(V&& value, A&& attribute) {
195
2.74M
    ABSL_DCHECK(!full());
196
197
2.74M
    if (ABSL_PREDICT_FALSE(full())) {
198
0
      Grow();
199
0
    }
200
201
2.74M
    ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(values_begin_, values_begin_ + max_size_,
202
2.74M
                                       values_, values_ + 1);
203
2.74M
    ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(attributes_begin_,
204
2.74M
                                       attributes_begin_ + max_size_,
205
2.74M
                                       attributes_, attributes_ + 1);
206
207
2.74M
    ::new (static_cast<void*>(values_++)) cel::Value(std::forward<V>(value));
208
2.74M
    ::new (static_cast<void*>(attributes_++))
209
2.74M
        AttributeTrail(std::forward<A>(attribute));
210
2.74M
  }
Unexecuted instantiation: void google::api::expr::runtime::EvaluatorStack::Push<cel::ErrorValue, std::__1::nullopt_t const&, void>(cel::ErrorValue&&, std::__1::nullopt_t const&)
void google::api::expr::runtime::EvaluatorStack::Push<cel::Value const&, std::__1::nullopt_t const&, void>(cel::Value const&, std::__1::nullopt_t const&)
Line
Count
Source
194
12.1M
  void Push(V&& value, A&& attribute) {
195
12.1M
    ABSL_DCHECK(!full());
196
197
12.1M
    if (ABSL_PREDICT_FALSE(full())) {
198
0
      Grow();
199
0
    }
200
201
12.1M
    ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(values_begin_, values_begin_ + max_size_,
202
12.1M
                                       values_, values_ + 1);
203
12.1M
    ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(attributes_begin_,
204
12.1M
                                       attributes_begin_ + max_size_,
205
12.1M
                                       attributes_, attributes_ + 1);
206
207
12.1M
    ::new (static_cast<void*>(values_++)) cel::Value(std::forward<V>(value));
208
12.1M
    ::new (static_cast<void*>(attributes_++))
209
12.1M
        AttributeTrail(std::forward<A>(attribute));
210
12.1M
  }
void google::api::expr::runtime::EvaluatorStack::Push<cel::Value, std::__1::nullopt_t const&, void>(cel::Value&&, std::__1::nullopt_t const&)
Line
Count
Source
194
1.36M
  void Push(V&& value, A&& attribute) {
195
1.36M
    ABSL_DCHECK(!full());
196
197
1.36M
    if (ABSL_PREDICT_FALSE(full())) {
198
0
      Grow();
199
0
    }
200
201
1.36M
    ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(values_begin_, values_begin_ + max_size_,
202
1.36M
                                       values_, values_ + 1);
203
1.36M
    ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(attributes_begin_,
204
1.36M
                                       attributes_begin_ + max_size_,
205
1.36M
                                       attributes_, attributes_ + 1);
206
207
1.36M
    ::new (static_cast<void*>(values_++)) cel::Value(std::forward<V>(value));
208
1.36M
    ::new (static_cast<void*>(attributes_++))
209
1.36M
        AttributeTrail(std::forward<A>(attribute));
210
1.36M
  }
Unexecuted instantiation: void google::api::expr::runtime::EvaluatorStack::Push<cel::CustomListValue, std::__1::nullopt_t const&, void>(cel::CustomListValue&&, std::__1::nullopt_t const&)
Unexecuted instantiation: void google::api::expr::runtime::EvaluatorStack::Push<cel::CustomMapValue, std::__1::nullopt_t const&, void>(cel::CustomMapValue&&, std::__1::nullopt_t const&)
void google::api::expr::runtime::EvaluatorStack::Push<cel::Value const&, google::api::expr::runtime::AttributeTrail const&, void>(cel::Value const&, google::api::expr::runtime::AttributeTrail const&)
Line
Count
Source
194
2.37M
  void Push(V&& value, A&& attribute) {
195
2.37M
    ABSL_DCHECK(!full());
196
197
2.37M
    if (ABSL_PREDICT_FALSE(full())) {
198
0
      Grow();
199
0
    }
200
201
2.37M
    ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(values_begin_, values_begin_ + max_size_,
202
2.37M
                                       values_, values_ + 1);
203
2.37M
    ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(attributes_begin_,
204
2.37M
                                       attributes_begin_ + max_size_,
205
2.37M
                                       attributes_, attributes_ + 1);
206
207
2.37M
    ::new (static_cast<void*>(values_++)) cel::Value(std::forward<V>(value));
208
2.37M
    ::new (static_cast<void*>(attributes_++))
209
2.37M
        AttributeTrail(std::forward<A>(attribute));
210
2.37M
  }
211
212
  template <typename V,
213
            typename = std::enable_if_t<std::is_convertible_v<V, cel::Value>>>
214
12.1M
  void Push(V&& value) {
215
12.1M
    ABSL_DCHECK(!full());
216
217
12.1M
    Push(std::forward<V>(value), absl::nullopt);
218
12.1M
  }
Unexecuted instantiation: void google::api::expr::runtime::EvaluatorStack::Push<cel::BoolValue, void>(cel::BoolValue&&)
void google::api::expr::runtime::EvaluatorStack::Push<cel::Value const&, void>(cel::Value const&)
Line
Count
Source
214
12.1M
  void Push(V&& value) {
215
12.1M
    ABSL_DCHECK(!full());
216
217
12.1M
    Push(std::forward<V>(value), absl::nullopt);
218
12.1M
  }
Unexecuted instantiation: void google::api::expr::runtime::EvaluatorStack::Push<cel::CustomListValue, void>(cel::CustomListValue&&)
Unexecuted instantiation: void google::api::expr::runtime::EvaluatorStack::Push<cel::CustomMapValue, void>(cel::CustomMapValue&&)
Unexecuted instantiation: void google::api::expr::runtime::EvaluatorStack::Push<cel::Value, void>(cel::Value&&)
219
220
  // Equivalent to `PopAndPush(1, ...)`.
221
  template <typename V, typename A,
222
            typename = std::enable_if_t<
223
                std::conjunction_v<std::is_convertible<V, cel::Value>,
224
                                   std::is_convertible<A, AttributeTrail>>>>
225
358k
  void PopAndPush(V&& value, A&& attribute) {
226
358k
    ABSL_DCHECK(!empty());
227
228
358k
    *(values_ - 1) = std::forward<V>(value);
229
358k
    *(attributes_ - 1) = std::forward<A>(attribute);
230
358k
  }
Unexecuted instantiation: void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::UnknownValue, std::__1::nullopt_t const&, void>(cel::UnknownValue&&, std::__1::nullopt_t const&)
void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::ErrorValue, std::__1::nullopt_t const&, void>(cel::ErrorValue&&, std::__1::nullopt_t const&)
Line
Count
Source
225
40.3k
  void PopAndPush(V&& value, A&& attribute) {
226
40.3k
    ABSL_DCHECK(!empty());
227
228
40.3k
    *(values_ - 1) = std::forward<V>(value);
229
40.3k
    *(attributes_ - 1) = std::forward<A>(attribute);
230
40.3k
  }
void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::BoolValue, std::__1::nullopt_t const&, void>(cel::BoolValue&&, std::__1::nullopt_t const&)
Line
Count
Source
225
241
  void PopAndPush(V&& value, A&& attribute) {
226
241
    ABSL_DCHECK(!empty());
227
228
241
    *(values_ - 1) = std::forward<V>(value);
229
241
    *(attributes_ - 1) = std::forward<A>(attribute);
230
241
  }
void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::Value, std::__1::nullopt_t const&, void>(cel::Value&&, std::__1::nullopt_t const&)
Line
Count
Source
225
19.0k
  void PopAndPush(V&& value, A&& attribute) {
226
19.0k
    ABSL_DCHECK(!empty());
227
228
19.0k
    *(values_ - 1) = std::forward<V>(value);
229
19.0k
    *(attributes_ - 1) = std::forward<A>(attribute);
230
19.0k
  }
void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::ErrorValue, google::api::expr::runtime::AttributeTrail, void>(cel::ErrorValue&&, google::api::expr::runtime::AttributeTrail&&)
Line
Count
Source
225
97.3k
  void PopAndPush(V&& value, A&& attribute) {
226
97.3k
    ABSL_DCHECK(!empty());
227
228
97.3k
    *(values_ - 1) = std::forward<V>(value);
229
97.3k
    *(attributes_ - 1) = std::forward<A>(attribute);
230
97.3k
  }
void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::Value, google::api::expr::runtime::AttributeTrail, void>(cel::Value&&, google::api::expr::runtime::AttributeTrail&&)
Line
Count
Source
225
201k
  void PopAndPush(V&& value, A&& attribute) {
226
201k
    ABSL_DCHECK(!empty());
227
228
201k
    *(values_ - 1) = std::forward<V>(value);
229
201k
    *(attributes_ - 1) = std::forward<A>(attribute);
230
201k
  }
Unexecuted instantiation: void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::BoolValue, google::api::expr::runtime::AttributeTrail, void>(cel::BoolValue&&, google::api::expr::runtime::AttributeTrail&&)
Unexecuted instantiation: void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::OptionalValue, google::api::expr::runtime::AttributeTrail, void>(cel::OptionalValue&&, google::api::expr::runtime::AttributeTrail&&)
231
232
  // Equivalent to `PopAndPush(1, ...)`.
233
  template <typename V,
234
            typename = std::enable_if_t<std::is_convertible_v<V, cel::Value>>>
235
59.6k
  void PopAndPush(V&& value) {
236
59.6k
    ABSL_DCHECK(!empty());
237
238
59.6k
    PopAndPush(std::forward<V>(value), absl::nullopt);
239
59.6k
  }
Unexecuted instantiation: void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::UnknownValue, void>(cel::UnknownValue&&)
void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::ErrorValue, void>(cel::ErrorValue&&)
Line
Count
Source
235
40.3k
  void PopAndPush(V&& value) {
236
40.3k
    ABSL_DCHECK(!empty());
237
238
40.3k
    PopAndPush(std::forward<V>(value), absl::nullopt);
239
40.3k
  }
void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::BoolValue, void>(cel::BoolValue&&)
Line
Count
Source
235
241
  void PopAndPush(V&& value) {
236
241
    ABSL_DCHECK(!empty());
237
238
241
    PopAndPush(std::forward<V>(value), absl::nullopt);
239
241
  }
void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::Value, void>(cel::Value&&)
Line
Count
Source
235
19.0k
  void PopAndPush(V&& value) {
236
19.0k
    ABSL_DCHECK(!empty());
237
238
19.0k
    PopAndPush(std::forward<V>(value), absl::nullopt);
239
19.0k
  }
240
241
  // Equivalent to `Pop(n)` followed by `Push(...)`. Both `V` and `A` MUST NOT
242
  // be located on the stack. If this is the case, use SwapAndPop instead.
243
  template <typename V, typename A,
244
            typename = std::enable_if_t<
245
                std::conjunction_v<std::is_convertible<V, cel::Value>,
246
                                   std::is_convertible<A, AttributeTrail>>>>
247
12.6M
  void PopAndPush(size_t n, V&& value, A&& attribute) {
248
12.6M
    if (n > 0) {
249
11.3M
      if constexpr (std::is_same_v<cel::Value, absl::remove_cvref_t<V>>) {
250
22.6M
        ABSL_DCHECK(&value < values_begin_ ||
251
22.6M
                    &value >= values_begin_ + max_size_)
252
22.6M
            << "Attmpting to push a value about to be popped, use PopAndSwap "
253
22.6M
               "instead.";
254
11.3M
      }
255
11.3M
      if constexpr (std::is_same_v<AttributeTrail, absl::remove_cvref_t<A>>) {
256
1.17M
        ABSL_DCHECK(&attribute < attributes_begin_ ||
257
1.17M
                    &attribute >= attributes_begin_ + max_size_)
258
1.17M
            << "Attmpting to push an attribute about to be popped, use "
259
1.17M
               "PopAndSwap instead.";
260
588k
      }
261
262
11.3M
      Pop(n - 1);
263
264
11.3M
      ABSL_DCHECK(!empty());
265
266
11.3M
      *(values_ - 1) = std::forward<V>(value);
267
11.3M
      *(attributes_ - 1) = std::forward<A>(attribute);
268
11.3M
    } else {
269
1.36M
      Push(std::forward<V>(value), std::forward<A>(attribute));
270
1.36M
    }
271
12.6M
  }
Unexecuted instantiation: void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::ErrorValue, std::__1::nullopt_t const&, void>(unsigned long, cel::ErrorValue&&, std::__1::nullopt_t const&)
void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::Value, google::api::expr::runtime::AttributeTrail, void>(unsigned long, cel::Value&&, google::api::expr::runtime::AttributeTrail&&)
Line
Count
Source
247
588k
  void PopAndPush(size_t n, V&& value, A&& attribute) {
248
588k
    if (n > 0) {
249
588k
      if constexpr (std::is_same_v<cel::Value, absl::remove_cvref_t<V>>) {
250
1.17M
        ABSL_DCHECK(&value < values_begin_ ||
251
1.17M
                    &value >= values_begin_ + max_size_)
252
1.17M
            << "Attmpting to push a value about to be popped, use PopAndSwap "
253
1.17M
               "instead.";
254
588k
      }
255
588k
      if constexpr (std::is_same_v<AttributeTrail, absl::remove_cvref_t<A>>) {
256
1.17M
        ABSL_DCHECK(&attribute < attributes_begin_ ||
257
1.17M
                    &attribute >= attributes_begin_ + max_size_)
258
1.17M
            << "Attmpting to push an attribute about to be popped, use "
259
1.17M
               "PopAndSwap instead.";
260
588k
      }
261
262
588k
      Pop(n - 1);
263
264
588k
      ABSL_DCHECK(!empty());
265
266
588k
      *(values_ - 1) = std::forward<V>(value);
267
588k
      *(attributes_ - 1) = std::forward<A>(attribute);
268
588k
    } else {
269
0
      Push(std::forward<V>(value), std::forward<A>(attribute));
270
0
    }
271
588k
  }
void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::Value, std::__1::nullopt_t const&, void>(unsigned long, cel::Value&&, std::__1::nullopt_t const&)
Line
Count
Source
247
12.0M
  void PopAndPush(size_t n, V&& value, A&& attribute) {
248
12.0M
    if (n > 0) {
249
10.7M
      if constexpr (std::is_same_v<cel::Value, absl::remove_cvref_t<V>>) {
250
21.4M
        ABSL_DCHECK(&value < values_begin_ ||
251
21.4M
                    &value >= values_begin_ + max_size_)
252
21.4M
            << "Attmpting to push a value about to be popped, use PopAndSwap "
253
21.4M
               "instead.";
254
10.7M
      }
255
      if constexpr (std::is_same_v<AttributeTrail, absl::remove_cvref_t<A>>) {
256
        ABSL_DCHECK(&attribute < attributes_begin_ ||
257
                    &attribute >= attributes_begin_ + max_size_)
258
            << "Attmpting to push an attribute about to be popped, use "
259
               "PopAndSwap instead.";
260
      }
261
262
10.7M
      Pop(n - 1);
263
264
10.7M
      ABSL_DCHECK(!empty());
265
266
10.7M
      *(values_ - 1) = std::forward<V>(value);
267
10.7M
      *(attributes_ - 1) = std::forward<A>(attribute);
268
10.7M
    } else {
269
1.36M
      Push(std::forward<V>(value), std::forward<A>(attribute));
270
1.36M
    }
271
12.0M
  }
272
273
  // Equivalent to `Pop(n)` followed by `Push(...)`. `V` MUST NOT be located on
274
  // the stack. If this is the case, use SwapAndPop instead.
275
  template <typename V,
276
            typename = std::enable_if_t<std::is_convertible_v<V, cel::Value>>>
277
12.0M
  void PopAndPush(size_t n, V&& value) {
278
12.0M
    PopAndPush(n, std::forward<V>(value), absl::nullopt);
279
12.0M
  }
Unexecuted instantiation: void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::ErrorValue, void>(unsigned long, cel::ErrorValue&&)
void google::api::expr::runtime::EvaluatorStack::PopAndPush<cel::Value, void>(unsigned long, cel::Value&&)
Line
Count
Source
277
12.0M
  void PopAndPush(size_t n, V&& value) {
278
12.0M
    PopAndPush(n, std::forward<V>(value), absl::nullopt);
279
12.0M
  }
280
281
  // Swaps the `n - i` element (from the top of the stack) with the `n` element,
282
  // and pops `n - 1` elements. This results in the `n - i` element being at the
283
  // top of the stack.
284
168k
  void SwapAndPop(size_t n, size_t i) {
285
168k
    ABSL_DCHECK_GT(n, 0);
286
168k
    ABSL_DCHECK_LT(i, n);
287
168k
    ABSL_DCHECK(HasEnough(n - 1));
288
289
168k
    using std::swap;
290
291
168k
    if (i > 0) {
292
166k
      swap(*(values_ - n), *(values_ - n + i));
293
166k
      swap(*(attributes_ - n), *(attributes_ - n + i));
294
166k
    }
295
168k
    Pop(n - 1);
296
168k
  }
297
298
  // Update the max size of the stack and update capacity if needed.
299
0
  void SetMaxSize(size_t size) { Reserve(size); }
300
301
 private:
302
50.8k
  static size_t AttributesBytesOffset(size_t size) {
303
50.8k
    return cel::internal::AlignUp(sizeof(cel::Value) * size,
304
50.8k
                                  __STDCPP_DEFAULT_NEW_ALIGNMENT__);
305
50.8k
  }
306
307
33.9k
  static size_t SizeBytes(size_t size) {
308
33.9k
    return AttributesBytesOffset(size) + (sizeof(AttributeTrail) * size);
309
33.9k
  }
310
311
  void Grow();
312
313
  // Preallocate stack.
314
  void Reserve(size_t size);
315
316
  cel::Value* absl_nullability_unknown values_ = nullptr;
317
  cel::Value* absl_nullability_unknown values_begin_ = nullptr;
318
  AttributeTrail* absl_nullability_unknown attributes_ = nullptr;
319
  AttributeTrail* absl_nullability_unknown attributes_begin_ = nullptr;
320
  cel::Value* absl_nullability_unknown values_end_ = nullptr;
321
  void* absl_nullability_unknown data_ = nullptr;
322
  size_t max_size_ = 0;
323
};
324
325
}  // namespace google::api::expr::runtime
326
327
#endif  // THIRD_PARTY_CEL_CPP_EVAL_EVAL_EVALUATOR_STACK_H_