aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Willemsen <dwillemsen@google.com>2017-10-09 11:23:32 -0700
committerDan Willemsen <dwillemsen@google.com>2017-10-13 13:21:27 -0700
commit36e5729db554afaea6fe9b23f3caa87b6c8cc80d (patch)
tree482b20ea2fcb0a6d5d112af75623eb690c12f9cb
parentf2a0a72d1fd1ee7b6f37754eef8886dcaafa22d0 (diff)
downloadandroid_build_kati-36e5729db554afaea6fe9b23f3caa87b6c8cc80d.tar.gz
android_build_kati-36e5729db554afaea6fe9b23f3caa87b6c8cc80d.tar.bz2
android_build_kati-36e5729db554afaea6fe9b23f3caa87b6c8cc80d.zip
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.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);
}