Skip to content

Commit f354981

Browse files
authored
[clang][bytecode] Stack-allocate bottom function frame (#125253)
Instead of heap-allocating it. This is similar to what the current interpeter does. In C, we have no function calls, so the extra heap allocation never makes sense.
1 parent 6b8d076 commit f354981

File tree

6 files changed

+23
-7
lines changed

6 files changed

+23
-7
lines changed

clang/lib/AST/ByteCode/EvalEmitter.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@ using namespace clang::interp;
1717

1818
EvalEmitter::EvalEmitter(Context &Ctx, Program &P, State &Parent,
1919
InterpStack &Stk)
20-
: Ctx(Ctx), P(P), S(Parent, P, Stk, Ctx, this), EvalResult(&Ctx) {
21-
// Create a dummy frame for the interpreter which does not have locals.
22-
S.Current =
23-
new InterpFrame(S, /*Func=*/nullptr, /*Caller=*/nullptr, CodePtr(), 0);
20+
: Ctx(Ctx), P(P), S(Parent, P, Stk, Ctx, this), EvalResult(&Ctx),
21+
BottomFrame(S) {
22+
S.Current = &BottomFrame;
2423
}
2524

2625
EvalEmitter::~EvalEmitter() {

clang/lib/AST/ByteCode/EvalEmitter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ class EvalEmitter : public SourceMapper {
122122
/// Active block which should be executed.
123123
LabelTy ActiveLabel = 0;
124124

125+
InterpFrame BottomFrame;
126+
125127
protected:
126128
#define GET_EVAL_PROTO
127129
#include "Opcodes.inc"

clang/lib/AST/ByteCode/Interp.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,11 +325,11 @@ bool Ret(InterpState &S, CodePtr &PC) {
325325

326326
if (InterpFrame *Caller = S.Current->Caller) {
327327
PC = S.Current->getRetPC();
328-
delete S.Current;
328+
InterpFrame::free(S.Current);
329329
S.Current = Caller;
330330
S.Stk.push<T>(Ret);
331331
} else {
332-
delete S.Current;
332+
InterpFrame::free(S.Current);
333333
S.Current = nullptr;
334334
// The topmost frame should come from an EvalEmitter,
335335
// which has its own implementation of the Ret<> instruction.

clang/lib/AST/ByteCode/InterpFrame.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
using namespace clang;
2424
using namespace clang::interp;
2525

26+
InterpFrame::InterpFrame(InterpState &S)
27+
: Caller(nullptr), S(S), Depth(0), Func(nullptr), RetPC(CodePtr()),
28+
ArgSize(0), Args(nullptr), FrameOffset(0), IsBottom(true) {}
29+
2630
InterpFrame::InterpFrame(InterpState &S, const Function *Func,
2731
InterpFrame *Caller, CodePtr RetPC, unsigned ArgSize)
2832
: Caller(Caller), S(S), Depth(Caller ? Caller->Depth + 1 : 0), Func(Func),

clang/lib/AST/ByteCode/InterpFrame.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ class InterpFrame final : public Frame {
2828
/// The frame of the previous function.
2929
InterpFrame *Caller;
3030

31+
/// Bottom Frame.
32+
InterpFrame(InterpState &S);
33+
3134
/// Creates a new frame for a method call.
3235
InterpFrame(InterpState &S, const Function *Func, InterpFrame *Caller,
3336
CodePtr RetPC, unsigned ArgSize);
@@ -42,6 +45,11 @@ class InterpFrame final : public Frame {
4245
/// Destroys the frame, killing all live pointers to stack slots.
4346
~InterpFrame();
4447

48+
static void free(InterpFrame *F) {
49+
if (!F->isBottomFrame())
50+
delete F;
51+
}
52+
4553
/// Invokes the destructors for a scope.
4654
void destroy(unsigned Idx);
4755
void initScope(unsigned Idx);
@@ -119,6 +127,8 @@ class InterpFrame final : public Frame {
119127

120128
bool isStdFunction() const;
121129

130+
bool isBottomFrame() const { return IsBottom; }
131+
122132
void dump() const { dump(llvm::errs(), 0); }
123133
void dump(llvm::raw_ostream &OS, unsigned Indent = 0) const;
124134

@@ -167,6 +177,7 @@ class InterpFrame final : public Frame {
167177
const size_t FrameOffset;
168178
/// Mapping from arg offsets to their argument blocks.
169179
llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Params;
180+
bool IsBottom = false;
170181
};
171182

172183
} // namespace interp

clang/lib/AST/ByteCode/InterpState.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ bool InterpState::inConstantContext() const {
2727
}
2828

2929
InterpState::~InterpState() {
30-
while (Current) {
30+
while (Current && !Current->isBottomFrame()) {
3131
InterpFrame *Next = Current->Caller;
3232
delete Current;
3333
Current = Next;

0 commit comments

Comments
 (0)