| 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 328 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 339         break; | 339         break; | 
| 340       case SKIP_UNTIL_SEEN: | 340       case SKIP_UNTIL_SEEN: | 
| 341         DCHECK(caller_->IsJSFunction()); | 341         DCHECK(caller_->IsJSFunction()); | 
| 342         skip_next_frame_ = true; | 342         skip_next_frame_ = true; | 
| 343         break; | 343         break; | 
| 344       case SKIP_NONE: | 344       case SKIP_NONE: | 
| 345         skip_next_frame_ = false; | 345         skip_next_frame_ = false; | 
| 346         break; | 346         break; | 
| 347     } | 347     } | 
| 348     encountered_strict_function_ = false; | 348     encountered_strict_function_ = false; | 
| 349     sloppy_frames_ = 0; |  | 
| 350   } | 349   } | 
| 351 | 350 | 
|  | 351   // Poison stack frames below the first strict mode frame. | 
| 352   // The stack trace API should not expose receivers and function | 352   // The stack trace API should not expose receivers and function | 
| 353   // objects on frames deeper than the top-most one with a strict mode | 353   // objects on frames deeper than the top-most one with a strict mode | 
| 354   // function. The number of sloppy frames is stored as first element in | 354   // function. | 
| 355   // the result array. | 355   bool IsStrictFrame(JSFunction* fun) { | 
| 356   void CountSloppyFrames(JSFunction* fun) { |  | 
| 357     if (!encountered_strict_function_) { | 356     if (!encountered_strict_function_) { | 
| 358       if (is_strict(fun->shared()->language_mode())) { | 357       encountered_strict_function_ = is_strict(fun->shared()->language_mode()); | 
| 359         encountered_strict_function_ = true; |  | 
| 360       } else { |  | 
| 361         sloppy_frames_++; |  | 
| 362       } |  | 
| 363     } | 358     } | 
|  | 359     return encountered_strict_function_; | 
| 364   } | 360   } | 
| 365 | 361 | 
| 366   // Determines whether the given stack frame should be displayed in a stack | 362   // Determines whether the given stack frame should be displayed in a stack | 
| 367   // trace. | 363   // trace. | 
| 368   bool IsVisibleInStackTrace(JSFunction* fun) { | 364   bool IsVisibleInStackTrace(JSFunction* fun) { | 
| 369     return ShouldIncludeFrame(fun) && IsNotInNativeScript(fun) && | 365     return ShouldIncludeFrame(fun) && IsNotInNativeScript(fun) && | 
| 370            IsInSameSecurityContext(fun); | 366            IsInSameSecurityContext(fun); | 
| 371   } | 367   } | 
| 372 | 368 | 
| 373   int sloppy_frames() const { return sloppy_frames_; } |  | 
| 374 |  | 
| 375  private: | 369  private: | 
| 376   // This mechanism excludes a number of uninteresting frames from the stack | 370   // This mechanism excludes a number of uninteresting frames from the stack | 
| 377   // trace. This can be be the first frame (which will be a builtin-exit frame | 371   // trace. This can be be the first frame (which will be a builtin-exit frame | 
| 378   // for the error constructor builtin) or every frame until encountering a | 372   // for the error constructor builtin) or every frame until encountering a | 
| 379   // user-specified function. | 373   // user-specified function. | 
| 380   bool ShouldIncludeFrame(JSFunction* fun) { | 374   bool ShouldIncludeFrame(JSFunction* fun) { | 
| 381     switch (mode_) { | 375     switch (mode_) { | 
| 382       case SKIP_NONE: | 376       case SKIP_NONE: | 
| 383         return true; | 377         return true; | 
| 384       case SKIP_FIRST: | 378       case SKIP_FIRST: | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
| 410   bool IsInSameSecurityContext(JSFunction* fun) { | 404   bool IsInSameSecurityContext(JSFunction* fun) { | 
| 411     return isolate_->context()->HasSameSecurityTokenAs(fun->context()); | 405     return isolate_->context()->HasSameSecurityTokenAs(fun->context()); | 
| 412   } | 406   } | 
| 413 | 407 | 
| 414   Isolate* isolate_; | 408   Isolate* isolate_; | 
| 415 | 409 | 
| 416   const FrameSkipMode mode_; | 410   const FrameSkipMode mode_; | 
| 417   const Handle<Object> caller_; | 411   const Handle<Object> caller_; | 
| 418   bool skip_next_frame_; | 412   bool skip_next_frame_; | 
| 419 | 413 | 
| 420   int sloppy_frames_; |  | 
| 421   bool encountered_strict_function_; | 414   bool encountered_strict_function_; | 
| 422 }; | 415 }; | 
| 423 | 416 | 
| 424 // TODO(jgruber): Fix all cases in which frames give us a hole value (e.g. the | 417 // TODO(jgruber): Fix all cases in which frames give us a hole value (e.g. the | 
| 425 // receiver in RegExp constructor frames. | 418 // receiver in RegExp constructor frames. | 
| 426 Handle<Object> TheHoleToUndefined(Isolate* isolate, Handle<Object> in) { | 419 Handle<Object> TheHoleToUndefined(Isolate* isolate, Handle<Object> in) { | 
| 427   return (in->IsTheHole(isolate)) | 420   return (in->IsTheHole(isolate)) | 
| 428              ? Handle<Object>::cast(isolate->factory()->undefined_value()) | 421              ? Handle<Object>::cast(isolate->factory()->undefined_value()) | 
| 429              : in; | 422              : in; | 
| 430 } | 423 } | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 468         JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); | 461         JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); | 
| 469         // Set initial size to the maximum inlining level + 1 for the outermost | 462         // Set initial size to the maximum inlining level + 1 for the outermost | 
| 470         // function. | 463         // function. | 
| 471         List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | 464         List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | 
| 472         js_frame->Summarize(&frames); | 465         js_frame->Summarize(&frames); | 
| 473         for (int i = frames.length() - 1; i >= 0; i--) { | 466         for (int i = frames.length() - 1; i >= 0; i--) { | 
| 474           Handle<JSFunction> fun = frames[i].function(); | 467           Handle<JSFunction> fun = frames[i].function(); | 
| 475 | 468 | 
| 476           // Filter out internal frames that we do not want to show. | 469           // Filter out internal frames that we do not want to show. | 
| 477           if (!helper.IsVisibleInStackTrace(*fun)) continue; | 470           if (!helper.IsVisibleInStackTrace(*fun)) continue; | 
| 478           helper.CountSloppyFrames(*fun); |  | 
| 479 | 471 | 
| 480           Handle<Object> recv = frames[i].receiver(); | 472           Handle<Object> recv = frames[i].receiver(); | 
| 481           Handle<AbstractCode> abstract_code = frames[i].abstract_code(); | 473           Handle<AbstractCode> abstract_code = frames[i].abstract_code(); | 
|  | 474           const int offset = frames[i].code_offset(); | 
|  | 475 | 
|  | 476           bool force_constructor = false; | 
| 482           if (frame->type() == StackFrame::BUILTIN) { | 477           if (frame->type() == StackFrame::BUILTIN) { | 
| 483             // Help CallSite::IsConstructor correctly detect hand-written | 478             // Help CallSite::IsConstructor correctly detect hand-written | 
| 484             // construct stubs. | 479             // construct stubs. | 
| 485             Code* code = Code::cast(*abstract_code); | 480             if (Code::cast(*abstract_code)->is_construct_stub()) { | 
| 486             if (code->is_construct_stub()) { | 481               force_constructor = true; | 
| 487               recv = handle(heap()->call_site_constructor_symbol(), this); |  | 
| 488             } | 482             } | 
| 489           } | 483           } | 
| 490           const int offset = frames[i].code_offset(); |  | 
| 491 | 484 | 
| 492           elements = FrameArray::AppendJSFrame(elements, | 485           int flags = 0; | 
| 493                                                TheHoleToUndefined(this, recv), | 486           if (helper.IsStrictFrame(*fun)) flags |= FrameArray::kIsStrict; | 
| 494                                                fun, abstract_code, offset); | 487           if (force_constructor) flags |= FrameArray::kForceConstructor; | 
|  | 488 | 
|  | 489           elements = FrameArray::AppendJSFrame( | 
|  | 490               elements, TheHoleToUndefined(this, recv), fun, abstract_code, | 
|  | 491               offset, flags); | 
| 495         } | 492         } | 
| 496       } break; | 493       } break; | 
| 497 | 494 | 
| 498       case StackFrame::BUILTIN_EXIT: { | 495       case StackFrame::BUILTIN_EXIT: { | 
| 499         BuiltinExitFrame* exit_frame = BuiltinExitFrame::cast(frame); | 496         BuiltinExitFrame* exit_frame = BuiltinExitFrame::cast(frame); | 
| 500         Handle<JSFunction> fun = handle(exit_frame->function(), this); | 497         Handle<JSFunction> fun = handle(exit_frame->function(), this); | 
| 501 | 498 | 
| 502         // Filter out internal frames that we do not want to show. | 499         // Filter out internal frames that we do not want to show. | 
| 503         if (!helper.IsVisibleInStackTrace(*fun)) continue; | 500         if (!helper.IsVisibleInStackTrace(*fun)) continue; | 
| 504         helper.CountSloppyFrames(*fun); |  | 
| 505 | 501 | 
| 506         Handle<Code> code = handle(exit_frame->LookupCode(), this); | 502         Handle<Object> recv(exit_frame->receiver(), this); | 
|  | 503         Handle<Code> code(exit_frame->LookupCode(), this); | 
| 507         int offset = | 504         int offset = | 
| 508             static_cast<int>(exit_frame->pc() - code->instruction_start()); | 505             static_cast<int>(exit_frame->pc() - code->instruction_start()); | 
| 509 | 506 | 
| 510         // In order to help CallSite::IsConstructor detect builtin constructors, | 507         int flags = 0; | 
| 511         // we reuse the receiver field to pass along a special symbol. | 508         if (helper.IsStrictFrame(*fun)) flags |= FrameArray::kIsStrict; | 
| 512         Handle<Object> recv; | 509         if (exit_frame->IsConstructor()) flags |= FrameArray::kForceConstructor; | 
| 513         if (exit_frame->IsConstructor()) { |  | 
| 514           recv = factory()->call_site_constructor_symbol(); |  | 
| 515         } else { |  | 
| 516           recv = handle(exit_frame->receiver(), this); |  | 
| 517         } |  | 
| 518 | 510 | 
| 519         elements = FrameArray::AppendJSFrame( | 511         elements = FrameArray::AppendJSFrame(elements, recv, fun, | 
| 520             elements, recv, fun, Handle<AbstractCode>::cast(code), offset); | 512                                              Handle<AbstractCode>::cast(code), | 
|  | 513                                              offset, flags); | 
| 521       } break; | 514       } break; | 
| 522 | 515 | 
| 523       case StackFrame::WASM: { | 516       case StackFrame::WASM: { | 
| 524         WasmFrame* wasm_frame = WasmFrame::cast(frame); | 517         WasmFrame* wasm_frame = WasmFrame::cast(frame); | 
| 525         Handle<Object> wasm_object = handle(wasm_frame->wasm_obj(), this); | 518         Handle<Object> wasm_object(wasm_frame->wasm_obj(), this); | 
| 526         const int wasm_function_index = wasm_frame->function_index(); | 519         const int wasm_function_index = wasm_frame->function_index(); | 
| 527         Code* code = wasm_frame->unchecked_code(); | 520         Code* code = wasm_frame->unchecked_code(); | 
| 528         Handle<AbstractCode> abstract_code = | 521         Handle<AbstractCode> abstract_code(AbstractCode::cast(code), this); | 
| 529             Handle<AbstractCode>(AbstractCode::cast(code), this); |  | 
| 530         const int offset = | 522         const int offset = | 
| 531             static_cast<int>(wasm_frame->pc() - code->instruction_start()); | 523             static_cast<int>(wasm_frame->pc() - code->instruction_start()); | 
| 532 | 524 | 
| 533         // TODO(wasm): The wasm object returned by the WasmFrame should always | 525         // TODO(wasm): The wasm object returned by the WasmFrame should always | 
| 534         //             be a wasm object. | 526         //             be a wasm object. | 
| 535         DCHECK(wasm::IsWasmObject(*wasm_object) || | 527         DCHECK(wasm::IsWasmObject(*wasm_object) || | 
| 536                wasm_object->IsUndefined(this)); | 528                wasm_object->IsUndefined(this)); | 
| 537 | 529 | 
| 538         elements = FrameArray::AppendWasmFrame( | 530         elements = FrameArray::AppendWasmFrame( | 
| 539             elements, wasm_object, wasm_function_index, abstract_code, offset); | 531             elements, wasm_object, wasm_function_index, abstract_code, offset, | 
|  | 532             FrameArray::kIsWasmFrame); | 
| 540       } break; | 533       } break; | 
| 541 | 534 | 
| 542       default: | 535       default: | 
| 543         break; | 536         break; | 
| 544     } | 537     } | 
| 545   } | 538   } | 
| 546 | 539 | 
| 547   elements->SetSloppyFrameCount(helper.sloppy_frames()); |  | 
| 548   elements->ShrinkToFit(); | 540   elements->ShrinkToFit(); | 
| 549 | 541 | 
| 550   // TODO(yangguo): Queue this structured stack trace for preprocessing on GC. | 542   // TODO(yangguo): Queue this structured stack trace for preprocessing on GC. | 
| 551   return factory()->NewJSArrayWithElements(elements); | 543   return factory()->NewJSArrayWithElements(elements); | 
| 552 } | 544 } | 
| 553 | 545 | 
| 554 MaybeHandle<JSReceiver> Isolate::CaptureAndSetDetailedStackTrace( | 546 MaybeHandle<JSReceiver> Isolate::CaptureAndSetDetailedStackTrace( | 
| 555     Handle<JSReceiver> error_object) { | 547     Handle<JSReceiver> error_object) { | 
| 556   if (capture_stack_trace_for_uncaught_exceptions_) { | 548   if (capture_stack_trace_for_uncaught_exceptions_) { | 
| 557     // Capture stack trace for a detailed exception message. | 549     // Capture stack trace for a detailed exception message. | 
| (...skipping 2625 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3183   // Then check whether this scope intercepts. | 3175   // Then check whether this scope intercepts. | 
| 3184   if ((flag & intercept_mask_)) { | 3176   if ((flag & intercept_mask_)) { | 
| 3185     intercepted_flags_ |= flag; | 3177     intercepted_flags_ |= flag; | 
| 3186     return true; | 3178     return true; | 
| 3187   } | 3179   } | 
| 3188   return false; | 3180   return false; | 
| 3189 } | 3181 } | 
| 3190 | 3182 | 
| 3191 }  // namespace internal | 3183 }  // namespace internal | 
| 3192 }  // namespace v8 | 3184 }  // namespace v8 | 
| OLD | NEW | 
|---|