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 <stdlib.h> | 5 #include <stdlib.h> |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #include "src/ast.h" | 9 #include "src/ast.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 base::OS::Abort(); | 318 base::OS::Abort(); |
319 } | 319 } |
320 | 320 |
321 | 321 |
322 // Determines whether the given stack frame should be displayed in | 322 // Determines whether the given stack frame should be displayed in |
323 // a stack trace. The caller is the error constructor that asked | 323 // a stack trace. The caller is the error constructor that asked |
324 // for the stack trace to be collected. The first time a construct | 324 // for the stack trace to be collected. The first time a construct |
325 // call to this function is encountered it is skipped. The seen_caller | 325 // call to this function is encountered it is skipped. The seen_caller |
326 // in/out parameter is used to remember if the caller has been seen | 326 // in/out parameter is used to remember if the caller has been seen |
327 // yet. | 327 // yet. |
328 static bool IsVisibleInStackTrace(StackFrame* raw_frame, | 328 static bool IsVisibleInStackTrace(JSFunction* fun, |
329 Object* caller, | 329 Object* caller, |
| 330 Object* receiver, |
330 bool* seen_caller) { | 331 bool* seen_caller) { |
331 // Only display JS frames. | |
332 if (!raw_frame->is_java_script()) return false; | |
333 JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame); | |
334 JSFunction* fun = frame->function(); | |
335 if ((fun == caller) && !(*seen_caller)) { | 332 if ((fun == caller) && !(*seen_caller)) { |
336 *seen_caller = true; | 333 *seen_caller = true; |
337 return false; | 334 return false; |
338 } | 335 } |
339 // Skip all frames until we've seen the caller. | 336 // Skip all frames until we've seen the caller. |
340 if (!(*seen_caller)) return false; | 337 if (!(*seen_caller)) return false; |
341 // Also, skip non-visible built-in functions and any call with the builtins | 338 // Also, skip non-visible built-in functions and any call with the builtins |
342 // object as receiver, so as to not reveal either the builtins object or | 339 // object as receiver, so as to not reveal either the builtins object or |
343 // an internal function. | 340 // an internal function. |
344 // The --builtins-in-stack-traces command line flag allows including | 341 // The --builtins-in-stack-traces command line flag allows including |
345 // internal call sites in the stack trace for debugging purposes. | 342 // internal call sites in the stack trace for debugging purposes. |
346 if (!FLAG_builtins_in_stack_traces) { | 343 if (!FLAG_builtins_in_stack_traces) { |
347 if (frame->receiver()->IsJSBuiltinsObject() || | 344 if (receiver->IsJSBuiltinsObject()) return false; |
348 (fun->IsBuiltin() && !fun->shared()->native())) { | 345 if (fun->IsBuiltin()) { |
| 346 return fun->shared()->native(); |
| 347 } else if (fun->IsFromNativeScript() || fun->IsFromExtensionScript()) { |
349 return false; | 348 return false; |
350 } | 349 } |
351 } | 350 } |
352 return true; | 351 return true; |
353 } | 352 } |
354 | 353 |
355 | 354 |
356 Handle<JSArray> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object, | 355 Handle<JSArray> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object, |
357 Handle<Object> caller, | 356 Handle<Object> caller, |
358 int limit) { | 357 int limit) { |
359 limit = Max(limit, 0); // Ensure that limit is not negative. | 358 limit = Max(limit, 0); // Ensure that limit is not negative. |
360 int initial_size = Min(limit, 10); | 359 int initial_size = Min(limit, 10); |
361 Handle<FixedArray> elements = | 360 Handle<FixedArray> elements = |
362 factory()->NewFixedArrayWithHoles(initial_size * 4 + 1); | 361 factory()->NewFixedArrayWithHoles(initial_size * 4 + 1); |
363 | 362 |
364 // If the caller parameter is a function we skip frames until we're | 363 // If the caller parameter is a function we skip frames until we're |
365 // under it before starting to collect. | 364 // under it before starting to collect. |
366 bool seen_caller = !caller->IsJSFunction(); | 365 bool seen_caller = !caller->IsJSFunction(); |
367 // First element is reserved to store the number of sloppy frames. | 366 // First element is reserved to store the number of sloppy frames. |
368 int cursor = 1; | 367 int cursor = 1; |
369 int frames_seen = 0; | 368 int frames_seen = 0; |
370 int sloppy_frames = 0; | 369 int sloppy_frames = 0; |
371 bool encountered_strict_function = false; | 370 bool encountered_strict_function = false; |
372 for (StackFrameIterator iter(this); | 371 for (JavaScriptFrameIterator iter(this); |
373 !iter.done() && frames_seen < limit; | 372 !iter.done() && frames_seen < limit; |
374 iter.Advance()) { | 373 iter.Advance()) { |
375 StackFrame* raw_frame = iter.frame(); | 374 JavaScriptFrame* frame = iter.frame(); |
376 if (IsVisibleInStackTrace(raw_frame, *caller, &seen_caller)) { | 375 // Set initial size to the maximum inlining level + 1 for the outermost |
377 JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame); | 376 // function. |
378 // Set initial size to the maximum inlining level + 1 for the outermost | 377 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); |
379 // function. | 378 frame->Summarize(&frames); |
380 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | 379 for (int i = frames.length() - 1; i >= 0; i--) { |
381 frame->Summarize(&frames); | 380 Handle<JSFunction> fun = frames[i].function(); |
382 for (int i = frames.length() - 1; i >= 0; i--) { | 381 Handle<Object> recv = frames[i].receiver(); |
383 Handle<JSFunction> fun = frames[i].function(); | 382 // Filter out internal frames that we do not want to show. |
384 // Filter out frames from other security contexts. | 383 if (!IsVisibleInStackTrace(*fun, *caller, *recv, &seen_caller)) continue; |
385 if (!this->context()->HasSameSecurityTokenAs(fun->context())) continue; | 384 // Filter out frames from other security contexts. |
386 if (cursor + 4 > elements->length()) { | 385 if (!this->context()->HasSameSecurityTokenAs(fun->context())) continue; |
387 int new_capacity = JSObject::NewElementsCapacity(elements->length()); | 386 if (cursor + 4 > elements->length()) { |
388 Handle<FixedArray> new_elements = | 387 int new_capacity = JSObject::NewElementsCapacity(elements->length()); |
389 factory()->NewFixedArrayWithHoles(new_capacity); | 388 Handle<FixedArray> new_elements = |
390 for (int i = 0; i < cursor; i++) { | 389 factory()->NewFixedArrayWithHoles(new_capacity); |
391 new_elements->set(i, elements->get(i)); | 390 for (int i = 0; i < cursor; i++) { |
392 } | 391 new_elements->set(i, elements->get(i)); |
393 elements = new_elements; | |
394 } | 392 } |
395 ASSERT(cursor + 4 <= elements->length()); | 393 elements = new_elements; |
| 394 } |
| 395 ASSERT(cursor + 4 <= elements->length()); |
396 | 396 |
397 Handle<Object> recv = frames[i].receiver(); | 397 |
398 Handle<Code> code = frames[i].code(); | 398 Handle<Code> code = frames[i].code(); |
399 Handle<Smi> offset(Smi::FromInt(frames[i].offset()), this); | 399 Handle<Smi> offset(Smi::FromInt(frames[i].offset()), this); |
400 // The stack trace API should not expose receivers and function | 400 // The stack trace API should not expose receivers and function |
401 // objects on frames deeper than the top-most one with a strict | 401 // objects on frames deeper than the top-most one with a strict |
402 // mode function. The number of sloppy frames is stored as | 402 // mode function. The number of sloppy frames is stored as |
403 // first element in the result array. | 403 // first element in the result array. |
404 if (!encountered_strict_function) { | 404 if (!encountered_strict_function) { |
405 if (fun->shared()->strict_mode() == STRICT) { | 405 if (fun->shared()->strict_mode() == STRICT) { |
406 encountered_strict_function = true; | 406 encountered_strict_function = true; |
407 } else { | 407 } else { |
408 sloppy_frames++; | 408 sloppy_frames++; |
409 } | |
410 } | 409 } |
411 elements->set(cursor++, *recv); | |
412 elements->set(cursor++, *fun); | |
413 elements->set(cursor++, *code); | |
414 elements->set(cursor++, *offset); | |
415 } | 410 } |
| 411 elements->set(cursor++, *recv); |
| 412 elements->set(cursor++, *fun); |
| 413 elements->set(cursor++, *code); |
| 414 elements->set(cursor++, *offset); |
416 frames_seen++; | 415 frames_seen++; |
417 } | 416 } |
418 } | 417 } |
419 elements->set(0, Smi::FromInt(sloppy_frames)); | 418 elements->set(0, Smi::FromInt(sloppy_frames)); |
420 Handle<JSArray> result = factory()->NewJSArrayWithElements(elements); | 419 Handle<JSArray> result = factory()->NewJSArrayWithElements(elements); |
421 result->set_length(Smi::FromInt(cursor)); | 420 result->set_length(Smi::FromInt(cursor)); |
422 return result; | 421 return result; |
423 } | 422 } |
424 | 423 |
425 | 424 |
(...skipping 1947 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2373 if (prev_ && prev_->Intercept(flag)) return true; | 2372 if (prev_ && prev_->Intercept(flag)) return true; |
2374 // Then check whether this scope intercepts. | 2373 // Then check whether this scope intercepts. |
2375 if ((flag & intercept_mask_)) { | 2374 if ((flag & intercept_mask_)) { |
2376 intercepted_flags_ |= flag; | 2375 intercepted_flags_ |= flag; |
2377 return true; | 2376 return true; |
2378 } | 2377 } |
2379 return false; | 2378 return false; |
2380 } | 2379 } |
2381 | 2380 |
2382 } } // namespace v8::internal | 2381 } } // namespace v8::internal |
OLD | NEW |