Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Unified Diff: runtime/vm/exceptions.cc

Issue 12335111: Resubmit change 19074. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/tests/vm/vm.status ('k') | runtime/vm/object.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/exceptions.cc
===================================================================
--- runtime/vm/exceptions.cc (revision 19094)
+++ runtime/vm/exceptions.cc (working copy)
@@ -26,6 +26,106 @@
const char* Exceptions::kCastErrorDstName = "type cast";
+class StacktraceBuilder : public ValueObject {
+ public:
+ StacktraceBuilder() { }
+ virtual ~StacktraceBuilder() { }
+
+ virtual void AddFrame(const Function& func,
+ const Code& code,
+ const Smi& offset) = 0;
+};
+
+
+class RegularStacktraceBuilder : public StacktraceBuilder {
+ public:
+ RegularStacktraceBuilder()
+ : func_list_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
+ code_list_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
+ pc_offset_list_(
+ GrowableObjectArray::Handle(GrowableObjectArray::New())) { }
+ ~RegularStacktraceBuilder() { }
+
+ const GrowableObjectArray& func_list() const { return func_list_; }
+ const GrowableObjectArray& code_list() const { return code_list_; }
+ const GrowableObjectArray& pc_offset_list() const { return pc_offset_list_; }
+
+ virtual void AddFrame(const Function& func,
+ const Code& code,
+ const Smi& offset) {
+ func_list_.Add(func);
+ code_list_.Add(code);
+ pc_offset_list_.Add(offset);
+ }
+
+ private:
+ const GrowableObjectArray& func_list_;
+ const GrowableObjectArray& code_list_;
+ const GrowableObjectArray& pc_offset_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(RegularStacktraceBuilder);
+};
+
+
+class PreallocatedStacktraceBuilder : public StacktraceBuilder {
+ public:
+ explicit PreallocatedStacktraceBuilder(const Stacktrace& stacktrace)
+ : stacktrace_(stacktrace),
+ cur_index_(0) {
+ ASSERT(stacktrace_.raw() ==
+ Isolate::Current()->object_store()->preallocated_stack_trace());
+ }
+ ~PreallocatedStacktraceBuilder() { }
+
+ virtual void AddFrame(const Function& func,
+ const Code& code,
+ const Smi& offset);
+
+ private:
+ static const int kNumTopframes = 3;
+
+ const Stacktrace& stacktrace_;
+ intptr_t cur_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(PreallocatedStacktraceBuilder);
+};
+
+
+void PreallocatedStacktraceBuilder::AddFrame(const Function& func,
+ const Code& code,
+ const Smi& offset) {
+ if (cur_index_ >= Stacktrace::kPreallocatedStackdepth) {
+ // The number of frames is overflowing the preallocated stack trace object.
+ Function& frame_func = Function::Handle();
+ Code& frame_code = Code::Handle();
+ Smi& frame_offset = Smi::Handle();
+ intptr_t start = Stacktrace::kPreallocatedStackdepth - (kNumTopframes - 1);
+ intptr_t null_slot = start - 2;
+ // Add an empty slot to indicate the overflow so that the toString
+ // method can account for the overflow.
+ if (stacktrace_.FunctionAtFrame(null_slot) != Function::null()) {
+ stacktrace_.SetFunctionAtFrame(null_slot, frame_func);
+ stacktrace_.SetCodeAtFrame(null_slot, frame_code);
+ }
+ // Move frames one slot down so that we can accomadate the new frame.
+ for (intptr_t i = start; i < Stacktrace::kPreallocatedStackdepth; i++) {
+ intptr_t prev = (i - 1);
+ frame_func = stacktrace_.FunctionAtFrame(i);
+ frame_code = stacktrace_.CodeAtFrame(i);
+ frame_offset = stacktrace_.PcOffsetAtFrame(i);
+ stacktrace_.SetFunctionAtFrame(prev, frame_func);
+ stacktrace_.SetCodeAtFrame(prev, frame_code);
+ stacktrace_.SetPcOffsetAtFrame(prev, frame_offset);
+ }
+ cur_index_ = (Stacktrace::kPreallocatedStackdepth - 1);
+ }
+ stacktrace_.SetFunctionAtFrame(cur_index_, func);
+ stacktrace_.SetCodeAtFrame(cur_index_, code);
+ stacktrace_.SetPcOffsetAtFrame(cur_index_, offset);
+ cur_index_ += 1;
+}
+
+
static bool ShouldShowFunction(const Function& function) {
if (FLAG_verbose_stacktrace) {
return true;
@@ -40,9 +140,7 @@
static bool FindExceptionHandler(uword* handler_pc,
uword* handler_sp,
uword* handler_fp,
- const GrowableObjectArray& func_list,
- const GrowableObjectArray& code_list,
- const GrowableObjectArray& pc_offset_list) {
+ StacktraceBuilder* builder) {
StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
StackFrame* frame = frames.NextFrame();
ASSERT(frame != NULL); // We expect to find a dart invocation frame.
@@ -64,18 +162,14 @@
ASSERT(pc < (code.EntryPoint() + code.Size()));
if (ShouldShowFunction(func)) {
offset = Smi::New(pc - code.EntryPoint());
- func_list.Add(func);
- code_list.Add(code);
- pc_offset_list.Add(offset);
+ builder->AddFrame(func, code, offset);
}
}
} else {
offset = Smi::New(frame->pc() - code.EntryPoint());
func = code.function();
if (ShouldShowFunction(func)) {
- func_list.Add(func);
- code_list.Add(code);
- pc_offset_list.Add(offset);
+ builder->AddFrame(func, code, offset);
}
}
if (frame->FindExceptionHandler(handler_pc)) {
@@ -171,46 +265,62 @@
static void ThrowExceptionHelper(const Instance& incoming_exception,
const Instance& existing_stacktrace) {
- Instance& exception = Instance::Handle(incoming_exception.raw());
+ bool use_preallocated_stacktrace = false;
+ Isolate* isolate = Isolate::Current();
+ Instance& exception = Instance::Handle(isolate, incoming_exception.raw());
if (exception.IsNull()) {
exception ^= Exceptions::Create(Exceptions::kNullThrown,
Object::empty_array());
+ } else if (exception.raw() == isolate->object_store()->out_of_memory() ||
+ exception.raw() == isolate->object_store()->stack_overflow()) {
+ use_preallocated_stacktrace = true;
}
uword handler_pc = 0;
uword handler_sp = 0;
uword handler_fp = 0;
- const GrowableObjectArray& func_list =
- GrowableObjectArray::Handle(GrowableObjectArray::New());
- const GrowableObjectArray& code_list =
- GrowableObjectArray::Handle(GrowableObjectArray::New());
- const GrowableObjectArray& pc_offset_list =
- GrowableObjectArray::Handle(GrowableObjectArray::New());
- bool handler_exists = FindExceptionHandler(&handler_pc,
- &handler_sp,
- &handler_fp,
- func_list,
- code_list,
- pc_offset_list);
+ Stacktrace& stacktrace = Stacktrace::Handle(isolate);
+ bool handler_exists = false;
+ if (use_preallocated_stacktrace) {
+ stacktrace ^= isolate->object_store()->preallocated_stack_trace();
+ PreallocatedStacktraceBuilder frame_builder(stacktrace);
+ handler_exists = FindExceptionHandler(&handler_pc,
+ &handler_sp,
+ &handler_fp,
+ &frame_builder);
+ } else {
+ RegularStacktraceBuilder frame_builder;
+ handler_exists = FindExceptionHandler(&handler_pc,
+ &handler_sp,
+ &handler_fp,
+ &frame_builder);
+ // TODO(5411263): At some point we can optimize by figuring out if a
+ // stack trace is needed based on whether the catch code specifies a
+ // stack trace object or there is a rethrow in the catch clause.
+ if (frame_builder.pc_offset_list().Length() != 0) {
+ // Create arrays for function, code and pc_offset triplet for each frame.
+ const Array& func_array =
+ Array::Handle(isolate, Array::MakeArray(frame_builder.func_list()));
+ const Array& code_array =
+ Array::Handle(isolate, Array::MakeArray(frame_builder.code_list()));
+ const Array& pc_offset_array =
+ Array::Handle(isolate,
+ Array::MakeArray(frame_builder.pc_offset_list()));
+ if (existing_stacktrace.IsNull()) {
+ stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array);
+ } else {
+ stacktrace ^= existing_stacktrace.raw();
+ stacktrace.Append(func_array, code_array, pc_offset_array);
+ }
+ } else {
+ stacktrace ^= existing_stacktrace.raw();
+ }
+ }
// We expect to find a handler_pc, if the exception is unhandled
// then we expect to at least have the dart entry frame on the
// stack as Exceptions::Throw should happen only after a dart
// invocation has been done.
ASSERT(handler_pc != 0);
- // TODO(5411263): At some point we can optimize by figuring out if a
- // stack trace is needed based on whether the catch code specifies a
- // stack trace object or there is a rethrow in the catch clause.
- Stacktrace& stacktrace = Stacktrace::Handle();
- if (pc_offset_list.Length() != 0) {
- if (existing_stacktrace.IsNull()) {
- stacktrace = Stacktrace::New(func_list, code_list, pc_offset_list);
- } else {
- stacktrace ^= existing_stacktrace.raw();
- stacktrace.Append(func_list, code_list, pc_offset_list);
- }
- } else {
- stacktrace ^= existing_stacktrace.raw();
- }
if (FLAG_print_stacktrace_at_throw) {
OS::Print("Exception '%s' thrown:\n", exception.ToCString());
OS::Print("%s\n", stacktrace.ToCString());
@@ -224,7 +334,6 @@
stacktrace);
} else {
if (FLAG_heap_profile_out_of_memory) {
- Isolate* isolate = Isolate::Current();
if (exception.raw() == isolate->object_store()->out_of_memory()) {
isolate->heap()->ProfileToFile("out-of-memory");
}
« no previous file with comments | « runtime/tests/vm/vm.status ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698