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

Side by Side Diff: src/isolate.cc

Issue 2161953003: Remove stack overflow boilerplate (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Address comments Created 4 years, 5 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/isolate.h ('k') | src/js/messages.js » ('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 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 for (int i = 0; i < cur_position; i++) { 322 for (int i = 0; i < cur_position; i++) {
323 new_elements->set(i, elements->get(i)); 323 new_elements->set(i, elements->get(i));
324 } 324 }
325 elements = new_elements; 325 elements = new_elements;
326 } 326 }
327 DCHECK(new_size <= elements->length()); 327 DCHECK(new_size <= elements->length());
328 return elements; 328 return elements;
329 } 329 }
330 330
331 class StackTraceHelper { 331 class StackTraceHelper {
332 private:
333 enum FrameSkipMode {
334 SKIP_FIRST,
335 SKIP_UNTIL_SEEN,
336 SKIP_NONE,
337 };
338
339 public: 332 public:
340 StackTraceHelper(Isolate* isolate, Handle<Object> caller) 333 StackTraceHelper(Isolate* isolate, FrameSkipMode mode, Handle<Object> caller)
341 : isolate_(isolate), caller_(caller) { 334 : isolate_(isolate), mode_(mode), caller_(caller) {
342 // The caller parameter can be used to skip a specific set of frames in the 335 // The caller parameter can be used to skip a specific set of frames in the
343 // stack trace. It can be: 336 // stack trace. It can be:
344 // * null, when called from a standard error constructor. We unconditionally 337 // * null, when called from a standard error constructor. We unconditionally
345 // skip the top frame, which is always a builtin-exit frame for the error 338 // skip the top frame, which is always a builtin-exit frame for the error
346 // constructor builtin. 339 // constructor builtin.
347 // * a JSFunction, when called by the user from Error.captureStackTrace(). 340 // * a JSFunction, when called by the user from Error.captureStackTrace().
348 // We skip each frame until encountering the caller function. 341 // We skip each frame until encountering the caller function.
349 // * For any other value, all frames are included in the trace. 342 // * For any other value, all frames are included in the trace.
350 if (caller_.is_null()) { 343 switch (mode_) {
351 mode_ = SKIP_FIRST; 344 case SKIP_FIRST:
352 skip_next_frame_ = true; 345 DCHECK(caller_.is_null());
353 } else if (caller_->IsJSFunction()) { 346 skip_next_frame_ = true;
354 mode_ = SKIP_UNTIL_SEEN; 347 break;
355 skip_next_frame_ = true; 348 case SKIP_UNTIL_SEEN:
356 } else { 349 DCHECK(caller_->IsJSFunction());
357 mode_ = SKIP_NONE; 350 skip_next_frame_ = true;
358 skip_next_frame_ = false; 351 break;
352 case SKIP_NONE:
353 skip_next_frame_ = false;
354 break;
355 default:
Yang 2016/07/21 06:45:02 I don't think you need a default case for the comp
jgruber 2016/07/21 07:47:45 Done.
356 UNREACHABLE();
359 } 357 }
360 encountered_strict_function_ = false; 358 encountered_strict_function_ = false;
361 sloppy_frames_ = 0; 359 sloppy_frames_ = 0;
362 } 360 }
363 361
364 // The stack trace API should not expose receivers and function 362 // The stack trace API should not expose receivers and function
365 // objects on frames deeper than the top-most one with a strict mode 363 // objects on frames deeper than the top-most one with a strict mode
366 // function. The number of sloppy frames is stored as first element in 364 // function. The number of sloppy frames is stored as first element in
367 // the result array. 365 // the result array.
368 void CountSloppyFrames(JSFunction* fun) { 366 void CountSloppyFrames(JSFunction* fun) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 } 416 }
419 return true; 417 return true;
420 } 418 }
421 419
422 bool IsInSameSecurityContext(JSFunction* fun) { 420 bool IsInSameSecurityContext(JSFunction* fun) {
423 return isolate_->context()->HasSameSecurityTokenAs(fun->context()); 421 return isolate_->context()->HasSameSecurityTokenAs(fun->context());
424 } 422 }
425 423
426 Isolate* isolate_; 424 Isolate* isolate_;
427 425
428 FrameSkipMode mode_; 426 const FrameSkipMode mode_;
429 Handle<Object> caller_; 427 const Handle<Object> caller_;
430 bool skip_next_frame_; 428 bool skip_next_frame_;
431 429
432 int sloppy_frames_; 430 int sloppy_frames_;
433 bool encountered_strict_function_; 431 bool encountered_strict_function_;
434 }; 432 };
435 433
436 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object, 434 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
435 FrameSkipMode mode,
437 Handle<Object> caller) { 436 Handle<Object> caller) {
438 DisallowJavascriptExecution no_js(this); 437 DisallowJavascriptExecution no_js(this);
439 438
440 // Get stack trace limit. 439 // Get stack trace limit.
441 Handle<JSObject> error = error_function(); 440 Handle<JSObject> error = error_function();
442 Handle<String> stackTraceLimit = 441 Handle<String> stackTraceLimit =
443 factory()->InternalizeUtf8String("stackTraceLimit"); 442 factory()->InternalizeUtf8String("stackTraceLimit");
444 DCHECK(!stackTraceLimit.is_null()); 443 DCHECK(!stackTraceLimit.is_null());
445 Handle<Object> stack_trace_limit = 444 Handle<Object> stack_trace_limit =
446 JSReceiver::GetDataProperty(error, stackTraceLimit); 445 JSReceiver::GetDataProperty(error, stackTraceLimit);
447 if (!stack_trace_limit->IsNumber()) return factory()->undefined_value(); 446 if (!stack_trace_limit->IsNumber()) return factory()->undefined_value();
448 int limit = FastD2IChecked(stack_trace_limit->Number()); 447 int limit = FastD2IChecked(stack_trace_limit->Number());
449 limit = Max(limit, 0); // Ensure that limit is not negative. 448 limit = Max(limit, 0); // Ensure that limit is not negative.
450 449
451 int initial_size = Min(limit, 10); 450 int initial_size = Min(limit, 10);
452 Handle<FixedArray> elements = 451 Handle<FixedArray> elements =
453 factory()->NewFixedArrayWithHoles(initial_size * 4 + 1); 452 factory()->NewFixedArrayWithHoles(initial_size * 4 + 1);
454 453
455 StackTraceHelper helper(this, caller); 454 StackTraceHelper helper(this, mode, caller);
456 455
457 // First element is reserved to store the number of sloppy frames. 456 // First element is reserved to store the number of sloppy frames.
458 int cursor = 1; 457 int cursor = 1;
459 int frames_seen = 0; 458 int frames_seen = 0;
460 for (StackFrameIterator iter(this); !iter.done() && frames_seen < limit; 459 for (StackFrameIterator iter(this); !iter.done() && frames_seen < limit;
461 iter.Advance()) { 460 iter.Advance()) {
462 StackFrame* frame = iter.frame(); 461 StackFrame* frame = iter.frame();
463 462
464 switch (frame->type()) { 463 switch (frame->type()) {
465 case StackFrame::JAVA_SCRIPT: 464 case StackFrame::JAVA_SCRIPT:
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 stack_trace_for_uncaught_exceptions_options_); 564 stack_trace_for_uncaught_exceptions_options_);
566 // TODO(jgruber): Set back to STRICT once we have eagerly formatted traces. 565 // TODO(jgruber): Set back to STRICT once we have eagerly formatted traces.
567 RETURN_ON_EXCEPTION( 566 RETURN_ON_EXCEPTION(
568 this, JSReceiver::SetProperty(error_object, key, stack_trace, SLOPPY), 567 this, JSReceiver::SetProperty(error_object, key, stack_trace, SLOPPY),
569 JSReceiver); 568 JSReceiver);
570 } 569 }
571 return error_object; 570 return error_object;
572 } 571 }
573 572
574 MaybeHandle<JSReceiver> Isolate::CaptureAndSetSimpleStackTrace( 573 MaybeHandle<JSReceiver> Isolate::CaptureAndSetSimpleStackTrace(
575 Handle<JSReceiver> error_object, Handle<Object> caller) { 574 Handle<JSReceiver> error_object, FrameSkipMode mode,
575 Handle<Object> caller) {
576 // Capture stack trace for simple stack trace string formatting. 576 // Capture stack trace for simple stack trace string formatting.
577 Handle<Name> key = factory()->stack_trace_symbol(); 577 Handle<Name> key = factory()->stack_trace_symbol();
578 Handle<Object> stack_trace = CaptureSimpleStackTrace(error_object, caller); 578 Handle<Object> stack_trace =
579 CaptureSimpleStackTrace(error_object, mode, caller);
579 // TODO(jgruber): Set back to STRICT once we have eagerly formatted traces. 580 // TODO(jgruber): Set back to STRICT once we have eagerly formatted traces.
580 RETURN_ON_EXCEPTION( 581 RETURN_ON_EXCEPTION(
581 this, JSReceiver::SetProperty(error_object, key, stack_trace, SLOPPY), 582 this, JSReceiver::SetProperty(error_object, key, stack_trace, SLOPPY),
582 JSReceiver); 583 JSReceiver);
583 return error_object; 584 return error_object;
584 } 585 }
585 586
586 587
587 Handle<JSArray> Isolate::GetDetailedStackTrace(Handle<JSObject> error_object) { 588 Handle<JSArray> Isolate::GetDetailedStackTrace(Handle<JSObject> error_object) {
588 Handle<Name> key_detailed = factory()->detailed_stack_trace_symbol(); 589 Handle<Name> key_detailed = factory()->detailed_stack_trace_symbol();
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 VMState<EXTERNAL> state(this); 954 VMState<EXTERNAL> state(this);
954 return callback(v8::Utils::ToLocal(accessing_context), 955 return callback(v8::Utils::ToLocal(accessing_context),
955 v8::Utils::ToLocal(receiver), v8::Utils::ToLocal(data)); 956 v8::Utils::ToLocal(receiver), v8::Utils::ToLocal(data));
956 } 957 }
957 } 958 }
958 959
959 960
960 Object* Isolate::StackOverflow() { 961 Object* Isolate::StackOverflow() {
961 DisallowJavascriptExecution no_js(this); 962 DisallowJavascriptExecution no_js(this);
962 HandleScope scope(this); 963 HandleScope scope(this);
963 // At this point we cannot create an Error object using its javascript 964
964 // constructor. Instead, we copy the pre-constructed boilerplate and 965 // Disable detailed stack trace collection while generating the stack
965 // attach the stack trace as a hidden property. 966 // overflow error.
967 bool old_detailed_enabled = capture_stack_trace_for_uncaught_exceptions_;
968 capture_stack_trace_for_uncaught_exceptions_ = false;
Yang 2016/07/21 06:45:02 I think it's cleaner to pass an additional (option
jgruber 2016/07/21 07:47:45 Done.
969
970 Handle<JSFunction> fun = range_error_function();
971 Handle<Object> msg = factory()->NewStringFromAsciiChecked(
972 MessageTemplate::TemplateString(MessageTemplate::kStackOverflow));
966 Handle<Object> exception; 973 Handle<Object> exception;
967 if (bootstrapper()->IsActive()) { 974 if (!ConstructError(this, fun, fun, msg, SKIP_NONE).ToHandle(&exception)) {
Yang 2016/07/21 06:45:02 You could use the ASSIGN_RETURN_FAILURE_ON_EXCEPTI
jgruber 2016/07/21 07:47:45 Done.
968 // There is no boilerplate to use during bootstrapping. 975 DCHECK(has_pending_exception());
969 exception = factory()->NewStringFromAsciiChecked( 976 return heap()->exception();
970 MessageTemplate::TemplateString(MessageTemplate::kStackOverflow));
971 } else {
972 Handle<JSObject> boilerplate = stack_overflow_boilerplate();
973 Handle<JSObject> copy = factory()->CopyJSObject(boilerplate);
974 CaptureAndSetSimpleStackTrace(copy, factory()->undefined_value());
975 exception = copy;
976 } 977 }
978
979 capture_stack_trace_for_uncaught_exceptions_ = old_detailed_enabled;
980
977 Throw(*exception, nullptr); 981 Throw(*exception, nullptr);
978 982
979 #ifdef VERIFY_HEAP 983 #ifdef VERIFY_HEAP
980 if (FLAG_verify_heap && FLAG_stress_compaction) { 984 if (FLAG_verify_heap && FLAG_stress_compaction) {
981 heap()->CollectAllGarbage(Heap::kNoGCFlags, "trigger compaction"); 985 heap()->CollectAllGarbage(Heap::kNoGCFlags, "trigger compaction");
982 } 986 }
983 #endif // VERIFY_HEAP 987 #endif // VERIFY_HEAP
984 988
985 return heap()->exception(); 989 return heap()->exception();
986 } 990 }
(...skipping 2139 matching lines...) Expand 10 before | Expand all | Expand 10 after
3126 // Then check whether this scope intercepts. 3130 // Then check whether this scope intercepts.
3127 if ((flag & intercept_mask_)) { 3131 if ((flag & intercept_mask_)) {
3128 intercepted_flags_ |= flag; 3132 intercepted_flags_ |= flag;
3129 return true; 3133 return true;
3130 } 3134 }
3131 return false; 3135 return false;
3132 } 3136 }
3133 3137
3134 } // namespace internal 3138 } // namespace internal
3135 } // namespace v8 3139 } // namespace v8
OLDNEW
« no previous file with comments | « src/isolate.h ('k') | src/js/messages.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698