diff options
author | Dan Willemsen <dwillemsen@google.com> | 2017-10-09 11:23:32 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@google.com> | 2017-10-13 13:21:27 -0700 |
commit | 36e5729db554afaea6fe9b23f3caa87b6c8cc80d (patch) | |
tree | 482b20ea2fcb0a6d5d112af75623eb690c12f9cb | |
parent | f2a0a72d1fd1ee7b6f37754eef8886dcaafa22d0 (diff) | |
download | kati-36e5729db554afaea6fe9b23f3caa87b6c8cc80d.tar.gz |
Keep track of stack usage, report line that used the most
This won't keep track of everything, but was useful in tracking down
some recursive variables in the android build that shouldn't have been
recursive (they were using 1MB+ of stack).
Change-Id: I5e6b70480cffbebb09dfd72276017559480da948
-rw-r--r-- | eval.cc | 24 | ||||
-rw-r--r-- | eval.h | 14 | ||||
-rw-r--r-- | expr.cc | 8 | ||||
-rw-r--r-- | func.cc | 2 | ||||
-rw-r--r-- | main.cc | 3 | ||||
-rw-r--r-- | var.cc | 7 |
6 files changed, 54 insertions, 4 deletions
@@ -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_; @@ -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_; @@ -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); @@ -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)); @@ -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; @@ -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); } |