aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eval.cc24
-rw-r--r--eval.h14
-rw-r--r--expr.cc8
-rw-r--r--func.cc2
-rw-r--r--main.cc3
-rw-r--r--var.cc7
6 files changed, 54 insertions, 4 deletions
diff --git a/eval.cc b/eval.cc
index 3d1a0bb..2206730 100644
--- a/eval.cc
+++ b/eval.cc
@@ -17,6 +17,7 @@
#include "eval.h"
#include <errno.h>
+#include <pthread.h>
#include <string.h>
#include "expr.h"
@@ -37,7 +38,20 @@ Evaluator::Evaluator()
eval_depth_(0),
posix_sym_(Intern(".POSIX")),
is_posix_(false),
- kati_readonly_(Intern(".KATI_READONLY")) {}
+ kati_readonly_(Intern(".KATI_READONLY")) {
+#if defined(__APPLE__)
+ stack_size_ = pthread_get_stacksize_np(pthread_self());
+ stack_addr_ = (char*)pthread_get_stackaddr_np(pthread_self()) - stack_size_;
+#else
+ pthread_attr_t attr;
+ CHECK(pthread_getattr_np(pthread_self(), &attr) == 0);
+ CHECK(pthread_attr_getstack(&attr, &stack_addr_, &stack_size_) == 0);
+ CHECK(pthread_attr_destroy(&attr) == 0);
+#endif
+
+ lowest_stack_ = (char*)stack_addr_ + stack_size_;
+ LOG_STAT("Stack size: %zd bytes", stack_size_);
+}
Evaluator::~Evaluator() {
// delete vars_;
@@ -289,6 +303,8 @@ void Evaluator::EvalIf(const IfStmt* stmt) {
}
void Evaluator::DoInclude(const string& fname) {
+ CheckStack();
+
Makefile* mk = MakefileCacheManager::Get()->ReadMakefile(fname);
if (!mk->Exists()) {
Error(StringPrintf("%s does not exist", fname.c_str()));
@@ -400,4 +416,10 @@ void Evaluator::Error(const string& msg) {
ERROR_LOC(loc_, "%s", msg.c_str());
}
+void Evaluator::DumpStackStats() const {
+ LOG_STAT("Max stack use: %zd bytes at %s:%d",
+ ((char*)stack_addr_ - (char*)lowest_stack_) + stack_size_,
+ LOCF(lowest_loc_));
+}
+
unordered_set<Symbol> Evaluator::used_undefined_vars_;
diff --git a/eval.h b/eval.h
index 97a2c23..2b62892 100644
--- a/eval.h
+++ b/eval.h
@@ -86,6 +86,15 @@ class Evaluator {
string GetShellFlag();
string GetShellAndFlag();
+ void CheckStack() {
+ void* addr = __builtin_frame_address(0);
+ if (__builtin_expect(addr < lowest_stack_ && addr >= stack_addr_, 0)) {
+ lowest_stack_ = addr;
+ lowest_loc_ = loc_;
+ }
+ }
+ void DumpStackStats() const;
+
private:
Var* EvalRHS(Symbol lhs,
Value* rhs,
@@ -119,6 +128,11 @@ class Evaluator {
Symbol posix_sym_;
bool is_posix_;
+ void* stack_addr_;
+ size_t stack_size_;
+ void* lowest_stack_;
+ Loc lowest_loc_;
+
static unordered_set<Symbol> used_undefined_vars_;
Symbol kati_readonly_;
diff --git a/expr.cc b/expr.cc
index f0afb7b..5419900 100644
--- a/expr.cc
+++ b/expr.cc
@@ -52,7 +52,8 @@ class Literal : public Value {
StringPiece val() const { return s_; }
- virtual void Eval(Evaluator*, string* s) const override {
+ virtual void Eval(Evaluator* ev, string* s) const override {
+ ev->CheckStack();
s->append(s_.begin(), s_.end());
}
@@ -79,6 +80,7 @@ class Expr : public Value {
void AddValue(Value* v) { vals_.push_back(v); }
virtual void Eval(Evaluator* ev, string* s) const override {
+ ev->CheckStack();
for (Value* v : vals_) {
v->Eval(ev, s);
}
@@ -119,6 +121,7 @@ class SymRef : public Value {
virtual ~SymRef() {}
virtual void Eval(Evaluator* ev, string* s) const override {
+ ev->CheckStack();
Var* v = ev->LookupVar(name_);
v->Used(ev, name_);
v->Eval(ev, s);
@@ -138,6 +141,7 @@ class VarRef : public Value {
virtual ~VarRef() { delete name_; }
virtual void Eval(Evaluator* ev, string* s) const override {
+ ev->CheckStack();
ev->IncrementEvalDepth();
const string&& name = name_->Eval(ev);
ev->DecrementEvalDepth();
@@ -166,6 +170,7 @@ class VarSubst : public Value {
}
virtual void Eval(Evaluator* ev, string* s) const override {
+ ev->CheckStack();
ev->IncrementEvalDepth();
const string&& name = name_->Eval(ev);
Symbol sym = Intern(name);
@@ -205,6 +210,7 @@ class Func : public Value {
}
virtual void Eval(Evaluator* ev, string* s) const override {
+ ev->CheckStack();
LOG("Invoke func %s(%s)", name(), JoinValues(args_, ",").c_str());
ev->IncrementEvalDepth();
fi_->func(args_, ev, s);
diff --git a/func.cc b/func.cc
index 045c759..220aee0 100644
--- a/func.cc
+++ b/func.cc
@@ -462,6 +462,7 @@ void ValueFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
void EvalFunc(const vector<Value*>& args, Evaluator* ev, string*) {
// TODO: eval leaks everything... for now.
// const string text = args[0]->Eval(ev);
+ ev->CheckStack();
string* text = new string;
args[0]->Eval(ev, text);
if (ev->avoid_io()) {
@@ -595,6 +596,7 @@ void CallFunc(const vector<Value*>& args, Evaluator* ev, string* s) {
Intern("0"), Intern("1"), Intern("2"), Intern("3"), Intern("4"),
Intern("5"), Intern("6"), Intern("7"), Intern("8"), Intern("9")};
+ ev->CheckStack();
const string&& func_name_buf = args[0]->Eval(ev);
const StringPiece func_name = TrimSpace(func_name_buf);
Var* func = ev->LookupVar(Intern(func_name));
diff --git a/main.cc b/main.cc
index d5e0b6e..160468b 100644
--- a/main.cc
+++ b/main.cc
@@ -195,6 +195,7 @@ static int Run(const vector<Symbol>& targets,
if (g_flags.generate_ninja) {
ScopedTimeReporter tr("generate ninja time");
GenerateNinja(nodes, ev, orig_args, start_time);
+ ev->DumpStackStats();
return 0;
}
@@ -216,6 +217,8 @@ static int Run(const vector<Symbol>& targets,
Exec(nodes, ev);
}
+ ev->DumpStackStats();
+
for (Stmt* stmt : bootstrap_asts)
delete stmt;
delete ev;
diff --git a/var.cc b/var.cc
index 27d92c7..14ccee6 100644
--- a/var.cc
+++ b/var.cc
@@ -59,7 +59,8 @@ SimpleVar::SimpleVar(VarOrigin origin) : origin_(origin) {}
SimpleVar::SimpleVar(const string& v, VarOrigin origin)
: v_(v), origin_(origin) {}
-void SimpleVar::Eval(Evaluator*, string* s) const {
+void SimpleVar::Eval(Evaluator* ev, string* s) const {
+ ev->CheckStack();
*s += v_;
}
@@ -82,10 +83,12 @@ RecursiveVar::RecursiveVar(Value* v, VarOrigin origin, StringPiece orig)
: v_(v), origin_(origin), orig_(orig) {}
void RecursiveVar::Eval(Evaluator* ev, string* s) const {
+ ev->CheckStack();
v_->Eval(ev, s);
}
-void RecursiveVar::AppendVar(Evaluator*, Value* v) {
+void RecursiveVar::AppendVar(Evaluator* ev, Value* v) {
+ ev->CheckStack();
v_ = NewExpr3(v_, NewLiteral(" "), v);
}