Author: [email protected]
Date: Thu Jul 2 05:26:31 2009
New Revision: 2338
Modified:
branches/bleeding_edge/src/bootstrapper.cc
branches/bleeding_edge/src/flag-definitions.h
branches/bleeding_edge/src/messages.js
branches/bleeding_edge/src/runtime.cc
branches/bleeding_edge/src/runtime.h
branches/bleeding_edge/test/mjsunit/stack-traces.js
Log:
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.
Modified: branches/bleeding_edge/src/bootstrapper.cc
==============================================================================
--- branches/bleeding_edge/src/bootstrapper.cc (original)
+++ branches/bleeding_edge/src/bootstrapper.cc Thu Jul 2 05:26:31 2009
@@ -1206,15 +1206,13 @@
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
Modified: branches/bleeding_edge/src/flag-definitions.h
==============================================================================
--- branches/bleeding_edge/src/flag-definitions.h (original)
+++ branches/bleeding_edge/src/flag-definitions.h Thu Jul 2 05:26:31 2009
@@ -110,7 +110,7 @@
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")
Modified: branches/bleeding_edge/src/messages.js
==============================================================================
--- branches/bleeding_edge/src/messages.js (original)
+++ branches/bleeding_edge/src/messages.js Thu Jul 2 05:26:31 2009
@@ -629,10 +629,22 @@
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 @@
}
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 @@
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 @@
} 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);
});
Modified: branches/bleeding_edge/src/runtime.cc
==============================================================================
--- branches/bleeding_edge/src/runtime.cc (original)
+++ branches/bleeding_edge/src/runtime.cc Thu Jul 2 05:26:31 2009
@@ -7420,32 +7420,46 @@
// 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;
}
Modified: branches/bleeding_edge/src/runtime.h
==============================================================================
--- branches/bleeding_edge/src/runtime.h (original)
+++ branches/bleeding_edge/src/runtime.h Thu Jul 2 05:26:31 2009
@@ -172,7 +172,7 @@
F(FunctionGetPositionForOffset, 2) \
F(FunctionIsAPIFunction, 1) \
F(GetScript, 1) \
- F(CollectStackTrace, 1) \
+ F(CollectStackTrace, 2) \
\
F(ClassOf, 1) \
F(SetCode, 2) \
Modified: branches/bleeding_edge/test/mjsunit/stack-traces.js
==============================================================================
--- branches/bleeding_edge/test/mjsunit/stack-traces.js (original)
+++ branches/bleeding_edge/test/mjsunit/stack-traces.js Thu Jul 2 05:26:31
2009
@@ -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; };
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---