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

Side by Side Diff: src/isolate.cc

Issue 2270783002: Add new FrameArray type (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Address comments Created 4 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
« no previous file with comments | « src/heap-symbols.h ('k') | src/messages.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 uint8_t buffer[kMaxStackTraceSize]; 308 uint8_t buffer[kMaxStackTraceSize];
309 int length = Min(kMaxStackTraceSize - 1, trace->length()); 309 int length = Min(kMaxStackTraceSize - 1, trace->length());
310 String::WriteToFlat(*trace, buffer, 0, length); 310 String::WriteToFlat(*trace, buffer, 0, length);
311 buffer[length] = '\0'; 311 buffer[length] = '\0';
312 // TODO(dcarney): convert buffer to utf8? 312 // TODO(dcarney): convert buffer to utf8?
313 base::OS::PrintError("Stacktrace (%x-%x) %p %p: %s\n", magic, magic2, ptr1, 313 base::OS::PrintError("Stacktrace (%x-%x) %p %p: %s\n", magic, magic2, ptr1,
314 ptr2, reinterpret_cast<char*>(buffer)); 314 ptr2, reinterpret_cast<char*>(buffer));
315 base::OS::Abort(); 315 base::OS::Abort();
316 } 316 }
317 317
318 static Handle<FixedArray> MaybeGrow(Isolate* isolate, 318 namespace {
319 Handle<FixedArray> elements,
320 int cur_position, int new_size) {
321 if (new_size > elements->length()) {
322 int new_capacity = JSObject::NewElementsCapacity(elements->length());
323 Handle<FixedArray> new_elements =
324 isolate->factory()->NewFixedArrayWithHoles(new_capacity);
325 for (int i = 0; i < cur_position; i++) {
326 new_elements->set(i, elements->get(i));
327 }
328 elements = new_elements;
329 }
330 DCHECK(new_size <= elements->length());
331 return elements;
332 }
333 319
334 class StackTraceHelper { 320 class StackTraceHelper {
335 public: 321 public:
336 StackTraceHelper(Isolate* isolate, FrameSkipMode mode, Handle<Object> caller) 322 StackTraceHelper(Isolate* isolate, FrameSkipMode mode, Handle<Object> caller)
337 : isolate_(isolate), 323 : isolate_(isolate),
338 mode_(mode), 324 mode_(mode),
339 caller_(caller), 325 caller_(caller),
340 skip_next_frame_(true) { 326 skip_next_frame_(true) {
341 // The caller parameter can be used to skip a specific set of frames in the 327 // The caller parameter can be used to skip a specific set of frames in the
342 // stack trace. It can be: 328 // stack trace. It can be:
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 Isolate* isolate_; 414 Isolate* isolate_;
429 415
430 const FrameSkipMode mode_; 416 const FrameSkipMode mode_;
431 const Handle<Object> caller_; 417 const Handle<Object> caller_;
432 bool skip_next_frame_; 418 bool skip_next_frame_;
433 419
434 int sloppy_frames_; 420 int sloppy_frames_;
435 bool encountered_strict_function_; 421 bool encountered_strict_function_;
436 }; 422 };
437 423
438 namespace {
439
440 // TODO(jgruber): Fix all cases in which frames give us a hole value (e.g. the 424 // TODO(jgruber): Fix all cases in which frames give us a hole value (e.g. the
441 // receiver in RegExp constructor frames. 425 // receiver in RegExp constructor frames.
442 Handle<Object> TheHoleToUndefined(Isolate* isolate, Handle<Object> in) { 426 Handle<Object> TheHoleToUndefined(Isolate* isolate, Handle<Object> in) {
443 return (in->IsTheHole(isolate)) 427 return (in->IsTheHole(isolate))
444 ? Handle<Object>::cast(isolate->factory()->undefined_value()) 428 ? Handle<Object>::cast(isolate->factory()->undefined_value())
445 : in; 429 : in;
446 } 430 }
431
432 bool GetStackTraceLimit(Isolate* isolate, int* result) {
433 Handle<JSObject> error = isolate->error_function();
434
435 Handle<String> key = isolate->factory()->stackTraceLimit_string();
436 Handle<Object> stack_trace_limit = JSReceiver::GetDataProperty(error, key);
437 if (!stack_trace_limit->IsNumber()) return false;
438
439 // Ensure that limit is not negative.
440 *result = Max(FastD2IChecked(stack_trace_limit->Number()), 0);
441 return true;
447 } 442 }
448 443
444 } // namespace
445
449 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object, 446 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
450 FrameSkipMode mode, 447 FrameSkipMode mode,
451 Handle<Object> caller) { 448 Handle<Object> caller) {
452 DisallowJavascriptExecution no_js(this); 449 DisallowJavascriptExecution no_js(this);
453 450
454 // Get stack trace limit. 451 int limit;
455 Handle<JSObject> error = error_function(); 452 if (!GetStackTraceLimit(this, &limit)) return factory()->undefined_value();
456 Handle<String> stackTraceLimit =
457 factory()->InternalizeUtf8String("stackTraceLimit");
458 DCHECK(!stackTraceLimit.is_null());
459 Handle<Object> stack_trace_limit =
460 JSReceiver::GetDataProperty(error, stackTraceLimit);
461 if (!stack_trace_limit->IsNumber()) return factory()->undefined_value();
462 int limit = FastD2IChecked(stack_trace_limit->Number());
463 limit = Max(limit, 0); // Ensure that limit is not negative.
464 453
465 int initial_size = Min(limit, 10); 454 const int initial_size = Min(limit, 10);
466 Handle<FixedArray> elements = 455 Handle<FrameArray> elements = factory()->NewFrameArray(initial_size);
467 factory()->NewFixedArrayWithHoles(initial_size * 4 + 1);
468 456
469 StackTraceHelper helper(this, mode, caller); 457 StackTraceHelper helper(this, mode, caller);
470 458
471 // First element is reserved to store the number of sloppy frames. 459 for (StackFrameIterator iter(this);
472 int cursor = 1; 460 !iter.done() && elements->FrameCount() < limit; iter.Advance()) {
473 int frames_seen = 0;
474 for (StackFrameIterator iter(this); !iter.done() && frames_seen < limit;
475 iter.Advance()) {
476 StackFrame* frame = iter.frame(); 461 StackFrame* frame = iter.frame();
477 462
478 switch (frame->type()) { 463 switch (frame->type()) {
479 case StackFrame::JAVA_SCRIPT: 464 case StackFrame::JAVA_SCRIPT:
480 case StackFrame::OPTIMIZED: 465 case StackFrame::OPTIMIZED:
481 case StackFrame::INTERPRETED: 466 case StackFrame::INTERPRETED:
482 case StackFrame::BUILTIN: { 467 case StackFrame::BUILTIN: {
483 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); 468 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
484 // Set initial size to the maximum inlining level + 1 for the outermost 469 // Set initial size to the maximum inlining level + 1 for the outermost
485 // function. 470 // function.
486 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); 471 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
487 js_frame->Summarize(&frames); 472 js_frame->Summarize(&frames);
488 for (int i = frames.length() - 1; i >= 0; i--) { 473 for (int i = frames.length() - 1; i >= 0; i--) {
489 Handle<JSFunction> fun = frames[i].function(); 474 Handle<JSFunction> fun = frames[i].function();
490 475
491 // Filter out internal frames that we do not want to show. 476 // Filter out internal frames that we do not want to show.
492 if (!helper.IsVisibleInStackTrace(*fun)) continue; 477 if (!helper.IsVisibleInStackTrace(*fun)) continue;
493 helper.CountSloppyFrames(*fun); 478 helper.CountSloppyFrames(*fun);
494 479
495 Handle<Object> recv = frames[i].receiver(); 480 Handle<Object> recv = frames[i].receiver();
496 Handle<AbstractCode> abstract_code = frames[i].abstract_code(); 481 Handle<AbstractCode> abstract_code = frames[i].abstract_code();
497 if (frame->type() == StackFrame::BUILTIN) { 482 if (frame->type() == StackFrame::BUILTIN) {
498 // Help CallSite::IsConstructor correctly detect hand-written 483 // Help CallSite::IsConstructor correctly detect hand-written
499 // construct stubs. 484 // construct stubs.
500 Code* code = Code::cast(*abstract_code); 485 Code* code = Code::cast(*abstract_code);
501 if (code->is_construct_stub()) { 486 if (code->is_construct_stub()) {
502 recv = handle(heap()->call_site_constructor_symbol(), this); 487 recv = handle(heap()->call_site_constructor_symbol(), this);
503 } 488 }
504 } 489 }
505 Handle<Smi> offset(Smi::FromInt(frames[i].code_offset()), this); 490 const int offset = frames[i].code_offset();
506 491
507 elements = MaybeGrow(this, elements, cursor, cursor + 4); 492 elements = FrameArray::AppendJSFrame(elements,
508 elements->set(cursor++, *TheHoleToUndefined(this, recv)); 493 TheHoleToUndefined(this, recv),
509 elements->set(cursor++, *fun); 494 fun, abstract_code, offset);
510 elements->set(cursor++, *abstract_code);
511 elements->set(cursor++, *offset);
512 frames_seen++;
513 } 495 }
514 } break; 496 } break;
515 497
516 case StackFrame::BUILTIN_EXIT: { 498 case StackFrame::BUILTIN_EXIT: {
517 BuiltinExitFrame* exit_frame = BuiltinExitFrame::cast(frame); 499 BuiltinExitFrame* exit_frame = BuiltinExitFrame::cast(frame);
518 Handle<JSFunction> fun = handle(exit_frame->function(), this); 500 Handle<JSFunction> fun = handle(exit_frame->function(), this);
519 501
520 // Filter out internal frames that we do not want to show. 502 // Filter out internal frames that we do not want to show.
521 if (!helper.IsVisibleInStackTrace(*fun)) continue; 503 if (!helper.IsVisibleInStackTrace(*fun)) continue;
522 helper.CountSloppyFrames(*fun); 504 helper.CountSloppyFrames(*fun);
523 505
524 Handle<Code> code = handle(exit_frame->LookupCode(), this); 506 Handle<Code> code = handle(exit_frame->LookupCode(), this);
525 int offset = 507 int offset =
526 static_cast<int>(exit_frame->pc() - code->instruction_start()); 508 static_cast<int>(exit_frame->pc() - code->instruction_start());
527 509
528 // In order to help CallSite::IsConstructor detect builtin constructors, 510 // In order to help CallSite::IsConstructor detect builtin constructors,
529 // we reuse the receiver field to pass along a special symbol. 511 // we reuse the receiver field to pass along a special symbol.
530 Handle<Object> recv; 512 Handle<Object> recv;
531 if (exit_frame->IsConstructor()) { 513 if (exit_frame->IsConstructor()) {
532 recv = factory()->call_site_constructor_symbol(); 514 recv = factory()->call_site_constructor_symbol();
533 } else { 515 } else {
534 recv = handle(exit_frame->receiver(), this); 516 recv = handle(exit_frame->receiver(), this);
535 } 517 }
536 518
537 elements = MaybeGrow(this, elements, cursor, cursor + 4); 519 elements = FrameArray::AppendJSFrame(
538 elements->set(cursor++, *recv); 520 elements, recv, fun, Handle<AbstractCode>::cast(code), offset);
539 elements->set(cursor++, *fun);
540 elements->set(cursor++, *code);
541 elements->set(cursor++, Smi::FromInt(offset));
542 frames_seen++;
543 } break; 521 } break;
544 522
545 case StackFrame::WASM: { 523 case StackFrame::WASM: {
546 WasmFrame* wasm_frame = WasmFrame::cast(frame); 524 WasmFrame* wasm_frame = WasmFrame::cast(frame);
525 Handle<Object> wasm_object = handle(wasm_frame->wasm_obj(), this);
526 const int wasm_function_index = wasm_frame->function_index();
547 Code* code = wasm_frame->unchecked_code(); 527 Code* code = wasm_frame->unchecked_code();
548 Handle<AbstractCode> abstract_code = 528 Handle<AbstractCode> abstract_code =
549 Handle<AbstractCode>(AbstractCode::cast(code), this); 529 Handle<AbstractCode>(AbstractCode::cast(code), this);
550 int offset = 530 const int offset =
551 static_cast<int>(wasm_frame->pc() - code->instruction_start()); 531 static_cast<int>(wasm_frame->pc() - code->instruction_start());
552 elements = MaybeGrow(this, elements, cursor, cursor + 4); 532
553 elements->set(cursor++, wasm_frame->wasm_obj()); 533 // TODO(wasm): The wasm object returned by the WasmFrame should always
554 elements->set(cursor++, Smi::FromInt(wasm_frame->function_index())); 534 // be a wasm object.
555 elements->set(cursor++, *abstract_code); 535 DCHECK(wasm::IsWasmObject(*wasm_object) ||
556 elements->set(cursor++, Smi::FromInt(offset)); 536 wasm_object->IsUndefined(this));
557 frames_seen++; 537
538 elements = FrameArray::AppendWasmFrame(
539 elements, wasm_object, wasm_function_index, abstract_code, offset);
558 } break; 540 } break;
559 541
560 default: 542 default:
561 break; 543 break;
562 } 544 }
563 } 545 }
564 elements->set(0, Smi::FromInt(helper.sloppy_frames())); 546
565 elements->Shrink(cursor); 547 elements->SetSloppyFrameCount(helper.sloppy_frames());
566 Handle<JSArray> result = factory()->NewJSArrayWithElements(elements); 548 elements->ShrinkToFit();
567 result->set_length(Smi::FromInt(cursor)); 549
568 // TODO(yangguo): Queue this structured stack trace for preprocessing on GC. 550 // TODO(yangguo): Queue this structured stack trace for preprocessing on GC.
569 return result; 551 return factory()->NewJSArrayWithElements(elements);
570 } 552 }
571 553
572 MaybeHandle<JSReceiver> Isolate::CaptureAndSetDetailedStackTrace( 554 MaybeHandle<JSReceiver> Isolate::CaptureAndSetDetailedStackTrace(
573 Handle<JSReceiver> error_object) { 555 Handle<JSReceiver> error_object) {
574 if (capture_stack_trace_for_uncaught_exceptions_) { 556 if (capture_stack_trace_for_uncaught_exceptions_) {
575 // Capture stack trace for a detailed exception message. 557 // Capture stack trace for a detailed exception message.
576 Handle<Name> key = factory()->detailed_stack_trace_symbol(); 558 Handle<Name> key = factory()->detailed_stack_trace_symbol();
577 Handle<JSArray> stack_trace = CaptureCurrentStackTrace( 559 Handle<JSArray> stack_trace = CaptureCurrentStackTrace(
578 stack_trace_for_uncaught_exceptions_frame_limit_, 560 stack_trace_for_uncaught_exceptions_frame_limit_,
579 stack_trace_for_uncaught_exceptions_options_); 561 stack_trace_for_uncaught_exceptions_options_);
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
766 Handle<String> column_key_; 748 Handle<String> column_key_;
767 Handle<String> line_key_; 749 Handle<String> line_key_;
768 Handle<String> script_id_key_; 750 Handle<String> script_id_key_;
769 Handle<String> script_name_key_; 751 Handle<String> script_name_key_;
770 Handle<String> script_name_or_source_url_key_; 752 Handle<String> script_name_or_source_url_key_;
771 Handle<String> function_key_; 753 Handle<String> function_key_;
772 Handle<String> eval_key_; 754 Handle<String> eval_key_;
773 Handle<String> constructor_key_; 755 Handle<String> constructor_key_;
774 }; 756 };
775 757
776
777 int PositionFromStackTrace(Handle<FixedArray> elements, int index) {
778 DisallowHeapAllocation no_gc;
779 Object* maybe_code = elements->get(index + 2);
780 if (maybe_code->IsSmi()) {
781 return Smi::cast(maybe_code)->value();
782 } else {
783 AbstractCode* abstract_code = AbstractCode::cast(maybe_code);
784 int code_offset = Smi::cast(elements->get(index + 3))->value();
785 return abstract_code->SourcePosition(code_offset);
786 }
787 }
788
789 Handle<JSArray> Isolate::CaptureCurrentStackTrace( 758 Handle<JSArray> Isolate::CaptureCurrentStackTrace(
790 int frame_limit, StackTrace::StackTraceOptions options) { 759 int frame_limit, StackTrace::StackTraceOptions options) {
791 DisallowJavascriptExecution no_js(this); 760 DisallowJavascriptExecution no_js(this);
792 CaptureStackTraceHelper helper(this, options); 761 CaptureStackTraceHelper helper(this, options);
793 762
794 // Ensure no negative values. 763 // Ensure no negative values.
795 int limit = Max(frame_limit, 0); 764 int limit = Max(frame_limit, 0);
796 Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit); 765 Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit);
797 Handle<FixedArray> stack_trace_elems( 766 Handle<FixedArray> stack_trace_elems(
798 FixedArray::cast(stack_trace->elements()), this); 767 FixedArray::cast(stack_trace->elements()), this);
(...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after
1524 1493
1525 bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target, 1494 bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target,
1526 Handle<Object> exception) { 1495 Handle<Object> exception) {
1527 if (!exception->IsJSObject()) return false; 1496 if (!exception->IsJSObject()) return false;
1528 Handle<Name> key = factory()->stack_trace_symbol(); 1497 Handle<Name> key = factory()->stack_trace_symbol();
1529 Handle<Object> property = 1498 Handle<Object> property =
1530 JSReceiver::GetDataProperty(Handle<JSObject>::cast(exception), key); 1499 JSReceiver::GetDataProperty(Handle<JSObject>::cast(exception), key);
1531 if (!property->IsJSArray()) return false; 1500 if (!property->IsJSArray()) return false;
1532 Handle<JSArray> simple_stack_trace = Handle<JSArray>::cast(property); 1501 Handle<JSArray> simple_stack_trace = Handle<JSArray>::cast(property);
1533 1502
1534 Handle<FixedArray> elements(FixedArray::cast(simple_stack_trace->elements())); 1503 Handle<FrameArray> elements(FrameArray::cast(simple_stack_trace->elements()));
1535 int elements_limit = Smi::cast(simple_stack_trace->length())->value();
1536 1504
1537 for (int i = 1; i < elements_limit; i += 4) { 1505 const int frame_count = elements->FrameCount();
1538 Handle<Object> fun_obj = handle(elements->get(i + 1), this); 1506 for (int i = 0; i < frame_count; i++) {
1539 if (fun_obj->IsSmi()) { 1507 if (elements->IsWasmFrame(i)) {
1540 // TODO(clemensh): handle wasm frames 1508 // TODO(clemensh): handle wasm frames
1541 return false; 1509 return false;
1542 } 1510 }
1543 Handle<JSFunction> fun = Handle<JSFunction>::cast(fun_obj); 1511
1512 Handle<JSFunction> fun = handle(elements->Function(i), this);
1544 if (!fun->shared()->IsSubjectToDebugging()) continue; 1513 if (!fun->shared()->IsSubjectToDebugging()) continue;
1545 1514
1546 Object* script = fun->shared()->script(); 1515 Object* script = fun->shared()->script();
1547 if (script->IsScript() && 1516 if (script->IsScript() &&
1548 !(Script::cast(script)->source()->IsUndefined(this))) { 1517 !(Script::cast(script)->source()->IsUndefined(this))) {
1549 int pos = PositionFromStackTrace(elements, i); 1518 AbstractCode* abstract_code = elements->Code(i);
1519 const int code_offset = elements->Offset(i)->value();
1520 const int pos = abstract_code->SourcePosition(code_offset);
1521
1550 Handle<Script> casted_script(Script::cast(script)); 1522 Handle<Script> casted_script(Script::cast(script));
1551 *target = MessageLocation(casted_script, pos, pos + 1); 1523 *target = MessageLocation(casted_script, pos, pos + 1);
1552 return true; 1524 return true;
1553 } 1525 }
1554 } 1526 }
1555 return false; 1527 return false;
1556 } 1528 }
1557 1529
1558 1530
1559 Handle<JSMessageObject> Isolate::CreateMessage(Handle<Object> exception, 1531 Handle<JSMessageObject> Isolate::CreateMessage(Handle<Object> exception,
(...skipping 1651 matching lines...) Expand 10 before | Expand all | Expand 10 after
3211 // Then check whether this scope intercepts. 3183 // Then check whether this scope intercepts.
3212 if ((flag & intercept_mask_)) { 3184 if ((flag & intercept_mask_)) {
3213 intercepted_flags_ |= flag; 3185 intercepted_flags_ |= flag;
3214 return true; 3186 return true;
3215 } 3187 }
3216 return false; 3188 return false;
3217 } 3189 }
3218 3190
3219 } // namespace internal 3191 } // namespace internal
3220 } // namespace v8 3192 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap-symbols.h ('k') | src/messages.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698