| 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 |