@@ -24,14 +24,14 @@ namespace interp {
2424// / Stack frame storing temporaries and parameters.
2525class InterpStack final {
2626public:
27- InterpStack () {}
27+ InterpStack () = default ;
2828
2929 // / Destroys the stack, freeing up storage.
3030 ~InterpStack ();
3131
3232 // / Constructs a value in place on the top of the stack.
3333 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)...);
3535 ItemTypes.push_back (toPrimType<T>());
3636 }
3737
@@ -89,7 +89,7 @@ class InterpStack final {
8989private:
9090 // / All stack slots are aligned to the native pointer alignment for storage.
9191 // / 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 () {
9393 constexpr size_t PtrAlign = alignof (void *);
9494 return ((sizeof (T) + PtrAlign - 1 ) / PtrAlign) * PtrAlign;
9595 }
@@ -100,7 +100,30 @@ class InterpStack final {
100100 }
101101
102102 // / 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+
104127 // / Returns a pointer from the top of the stack.
105128 void *peekData (size_t Size) const ;
106129 // / Shrinks the stack.
@@ -118,13 +141,13 @@ class InterpStack final {
118141 struct StackChunk {
119142 StackChunk *Next;
120143 StackChunk *Prev;
121- char *End ;
144+ uint32_t Size ;
122145
123146 StackChunk (StackChunk *Prev = nullptr )
124- : Next(nullptr ), Prev(Prev), End( reinterpret_cast < char *>( this + 1 ) ) {}
147+ : Next(nullptr ), Prev(Prev), Size( 0 ) {}
125148
126149 // / Returns the size of the chunk, minus the header.
127- size_t size () const { return End - start () ; }
150+ size_t size () const { return Size ; }
128151
129152 // / Returns a pointer to the start of the data region.
130153 char *start () { return reinterpret_cast <char *>(this + 1 ); }
0 commit comments