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() {
Handle<JSObject>(js_global->builtins()), DONT_ENUM);
}
if (FLAG_capture_stack_traces) {
Handle<Object> Error = GetProperty(js_global, "Error");
if (Error->IsJSObject()) {
Handle<String> name = Factory::LookupAsciiSymbol("captureStackTraces");
SetProperty(Handle<JSObject>::cast(Error),
name,
Factory::true_value(),
NONE);
}
Handle<Object> Error = GetProperty(js_global, "Error");
if (Error->IsJSObject()) {
Handle<String> name = Factory::LookupAsciiSymbol("stackTraceLimit");
SetProperty(Handle<JSObject>::cast(Error),
name,
Handle<Smi>(Smi::FromInt(FLAG_stack_trace_limit)),
NONE);
}
#ifdef ENABLE_DEBUGGER_SUPPORT
......
......@@ -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(natives_file, NULL, "alternative natives file")
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
DEFINE_bool(inline_new, true, "use fast inline allocation")
......
......@@ -629,10 +629,22 @@ CallSite.prototype.getEvalOrigin = function () {
CallSite.prototype.getFunctionName = function () {
// See if the function knows its own name
var name = this.fun.name;
if (name)
if (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
// this function.
var name = null;
for (var prop in this.receiver) {
if (this.receiver[prop] === this.fun) {
// If we find more than one match bail out to avoid confusion
......@@ -643,10 +655,6 @@ CallSite.prototype.getFunctionName = function () {
}
if (name)
return name;
// Maybe this is an evaluation?
var script = %FunctionGetScript(this.fun);
if (script && script.compilation_type == 1)
return "eval";
return null;
};
......@@ -717,18 +725,27 @@ function FormatSourcePosition(frame) {
fileLocation = "unknown source";
}
var line = "";
var methodName = frame.getMethodName();
var functionName = frame.getFunctionName();
if (functionName) {
if (frame.isToplevel()) {
line += functionName;
} else if (frame.isConstructor()) {
line += "new " + functionName;
} else {
line += frame.getTypeName() + "." + functionName;
}
line += " (" + fileLocation + ")";
var addPrefix = true;
if (frame.isToplevel()) {
line += functionName;
} else if (frame.isConstructor()) {
line += "new " + functionName;
} else if (methodName) {
line += frame.getTypeName() + "." + methodName;
} else if (functionName) {
line += functionName;
} else {
line += fileLocation;
addPrefix = false;
}
if (addPrefix) {
line += " (";
if (functionName) {
line += functionName + " @ ";
}
line += fileLocation + ")";
}
return line;
}
......@@ -812,8 +829,12 @@ function DefineError(f) {
} else if (!IS_UNDEFINED(m)) {
this.message = ToString(m);
}
if ($Error.captureStackTraces) {
var raw_stack = %CollectStackTrace(f);
var stackTraceLimit = $Error.stackTraceLimit;
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) {
return FormatRawStackTrace(obj, raw_stack);
});
......
......@@ -7420,32 +7420,46 @@ static bool ShowFrameInStackTrace(StackFrame* raw_frame, Object* caller,
// element segments each containing a receiver, function and native
// code offset.
static Object* Runtime_CollectStackTrace(Arguments args) {
ASSERT_EQ(args.length(), 1);
ASSERT_EQ(args.length(), 2);
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;
int frame_count = 0;
bool seen_caller = false;
while (!iter.done()) {
if (ShowFrameInStackTrace(iter.frame(), caller, &seen_caller))
frame_count++;
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()) {
int cursor = 0;
int frames_seen = 0;
while (!iter.done() && frames_seen < limit) {
StackFrame* raw_frame = iter.frame();
if (ShowFrameInStackTrace(raw_frame, caller, &seen_caller)) {
frames_seen++;
JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
result->SetElement(i++, frame->receiver());
result->SetElement(i++, frame->function());
Object* recv = frame->receiver();
Object* fun = frame->function();
Address pc = frame->pc();
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;
}
......
......@@ -172,7 +172,7 @@ namespace internal {
F(FunctionGetPositionForOffset, 2) \
F(FunctionIsAPIFunction, 1) \
F(GetScript, 1) \
F(CollectStackTrace, 1) \
F(CollectStackTrace, 2) \
\
F(ClassOf, 1) \
F(SetCode, 2) \
......
......@@ -25,8 +25,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Error.captureStackTraces = true;
function testMethodNameInference() {
function Foo() { }
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