Enable capture of the top of the stack on error instantiation.

Performance impact on v8 benchmarks seems limited.  Will be backed out
if chrome performance regresses.


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2338 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent da1327e0
...@@ -1206,15 +1206,13 @@ bool Genesis::InstallSpecialObjects() { ...@@ -1206,15 +1206,13 @@ bool Genesis::InstallSpecialObjects() {
Handle<JSObject>(js_global->builtins()), DONT_ENUM); Handle<JSObject>(js_global->builtins()), DONT_ENUM);
} }
if (FLAG_capture_stack_traces) { Handle<Object> Error = GetProperty(js_global, "Error");
Handle<Object> Error = GetProperty(js_global, "Error"); if (Error->IsJSObject()) {
if (Error->IsJSObject()) { Handle<String> name = Factory::LookupAsciiSymbol("stackTraceLimit");
Handle<String> name = Factory::LookupAsciiSymbol("captureStackTraces"); SetProperty(Handle<JSObject>::cast(Error),
SetProperty(Handle<JSObject>::cast(Error), name,
name, Handle<Smi>(Smi::FromInt(FLAG_stack_trace_limit)),
Factory::true_value(), NONE);
NONE);
}
} }
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
......
...@@ -110,7 +110,7 @@ DEFINE_string(expose_natives_as, NULL, "expose natives in global object") ...@@ -110,7 +110,7 @@ DEFINE_string(expose_natives_as, NULL, "expose natives in global object")
DEFINE_string(expose_debug_as, NULL, "expose debug in global object") DEFINE_string(expose_debug_as, NULL, "expose debug in global object")
DEFINE_string(natives_file, NULL, "alternative natives file") DEFINE_string(natives_file, NULL, "alternative natives file")
DEFINE_bool(expose_gc, false, "expose gc extension") DEFINE_bool(expose_gc, false, "expose gc extension")
DEFINE_bool(capture_stack_traces, false, "capture stack traces") DEFINE_int(stack_trace_limit, 10, "number of stack frames to capture")
// builtins-ia32.cc // builtins-ia32.cc
DEFINE_bool(inline_new, true, "use fast inline allocation") DEFINE_bool(inline_new, true, "use fast inline allocation")
......
...@@ -629,10 +629,22 @@ CallSite.prototype.getEvalOrigin = function () { ...@@ -629,10 +629,22 @@ CallSite.prototype.getEvalOrigin = function () {
CallSite.prototype.getFunctionName = function () { CallSite.prototype.getFunctionName = function () {
// See if the function knows its own name // See if the function knows its own name
var name = this.fun.name; var name = this.fun.name;
if (name) if (name) {
return name; return name;
} else {
return %FunctionGetInferredName(this.fun);
}
// Maybe this is an evaluation?
var script = %FunctionGetScript(this.fun);
if (script && script.compilation_type == 1)
return "eval";
return null;
};
CallSite.prototype.getMethodName = function () {
// See if we can find a unique property on the receiver that holds // See if we can find a unique property on the receiver that holds
// this function. // this function.
var name = null;
for (var prop in this.receiver) { for (var prop in this.receiver) {
if (this.receiver[prop] === this.fun) { if (this.receiver[prop] === this.fun) {
// If we find more than one match bail out to avoid confusion // If we find more than one match bail out to avoid confusion
...@@ -643,10 +655,6 @@ CallSite.prototype.getFunctionName = function () { ...@@ -643,10 +655,6 @@ CallSite.prototype.getFunctionName = function () {
} }
if (name) if (name)
return name; return name;
// Maybe this is an evaluation?
var script = %FunctionGetScript(this.fun);
if (script && script.compilation_type == 1)
return "eval";
return null; return null;
}; };
...@@ -717,18 +725,27 @@ function FormatSourcePosition(frame) { ...@@ -717,18 +725,27 @@ function FormatSourcePosition(frame) {
fileLocation = "unknown source"; fileLocation = "unknown source";
} }
var line = ""; var line = "";
var methodName = frame.getMethodName();
var functionName = frame.getFunctionName(); var functionName = frame.getFunctionName();
if (functionName) { var addPrefix = true;
if (frame.isToplevel()) { if (frame.isToplevel()) {
line += functionName; line += functionName;
} else if (frame.isConstructor()) { } else if (frame.isConstructor()) {
line += "new " + functionName; line += "new " + functionName;
} else { } else if (methodName) {
line += frame.getTypeName() + "." + functionName; line += frame.getTypeName() + "." + methodName;
} } else if (functionName) {
line += " (" + fileLocation + ")"; line += functionName;
} else { } else {
line += fileLocation; line += fileLocation;
addPrefix = false;
}
if (addPrefix) {
line += " (";
if (functionName) {
line += functionName + " @ ";
}
line += fileLocation + ")";
} }
return line; return line;
} }
...@@ -812,8 +829,12 @@ function DefineError(f) { ...@@ -812,8 +829,12 @@ function DefineError(f) {
} else if (!IS_UNDEFINED(m)) { } else if (!IS_UNDEFINED(m)) {
this.message = ToString(m); this.message = ToString(m);
} }
if ($Error.captureStackTraces) { var stackTraceLimit = $Error.stackTraceLimit;
var raw_stack = %CollectStackTrace(f); if (stackTraceLimit) {
// Cap the limit to avoid extremely big traces
if (stackTraceLimit < 0 || stackTraceLimit > 10000)
stackTraceLimit = 10000;
var raw_stack = %CollectStackTrace(f, stackTraceLimit);
DefineOneShotAccessor(this, 'stack', function (obj) { DefineOneShotAccessor(this, 'stack', function (obj) {
return FormatRawStackTrace(obj, raw_stack); return FormatRawStackTrace(obj, raw_stack);
}); });
......
...@@ -7420,32 +7420,46 @@ static bool ShowFrameInStackTrace(StackFrame* raw_frame, Object* caller, ...@@ -7420,32 +7420,46 @@ static bool ShowFrameInStackTrace(StackFrame* raw_frame, Object* caller,
// element segments each containing a receiver, function and native // element segments each containing a receiver, function and native
// code offset. // code offset.
static Object* Runtime_CollectStackTrace(Arguments args) { static Object* Runtime_CollectStackTrace(Arguments args) {
ASSERT_EQ(args.length(), 1); ASSERT_EQ(args.length(), 2);
Object* caller = args[0]; Object* caller = args[0];
CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[1]);
HandleScope scope;
int initial_size = limit < 10 ? limit : 10;
Handle<JSArray> result = Factory::NewJSArray(initial_size * 3);
StackFrameIterator iter; StackFrameIterator iter;
int frame_count = 0;
bool seen_caller = false; bool seen_caller = false;
while (!iter.done()) { int cursor = 0;
if (ShowFrameInStackTrace(iter.frame(), caller, &seen_caller)) int frames_seen = 0;
frame_count++; while (!iter.done() && frames_seen < limit) {
iter.Advance();
}
HandleScope scope;
Handle<JSArray> result = Factory::NewJSArray(frame_count * 3);
int i = 0;
seen_caller = false;
for (iter.Reset(); !iter.done(); iter.Advance()) {
StackFrame* raw_frame = iter.frame(); StackFrame* raw_frame = iter.frame();
if (ShowFrameInStackTrace(raw_frame, caller, &seen_caller)) { if (ShowFrameInStackTrace(raw_frame, caller, &seen_caller)) {
frames_seen++;
JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame); JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
result->SetElement(i++, frame->receiver()); Object* recv = frame->receiver();
result->SetElement(i++, frame->function()); Object* fun = frame->function();
Address pc = frame->pc(); Address pc = frame->pc();
Address start = frame->code()->address(); Address start = frame->code()->address();
result->SetElement(i++, Smi::FromInt(pc - start)); Smi* offset = Smi::FromInt(pc - start);
FixedArray* elements = result->elements();
if (cursor + 2 < elements->length()) {
elements->set(cursor++, recv);
elements->set(cursor++, fun);
elements->set(cursor++, offset, SKIP_WRITE_BARRIER);
} else {
HandleScope scope;
SetElement(result, cursor++, Handle<Object>(recv));
SetElement(result, cursor++, Handle<Object>(fun));
SetElement(result, cursor++, Handle<Smi>(offset));
}
} }
iter.Advance();
} }
result->set_length(Smi::FromInt(cursor), SKIP_WRITE_BARRIER);
return *result; return *result;
} }
......
...@@ -172,7 +172,7 @@ namespace internal { ...@@ -172,7 +172,7 @@ namespace internal {
F(FunctionGetPositionForOffset, 2) \ F(FunctionGetPositionForOffset, 2) \
F(FunctionIsAPIFunction, 1) \ F(FunctionIsAPIFunction, 1) \
F(GetScript, 1) \ F(GetScript, 1) \
F(CollectStackTrace, 1) \ F(CollectStackTrace, 2) \
\ \
F(ClassOf, 1) \ F(ClassOf, 1) \
F(SetCode, 2) \ F(SetCode, 2) \
......
...@@ -25,8 +25,6 @@ ...@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Error.captureStackTraces = true;
function testMethodNameInference() { function testMethodNameInference() {
function Foo() { } function Foo() { }
Foo.prototype.bar = function () { FAIL; }; Foo.prototype.bar = function () { FAIL; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment