OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/isolate.h" | 5 #include "src/isolate.h" |
6 | 6 |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 | 8 |
9 #include <fstream> // NOLINT(readability/streams) | 9 #include <fstream> // NOLINT(readability/streams) |
10 #include <sstream> | 10 #include <sstream> |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 // Functions defined in native scripts are not visible unless directly | 331 // Functions defined in native scripts are not visible unless directly |
332 // exposed, in which case the native flag is set. | 332 // exposed, in which case the native flag is set. |
333 // The --builtins-in-stack-traces command line flag allows including | 333 // The --builtins-in-stack-traces command line flag allows including |
334 // internal call sites in the stack trace for debugging purposes. | 334 // internal call sites in the stack trace for debugging purposes. |
335 if (!FLAG_builtins_in_stack_traces && fun->shared()->IsBuiltin()) { | 335 if (!FLAG_builtins_in_stack_traces && fun->shared()->IsBuiltin()) { |
336 return fun->shared()->native(); | 336 return fun->shared()->native(); |
337 } | 337 } |
338 return true; | 338 return true; |
339 } | 339 } |
340 | 340 |
341 static Handle<FixedArray> MaybeGrow(Isolate* isolate, | |
342 Handle<FixedArray> elements, | |
343 int cur_position, int new_size) { | |
344 if (new_size > elements->length()) { | |
345 int new_capacity = JSObject::NewElementsCapacity(elements->length()); | |
346 Handle<FixedArray> new_elements = | |
347 isolate->factory()->NewFixedArrayWithHoles(new_capacity); | |
348 for (int i = 0; i < cur_position; i++) { | |
349 new_elements->set(i, elements->get(i)); | |
350 } | |
351 elements = new_elements; | |
352 } | |
353 DCHECK(new_size <= elements->length()); | |
354 return elements; | |
355 } | |
356 | 341 |
357 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object, | 342 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object, |
358 Handle<Object> caller) { | 343 Handle<Object> caller) { |
359 // Get stack trace limit. | 344 // Get stack trace limit. |
360 Handle<JSObject> error = error_function(); | 345 Handle<JSObject> error = error_function(); |
361 Handle<String> stackTraceLimit = | 346 Handle<String> stackTraceLimit = |
362 factory()->InternalizeUtf8String("stackTraceLimit"); | 347 factory()->InternalizeUtf8String("stackTraceLimit"); |
363 DCHECK(!stackTraceLimit.is_null()); | 348 DCHECK(!stackTraceLimit.is_null()); |
364 Handle<Object> stack_trace_limit = | 349 Handle<Object> stack_trace_limit = |
365 JSReceiver::GetDataProperty(error, stackTraceLimit); | 350 JSReceiver::GetDataProperty(error, stackTraceLimit); |
366 if (!stack_trace_limit->IsNumber()) return factory()->undefined_value(); | 351 if (!stack_trace_limit->IsNumber()) return factory()->undefined_value(); |
367 int limit = FastD2IChecked(stack_trace_limit->Number()); | 352 int limit = FastD2IChecked(stack_trace_limit->Number()); |
368 limit = Max(limit, 0); // Ensure that limit is not negative. | 353 limit = Max(limit, 0); // Ensure that limit is not negative. |
369 | 354 |
370 int initial_size = Min(limit, 10); | 355 int initial_size = Min(limit, 10); |
371 Handle<FixedArray> elements = | 356 Handle<FixedArray> elements = |
372 factory()->NewFixedArrayWithHoles(initial_size * 4 + 1); | 357 factory()->NewFixedArrayWithHoles(initial_size * 4 + 1); |
373 | 358 |
374 // If the caller parameter is a function we skip frames until we're | 359 // If the caller parameter is a function we skip frames until we're |
375 // under it before starting to collect. | 360 // under it before starting to collect. |
376 bool seen_caller = !caller->IsJSFunction(); | 361 bool seen_caller = !caller->IsJSFunction(); |
377 // First element is reserved to store the number of sloppy frames. | 362 // First element is reserved to store the number of sloppy frames. |
378 int cursor = 1; | 363 int cursor = 1; |
379 int frames_seen = 0; | 364 int frames_seen = 0; |
380 int sloppy_frames = 0; | 365 int sloppy_frames = 0; |
381 bool encountered_strict_function = false; | 366 bool encountered_strict_function = false; |
382 for (StackFrameIterator iter(this); !iter.done() && frames_seen < limit; | 367 for (JavaScriptFrameIterator iter(this); |
| 368 !iter.done() && frames_seen < limit; |
383 iter.Advance()) { | 369 iter.Advance()) { |
384 StackFrame* frame = iter.frame(); | 370 JavaScriptFrame* frame = iter.frame(); |
| 371 // Set initial size to the maximum inlining level + 1 for the outermost |
| 372 // function. |
| 373 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); |
| 374 frame->Summarize(&frames); |
| 375 for (int i = frames.length() - 1; i >= 0; i--) { |
| 376 Handle<JSFunction> fun = frames[i].function(); |
| 377 Handle<Object> recv = frames[i].receiver(); |
| 378 // Filter out internal frames that we do not want to show. |
| 379 if (!IsVisibleInStackTrace(*fun, *caller, *recv, &seen_caller)) continue; |
| 380 // Filter out frames from other security contexts. |
| 381 if (!this->context()->HasSameSecurityTokenAs(fun->context())) continue; |
| 382 if (cursor + 4 > elements->length()) { |
| 383 int new_capacity = JSObject::NewElementsCapacity(elements->length()); |
| 384 Handle<FixedArray> new_elements = |
| 385 factory()->NewFixedArrayWithHoles(new_capacity); |
| 386 for (int i = 0; i < cursor; i++) { |
| 387 new_elements->set(i, elements->get(i)); |
| 388 } |
| 389 elements = new_elements; |
| 390 } |
| 391 DCHECK(cursor + 4 <= elements->length()); |
385 | 392 |
386 switch (frame->type()) { | 393 Handle<AbstractCode> abstract_code = frames[i].abstract_code(); |
387 case StackFrame::JAVA_SCRIPT: | |
388 case StackFrame::OPTIMIZED: | |
389 case StackFrame::INTERPRETED: { | |
390 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); | |
391 // Set initial size to the maximum inlining level + 1 for the outermost | |
392 // function. | |
393 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | |
394 js_frame->Summarize(&frames); | |
395 for (int i = frames.length() - 1; i >= 0; i--) { | |
396 Handle<JSFunction> fun = frames[i].function(); | |
397 Handle<Object> recv = frames[i].receiver(); | |
398 // Filter out internal frames that we do not want to show. | |
399 if (!IsVisibleInStackTrace(*fun, *caller, *recv, &seen_caller)) { | |
400 continue; | |
401 } | |
402 // Filter out frames from other security contexts. | |
403 if (!this->context()->HasSameSecurityTokenAs(fun->context())) { | |
404 continue; | |
405 } | |
406 elements = MaybeGrow(this, elements, cursor, cursor + 4); | |
407 | 394 |
408 Handle<AbstractCode> abstract_code = frames[i].abstract_code(); | 395 Handle<Smi> offset(Smi::FromInt(frames[i].code_offset()), this); |
409 | 396 // The stack trace API should not expose receivers and function |
410 Handle<Smi> offset(Smi::FromInt(frames[i].code_offset()), this); | 397 // objects on frames deeper than the top-most one with a strict |
411 // The stack trace API should not expose receivers and function | 398 // mode function. The number of sloppy frames is stored as |
412 // objects on frames deeper than the top-most one with a strict mode | 399 // first element in the result array. |
413 // function. The number of sloppy frames is stored as first element in | 400 if (!encountered_strict_function) { |
414 // the result array. | 401 if (is_strict(fun->shared()->language_mode())) { |
415 if (!encountered_strict_function) { | 402 encountered_strict_function = true; |
416 if (is_strict(fun->shared()->language_mode())) { | 403 } else { |
417 encountered_strict_function = true; | 404 sloppy_frames++; |
418 } else { | |
419 sloppy_frames++; | |
420 } | |
421 } | |
422 elements->set(cursor++, *recv); | |
423 elements->set(cursor++, *fun); | |
424 elements->set(cursor++, *abstract_code); | |
425 elements->set(cursor++, *offset); | |
426 frames_seen++; | |
427 } | 405 } |
428 } break; | 406 } |
429 | 407 elements->set(cursor++, *recv); |
430 case StackFrame::WASM: { | 408 elements->set(cursor++, *fun); |
431 elements = MaybeGrow(this, elements, cursor, cursor + 4); | 409 elements->set(cursor++, *abstract_code); |
432 // TODO(jfb) Pass module object. | 410 elements->set(cursor++, *offset); |
433 elements->set(cursor++, *factory()->undefined_value()); | 411 frames_seen++; |
434 elements->set(cursor++, | |
435 *factory()->NewFunction( | |
436 factory()->NewStringFromAsciiChecked("<WASM>"))); | |
437 elements->set(cursor++, Internals::IntToSmi(0)); | |
438 elements->set(cursor++, Internals::IntToSmi(0)); | |
439 frames_seen++; | |
440 } break; | |
441 | |
442 default: | |
443 break; | |
444 } | 412 } |
445 } | 413 } |
446 elements->set(0, Smi::FromInt(sloppy_frames)); | 414 elements->set(0, Smi::FromInt(sloppy_frames)); |
447 elements->Shrink(cursor); | 415 elements->Shrink(cursor); |
448 Handle<JSArray> result = factory()->NewJSArrayWithElements(elements); | 416 Handle<JSArray> result = factory()->NewJSArrayWithElements(elements); |
449 result->set_length(Smi::FromInt(cursor)); | 417 result->set_length(Smi::FromInt(cursor)); |
450 // TODO(yangguo): Queue this structured stack trace for preprocessing on GC. | 418 // TODO(yangguo): Queue this structured stack trace for preprocessing on GC. |
451 return result; | 419 return result; |
452 } | 420 } |
453 | 421 |
| 422 |
454 MaybeHandle<JSObject> Isolate::CaptureAndSetDetailedStackTrace( | 423 MaybeHandle<JSObject> Isolate::CaptureAndSetDetailedStackTrace( |
455 Handle<JSObject> error_object) { | 424 Handle<JSObject> error_object) { |
456 if (capture_stack_trace_for_uncaught_exceptions_) { | 425 if (capture_stack_trace_for_uncaught_exceptions_) { |
457 // Capture stack trace for a detailed exception message. | 426 // Capture stack trace for a detailed exception message. |
458 Handle<Name> key = factory()->detailed_stack_trace_symbol(); | 427 Handle<Name> key = factory()->detailed_stack_trace_symbol(); |
459 Handle<JSArray> stack_trace = CaptureCurrentStackTrace( | 428 Handle<JSArray> stack_trace = CaptureCurrentStackTrace( |
460 stack_trace_for_uncaught_exceptions_frame_limit_, | 429 stack_trace_for_uncaught_exceptions_frame_limit_, |
461 stack_trace_for_uncaught_exceptions_options_); | 430 stack_trace_for_uncaught_exceptions_options_); |
462 RETURN_ON_EXCEPTION( | 431 RETURN_ON_EXCEPTION( |
463 this, JSObject::SetProperty(error_object, key, stack_trace, STRICT), | 432 this, JSObject::SetProperty(error_object, key, stack_trace, STRICT), |
(...skipping 2424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2888 // Then check whether this scope intercepts. | 2857 // Then check whether this scope intercepts. |
2889 if ((flag & intercept_mask_)) { | 2858 if ((flag & intercept_mask_)) { |
2890 intercepted_flags_ |= flag; | 2859 intercepted_flags_ |= flag; |
2891 return true; | 2860 return true; |
2892 } | 2861 } |
2893 return false; | 2862 return false; |
2894 } | 2863 } |
2895 | 2864 |
2896 } // namespace internal | 2865 } // namespace internal |
2897 } // namespace v8 | 2866 } // namespace v8 |
OLD | NEW |