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

Side by Side Diff: runtime/vm/exceptions.cc

Issue 23445012: Mark exception handlers if they have a stacktrace specified. Do not build a stacktrace if the handl… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 3 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/exceptions.h" 5 #include "vm/exceptions.h"
6 6
7 #include "vm/dart_api_impl.h" 7 #include "vm/dart_api_impl.h"
8 #include "vm/dart_entry.h" 8 #include "vm/dart_entry.h"
9 #include "vm/debugger.h" 9 #include "vm/debugger.h"
10 #include "vm/flags.h" 10 #include "vm/flags.h"
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 181
182 182
183 static bool ShouldShowFunction(const Function& function) { 183 static bool ShouldShowFunction(const Function& function) {
184 if (FLAG_verbose_stacktrace) { 184 if (FLAG_verbose_stacktrace) {
185 return true; 185 return true;
186 } 186 }
187 return function.is_visible(); 187 return function.is_visible();
188 } 188 }
189 189
190 190
191 // Iterate through the stack frames and try to find a frame with an 191 static void BuildStackTrace(StacktraceBuilder* builder) {
192 // exception handler. Once found, set the pc, sp and fp so that execution
193 // can continue in that frame.
194 static bool FindExceptionHandler(uword* handler_pc,
195 uword* handler_sp,
196 uword* handler_fp,
197 StacktraceBuilder* builder) {
198 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); 192 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
199 StackFrame* frame = frames.NextFrame(); 193 StackFrame* frame = frames.NextFrame();
200 ASSERT(frame != NULL); // We expect to find a dart invocation frame. 194 ASSERT(frame != NULL); // We expect to find a dart invocation frame.
201 Function& func = Function::Handle(); 195 Function& func = Function::Handle();
202 Code& code = Code::Handle(); 196 Code& code = Code::Handle();
203 Smi& offset = Smi::Handle(); 197 Smi& offset = Smi::Handle();
198 uword handler_pc = NULL;
hausner 2013/08/28 16:08:20 Should a uword variable not be initialized with 0?
siva 2013/08/28 17:00:09 Maybe intialize it to kUwordMax.
srdjan 2013/08/28 20:38:29 Initialized to kUWordMax and moved close to frame-
srdjan 2013/08/28 20:38:29 Using kUWordMax
204 bool dart_handler_found = false; 199 bool dart_handler_found = false;
205 bool handler_pc_set = false; 200 bool handler_pc_set = false;
siva 2013/08/28 17:00:09 The variable dart_handler_found is not needed anym
srdjan 2013/08/28 20:38:29 Offline discussion: it is needed to note the catch
206 while (frame != NULL) { 201 while (frame != NULL) {
207 while (!frame->IsEntryFrame()) { 202 while (!frame->IsEntryFrame()) {
208 if (frame->IsDartFrame()) { 203 if (frame->IsDartFrame()) {
209 code = frame->LookupDartCode(); 204 code = frame->LookupDartCode();
210 if (code.is_optimized()) { 205 if (code.is_optimized()) {
211 // For optimized frames, extract all the inlined functions if any 206 // For optimized frames, extract all the inlined functions if any
212 // into the stack trace. 207 // into the stack trace.
213 for (InlinedFunctionsIterator it(frame); !it.Done(); it.Advance()) { 208 for (InlinedFunctionsIterator it(frame); !it.Done(); it.Advance()) {
214 func = it.function(); 209 func = it.function();
215 code = it.code(); 210 code = it.code();
216 uword pc = it.pc(); 211 uword pc = it.pc();
217 ASSERT(pc != 0); 212 ASSERT(pc != 0);
218 ASSERT(code.EntryPoint() <= pc); 213 ASSERT(code.EntryPoint() <= pc);
219 ASSERT(pc < (code.EntryPoint() + code.Size())); 214 ASSERT(pc < (code.EntryPoint() + code.Size()));
220 if (ShouldShowFunction(func)) { 215 if (ShouldShowFunction(func)) {
221 offset = Smi::New(pc - code.EntryPoint()); 216 offset = Smi::New(pc - code.EntryPoint());
222 builder->AddFrame(func, code, offset, dart_handler_found); 217 builder->AddFrame(func, code, offset, dart_handler_found);
223 } 218 }
224 } 219 }
225 } else { 220 } else {
226 offset = Smi::New(frame->pc() - code.EntryPoint()); 221 offset = Smi::New(frame->pc() - code.EntryPoint());
227 func = code.function(); 222 func = code.function();
228 if (ShouldShowFunction(func)) { 223 if (ShouldShowFunction(func)) {
229 builder->AddFrame(func, code, offset, dart_handler_found); 224 builder->AddFrame(func, code, offset, dart_handler_found);
230 } 225 }
231 } 226 }
232 if (!handler_pc_set && frame->FindExceptionHandler(handler_pc)) { 227 bool needs_stacktrace = false;
228 if (!handler_pc_set &&
229 frame->FindExceptionHandler(&handler_pc, &needs_stacktrace)) {
233 handler_pc_set = true; 230 handler_pc_set = true;
234 *handler_sp = frame->sp();
235 *handler_fp = frame->fp();
236 dart_handler_found = true; 231 dart_handler_found = true;
237 if (!builder->FullStacktrace()) { 232 if (!builder->FullStacktrace()) {
238 return dart_handler_found; 233 return;
239 } 234 }
240 } 235 }
241 } 236 }
242 frame = frames.NextFrame(); 237 frame = frames.NextFrame();
243 ASSERT(frame != NULL); 238 ASSERT(frame != NULL);
244 } 239 }
245 ASSERT(frame->IsEntryFrame()); 240 ASSERT(frame->IsEntryFrame());
246 if (!handler_pc_set) { 241 if (!handler_pc_set) {
247 handler_pc_set = true; 242 handler_pc_set = true;
243 handler_pc = frame->pc();
244 if (!builder->FullStacktrace()) {
245 return;
246 }
247 }
248 frame = frames.NextFrame();
249 }
250 }
251
252
253 // Iterate through the stack frames and try to find a frame with an
254 // exception handler. Once found, set the pc, sp and fp so that execution
255 // can continue in that frame.
256 static bool FindExceptionHandler(uword* handler_pc,
257 uword* handler_sp,
258 uword* handler_fp,
259 bool* handler_needs_stacktrace) {
260 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
261 StackFrame* frame = frames.NextFrame();
262 ASSERT(frame != NULL); // We expect to find a dart invocation frame.
263 bool handler_pc_set = false;
264 *handler_needs_stacktrace = false;
265 while (frame != NULL) {
266 while (!frame->IsEntryFrame()) {
267 if (frame->IsDartFrame()) {
268 if (!handler_pc_set &&
269 frame->FindExceptionHandler(handler_pc, handler_needs_stacktrace)) {
270 handler_pc_set = true;
271 *handler_sp = frame->sp();
272 *handler_fp = frame->fp();
273 return true;
siva 2013/08/28 17:00:09 Don't you have to keep going till you hit the entr
srdjan 2013/08/28 20:38:29 Good 'catch'!
274 }
275 }
276 frame = frames.NextFrame();
277 ASSERT(frame != NULL);
278 } // while !frame->IsEntryFrame.
279 ASSERT(frame->IsEntryFrame());
280 if (!handler_pc_set) {
281 handler_pc_set = true;
248 *handler_pc = frame->pc(); 282 *handler_pc = frame->pc();
249 *handler_sp = frame->sp(); 283 *handler_sp = frame->sp();
250 *handler_fp = frame->fp(); 284 *handler_fp = frame->fp();
251 if (!builder->FullStacktrace()) { 285 *handler_needs_stacktrace = true;
252 return dart_handler_found;
253 }
254 } 286 }
255 frame = frames.NextFrame(); 287 frame = frames.NextFrame();
256 } 288 } // while frame != NULL.
257 return dart_handler_found; 289 return false;
siva 2013/08/28 17:00:09 Since you are not building a full stack trace anym
srdjan 2013/08/28 20:38:29 Done.
258 } 290 }
259 291
260 292
261 static void FindErrorHandler(uword* handler_pc, 293 static void FindErrorHandler(uword* handler_pc,
262 uword* handler_sp, 294 uword* handler_sp,
263 uword* handler_fp) { 295 uword* handler_fp) {
264 // TODO(turnidge): Is there a faster way to get the next entry frame? 296 // TODO(turnidge): Is there a faster way to get the next entry frame?
265 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); 297 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
266 StackFrame* frame = frames.NextFrame(); 298 StackFrame* frame = frames.NextFrame();
267 ASSERT(frame != NULL); 299 ASSERT(frame != NULL);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 Object::empty_array()); 389 Object::empty_array());
358 } else if (exception.raw() == isolate->object_store()->out_of_memory() || 390 } else if (exception.raw() == isolate->object_store()->out_of_memory() ||
359 exception.raw() == isolate->object_store()->stack_overflow()) { 391 exception.raw() == isolate->object_store()->stack_overflow()) {
360 use_preallocated_stacktrace = true; 392 use_preallocated_stacktrace = true;
361 } 393 }
362 uword handler_pc = 0; 394 uword handler_pc = 0;
363 uword handler_sp = 0; 395 uword handler_sp = 0;
364 uword handler_fp = 0; 396 uword handler_fp = 0;
365 Stacktrace& stacktrace = Stacktrace::Handle(isolate); 397 Stacktrace& stacktrace = Stacktrace::Handle(isolate);
366 bool handler_exists = false; 398 bool handler_exists = false;
399 bool handler_needs_stacktrace = false;
367 if (use_preallocated_stacktrace) { 400 if (use_preallocated_stacktrace) {
368 stacktrace ^= isolate->object_store()->preallocated_stack_trace(); 401 stacktrace ^= isolate->object_store()->preallocated_stack_trace();
369 PreallocatedStacktraceBuilder frame_builder(stacktrace); 402 PreallocatedStacktraceBuilder frame_builder(stacktrace);
370 handler_exists = FindExceptionHandler(&handler_pc, 403 handler_exists = FindExceptionHandler(&handler_pc,
371 &handler_sp, 404 &handler_sp,
372 &handler_fp, 405 &handler_fp,
373 &frame_builder); 406 &handler_needs_stacktrace);
407 if (handler_needs_stacktrace) {
408 BuildStackTrace(&frame_builder);
409 }
374 } else { 410 } else {
411 // Get stacktrace field of class Error.
375 const Field& stacktrace_field = 412 const Field& stacktrace_field =
376 Field::Handle(LookupStacktraceField(exception)); 413 Field::Handle(isolate, LookupStacktraceField(exception));
377 bool full_stacktrace = !stacktrace_field.IsNull(); 414 bool full_stacktrace = !stacktrace_field.IsNull();
378 RegularStacktraceBuilder frame_builder(full_stacktrace);
379 handler_exists = FindExceptionHandler(&handler_pc, 415 handler_exists = FindExceptionHandler(&handler_pc,
380 &handler_sp, 416 &handler_sp,
381 &handler_fp, 417 &handler_fp,
382 &frame_builder); 418 &handler_needs_stacktrace);
383 // Create arrays for function, code and pc_offset triplet of each frame. 419 Array& func_array = Array::Handle(isolate, Object::empty_array().raw());
384 const Array& func_array = 420 Array& code_array = Array::Handle(isolate, Object::empty_array().raw());
385 Array::Handle(isolate, Array::MakeArray(frame_builder.func_list())); 421 Array& pc_offset_array =
386 const Array& code_array = 422 Array::Handle(isolate, Object::empty_array().raw());
387 Array::Handle(isolate, Array::MakeArray(frame_builder.code_list())); 423 if (handler_needs_stacktrace || full_stacktrace) {
388 const Array& pc_offset_array = 424 RegularStacktraceBuilder frame_builder(full_stacktrace);
389 Array::Handle(isolate, 425 BuildStackTrace(&frame_builder);
390 Array::MakeArray(frame_builder.pc_offset_list())); 426
391 if (!stacktrace_field.IsNull()) { 427 // Create arrays for function, code and pc_offset triplet of each frame.
392 // This is an error object and we need to capture the full stack trace 428 func_array = Array::MakeArray(frame_builder.func_list());
393 // here implicitly, so we set up the stack trace. The stack trace field 429 code_array = Array::MakeArray(frame_builder.code_list());
394 // is set only once, it is not overriden. 430 pc_offset_array = Array::MakeArray(frame_builder.pc_offset_list());
395 const Array& catch_func_array = 431 if (!stacktrace_field.IsNull()) {
396 Array::Handle(isolate, 432 // This is an error object and we need to capture the full stack trace
397 Array::MakeArray(frame_builder.catch_func_list())); 433 // here implicitly, so we set up the stack trace. The stack trace field
398 const Array& catch_code_array = 434 // is set only once, it is not overriden.
399 Array::Handle(isolate, 435 const Array& catch_func_array = Array::Handle(isolate,
400 Array::MakeArray(frame_builder.catch_code_list())); 436 Array::MakeArray(frame_builder.catch_func_list()));
401 const Array& catch_pc_offset_array = 437 const Array& catch_code_array = Array::Handle(isolate,
402 Array::Handle(isolate, 438 Array::MakeArray(frame_builder.catch_code_list()));
403 Array::MakeArray(frame_builder.catch_pc_offset_list())); 439 const Array& catch_pc_offset_array = Array::Handle(isolate,
440 Array::MakeArray(frame_builder.catch_pc_offset_list()));
441 stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array);
442 stacktrace.SetCatchStacktrace(catch_func_array,
443 catch_code_array,
444 catch_pc_offset_array);
445 if (exception.GetField(stacktrace_field) == Object::null()) {
446 exception.SetField(stacktrace_field, stacktrace);
447 }
448 } // if stacktrace needed.
449 }
450 if (existing_stacktrace.IsNull()) {
404 stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array); 451 stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array);
405 stacktrace.SetCatchStacktrace(catch_func_array,
406 catch_code_array,
407 catch_pc_offset_array);
408 if (exception.GetField(stacktrace_field) == Object::null()) {
409 exception.SetField(stacktrace_field, stacktrace);
410 }
411 }
412 // TODO(5411263): At some point we can optimize by figuring out if a
413 // stack trace is needed based on whether the catch code specifies a
414 // stack trace object or there is a rethrow in the catch clause.
415 if (existing_stacktrace.IsNull()) {
416 stacktrace = Stacktrace::New(func_array, code_array, pc_offset_array);
417 } else { 452 } else {
418 stacktrace ^= existing_stacktrace.raw(); 453 stacktrace ^= existing_stacktrace.raw();
419 if (pc_offset_array.Length() != 0) { 454 if (pc_offset_array.Length() != 0) {
420 stacktrace.Append(func_array, code_array, pc_offset_array); 455 stacktrace.Append(func_array, code_array, pc_offset_array);
421 } 456 }
422 // Since we are re throwing and appending to the existing stack trace 457 // Since we are re throwing and appending to the existing stack trace
423 // we clear out the catch trace collected in the existing stack trace 458 // we clear out the catch trace collected in the existing stack trace
424 // as that trace will not be valid anymore. 459 // as that trace will not be valid anymore.
425 stacktrace.SetCatchStacktrace(Object::empty_array(), 460 stacktrace.SetCatchStacktrace(Object::empty_array(),
426 Object::empty_array(), 461 Object::empty_array(),
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 break; 737 break;
703 } 738 }
704 739
705 return DartLibraryCalls::InstanceCreate(library, 740 return DartLibraryCalls::InstanceCreate(library,
706 *class_name, 741 *class_name,
707 *constructor_name, 742 *constructor_name,
708 arguments); 743 arguments);
709 } 744 }
710 745
711 } // namespace dart 746 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698