@@ -24,14 +24,14 @@ namespace interp {
24
24
// / Stack frame storing temporaries and parameters.
25
25
class InterpStack final {
26
26
public:
27
- InterpStack () {}
27
+ InterpStack () = default ;
28
28
29
29
// / Destroys the stack, freeing up storage.
30
30
~InterpStack ();
31
31
32
32
// / Constructs a value in place on the top of the stack.
33
33
template <typename T, typename ... Tys> void push (Tys &&...Args) {
34
- new (grow ( aligned_size<T>())) T (std::forward<Tys>(Args)...);
34
+ new (grow< aligned_size<T>()>( )) T (std::forward<Tys>(Args)...);
35
35
ItemTypes.push_back (toPrimType<T>());
36
36
}
37
37
@@ -89,7 +89,7 @@ class InterpStack final {
89
89
private:
90
90
// / All stack slots are aligned to the native pointer alignment for storage.
91
91
// / The size of an object is rounded up to a pointer alignment multiple.
92
- template <typename T> constexpr size_t aligned_size () const {
92
+ template <typename T> static constexpr size_t aligned_size () {
93
93
constexpr size_t PtrAlign = alignof (void *);
94
94
return ((sizeof (T) + PtrAlign - 1 ) / PtrAlign) * PtrAlign;
95
95
}
@@ -100,7 +100,30 @@ class InterpStack final {
100
100
}
101
101
102
102
// / Grows the stack to accommodate a value and returns a pointer to it.
103
- void *grow (size_t Size);
103
+ template <size_t Size> void *grow () {
104
+ assert (Size < ChunkSize - sizeof (StackChunk) && " Object too large" );
105
+ static_assert (aligned (Size));
106
+
107
+ // Allocate a new stack chunk if necessary.
108
+ if (LLVM_UNLIKELY (!Chunk)) {
109
+ Chunk = new (std::malloc (ChunkSize)) StackChunk (Chunk);
110
+ } else if (LLVM_UNLIKELY (Chunk->size () >
111
+ ChunkSize - sizeof (StackChunk) - Size)) {
112
+ if (Chunk->Next ) {
113
+ Chunk = Chunk->Next ;
114
+ } else {
115
+ StackChunk *Next = new (std::malloc (ChunkSize)) StackChunk (Chunk);
116
+ Chunk->Next = Next;
117
+ Chunk = Next;
118
+ }
119
+ }
120
+
121
+ auto *Object = reinterpret_cast <void *>(Chunk->start () + Chunk->Size );
122
+ Chunk->Size += Size;
123
+ StackSize += Size;
124
+ return Object;
125
+ }
126
+
104
127
// / Returns a pointer from the top of the stack.
105
128
void *peekData (size_t Size) const ;
106
129
// / Shrinks the stack.
@@ -118,13 +141,13 @@ class InterpStack final {
118
141
struct StackChunk {
119
142
StackChunk *Next;
120
143
StackChunk *Prev;
121
- char *End ;
144
+ uint32_t Size ;
122
145
123
146
StackChunk (StackChunk *Prev = nullptr )
124
- : Next(nullptr ), Prev(Prev), End( reinterpret_cast < char *>( this + 1 ) ) {}
147
+ : Next(nullptr ), Prev(Prev), Size( 0 ) {}
125
148
126
149
// / Returns the size of the chunk, minus the header.
127
- size_t size () const { return End - start () ; }
150
+ size_t size () const { return Size ; }
128
151
129
152
// / Returns a pointer to the start of the data region.
130
153
char *start () { return reinterpret_cast <char *>(this + 1 ); }
0 commit comments