| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 | 29 |
| 30 #include "frames-inl.h" | 30 #include "frames-inl.h" |
| 31 #include "mark-compact.h" | 31 #include "mark-compact.h" |
| 32 #include "scopeinfo.h" | 32 #include "scopeinfo.h" |
| 33 #include "string-stream.h" | 33 #include "string-stream.h" |
| 34 #include "top.h" | 34 #include "top.h" |
| 35 | 35 |
| 36 namespace v8 { | 36 namespace v8 { |
| 37 namespace internal { | 37 namespace internal { |
| 38 | 38 |
| 39 PcToCodeCache::PcToCodeCacheEntry |
| 40 PcToCodeCache::cache_[PcToCodeCache::kPcToCodeCacheSize]; |
| 41 |
| 42 int SafeStackFrameIterator::active_count_ = 0; |
| 43 |
| 39 // Iterator that supports traversing the stack handlers of a | 44 // Iterator that supports traversing the stack handlers of a |
| 40 // particular frame. Needs to know the top of the handler chain. | 45 // particular frame. Needs to know the top of the handler chain. |
| 41 class StackHandlerIterator BASE_EMBEDDED { | 46 class StackHandlerIterator BASE_EMBEDDED { |
| 42 public: | 47 public: |
| 43 StackHandlerIterator(const StackFrame* frame, StackHandler* handler) | 48 StackHandlerIterator(const StackFrame* frame, StackHandler* handler) |
| 44 : limit_(frame->fp()), handler_(handler) { | 49 : limit_(frame->fp()), handler_(handler) { |
| 45 // Make sure the handler has already been unwound to this frame. | 50 // Make sure the handler has already been unwound to this frame. |
| 46 ASSERT(frame->sp() <= handler->address()); | 51 ASSERT(frame->sp() <= handler->address()); |
| 47 } | 52 } |
| 48 | 53 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp) | 86 StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp) |
| 82 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | 87 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) |
| 83 frame_(NULL), handler_(NULL), | 88 frame_(NULL), handler_(NULL), |
| 84 thread_(use_top ? Top::GetCurrentThread() : NULL), | 89 thread_(use_top ? Top::GetCurrentThread() : NULL), |
| 85 fp_(use_top ? NULL : fp), sp_(sp), | 90 fp_(use_top ? NULL : fp), sp_(sp), |
| 86 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler : | 91 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler : |
| 87 &StackFrameIterator::AdvanceWithoutHandler) { | 92 &StackFrameIterator::AdvanceWithoutHandler) { |
| 88 if (use_top || fp != NULL) { | 93 if (use_top || fp != NULL) { |
| 89 Reset(); | 94 Reset(); |
| 90 } | 95 } |
| 91 JavaScriptFrame_.DisableHeapAccess(); | |
| 92 } | 96 } |
| 93 | 97 |
| 94 #undef INITIALIZE_SINGLETON | 98 #undef INITIALIZE_SINGLETON |
| 95 | 99 |
| 96 | 100 |
| 97 void StackFrameIterator::AdvanceWithHandler() { | 101 void StackFrameIterator::AdvanceWithHandler() { |
| 98 ASSERT(!done()); | 102 ASSERT(!done()); |
| 99 // Compute the state of the calling frame before restoring | 103 // Compute the state of the calling frame before restoring |
| 100 // callee-saved registers and unwinding handlers. This allows the | 104 // callee-saved registers and unwinding handlers. This allows the |
| 101 // frame code that computes the caller state to access the top | 105 // frame code that computes the caller state to access the top |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 return (script->IsScript() && | 198 return (script->IsScript() && |
| 195 Script::TYPE_NATIVE != Script::cast(script)->type()->value()); | 199 Script::TYPE_NATIVE != Script::cast(script)->type()->value()); |
| 196 } | 200 } |
| 197 | 201 |
| 198 | 202 |
| 199 // ------------------------------------------------------------------------- | 203 // ------------------------------------------------------------------------- |
| 200 | 204 |
| 201 | 205 |
| 202 SafeStackFrameIterator::SafeStackFrameIterator( | 206 SafeStackFrameIterator::SafeStackFrameIterator( |
| 203 Address fp, Address sp, Address low_bound, Address high_bound) : | 207 Address fp, Address sp, Address low_bound, Address high_bound) : |
| 204 low_bound_(low_bound), high_bound_(high_bound), | 208 maintainer_(), low_bound_(low_bound), high_bound_(high_bound), |
| 205 is_valid_top_( | 209 is_valid_top_( |
| 206 IsWithinBounds(low_bound, high_bound, | 210 IsWithinBounds(low_bound, high_bound, |
| 207 Top::c_entry_fp(Top::GetCurrentThread())) && | 211 Top::c_entry_fp(Top::GetCurrentThread())) && |
| 208 Top::handler(Top::GetCurrentThread()) != NULL), | 212 Top::handler(Top::GetCurrentThread()) != NULL), |
| 209 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)), | 213 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)), |
| 210 is_working_iterator_(is_valid_top_ || is_valid_fp_), | 214 is_working_iterator_(is_valid_top_ || is_valid_fp_), |
| 211 iteration_done_(!is_working_iterator_), | 215 iteration_done_(!is_working_iterator_), |
| 212 iterator_(is_valid_top_, is_valid_fp_ ? fp : NULL, sp) { | 216 iterator_(is_valid_top_, is_valid_fp_ ? fp : NULL, sp) { |
| 213 } | 217 } |
| 214 | 218 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 void SafeStackTraceFrameIterator::Advance() { | 299 void SafeStackTraceFrameIterator::Advance() { |
| 296 while (true) { | 300 while (true) { |
| 297 SafeJavaScriptFrameIterator::Advance(); | 301 SafeJavaScriptFrameIterator::Advance(); |
| 298 if (done()) return; | 302 if (done()) return; |
| 299 if (frame()->is_java_script()) return; | 303 if (frame()->is_java_script()) return; |
| 300 } | 304 } |
| 301 } | 305 } |
| 302 #endif | 306 #endif |
| 303 | 307 |
| 304 | 308 |
| 305 // ------------------------------------------------------------------------- | |
| 306 | |
| 307 | |
| 308 void StackHandler::Cook(Code* code) { | |
| 309 ASSERT(code->contains(pc())); | |
| 310 set_pc(AddressFrom<Address>(pc() - code->instruction_start())); | |
| 311 } | |
| 312 | |
| 313 | |
| 314 void StackHandler::Uncook(Code* code) { | |
| 315 set_pc(code->instruction_start() + OffsetFrom(pc())); | |
| 316 ASSERT(code->contains(pc())); | |
| 317 } | |
| 318 | |
| 319 | |
| 320 // ------------------------------------------------------------------------- | |
| 321 | |
| 322 | |
| 323 bool StackFrame::HasHandler() const { | 309 bool StackFrame::HasHandler() const { |
| 324 StackHandlerIterator it(this, top_handler()); | 310 StackHandlerIterator it(this, top_handler()); |
| 325 return !it.done(); | 311 return !it.done(); |
| 326 } | 312 } |
| 327 | 313 |
| 328 | 314 void StackFrame::IteratePc(ObjectVisitor* v, |
| 329 void StackFrame::CookFramesForThread(ThreadLocalTop* thread) { | 315 Address* pc_address, |
| 330 ASSERT(!thread->stack_is_cooked()); | 316 Code* holder) { |
| 331 for (StackFrameIterator it(thread); !it.done(); it.Advance()) { | 317 Address pc = *pc_address; |
| 332 it.frame()->Cook(); | 318 ASSERT(holder->contains(pc)); |
| 319 unsigned pc_offset = pc - holder->instruction_start(); |
| 320 Object* code = holder; |
| 321 v->VisitPointer(&code); |
| 322 if (code != holder) { |
| 323 holder = reinterpret_cast<Code*>(code); |
| 324 pc = holder->instruction_start() + pc_offset; |
| 325 *pc_address = pc; |
| 333 } | 326 } |
| 334 thread->set_stack_is_cooked(true); | |
| 335 } | 327 } |
| 336 | 328 |
| 337 | 329 |
| 338 void StackFrame::UncookFramesForThread(ThreadLocalTop* thread) { | 330 StackFrame::Type StackFrame::ComputeType(State* state) { |
| 339 ASSERT(thread->stack_is_cooked()); | 331 ASSERT(state->fp != NULL); |
| 340 for (StackFrameIterator it(thread); !it.done(); it.Advance()) { | 332 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { |
| 341 it.frame()->Uncook(); | 333 return ARGUMENTS_ADAPTOR; |
| 342 } | 334 } |
| 343 thread->set_stack_is_cooked(false); | 335 // The marker and function offsets overlap. If the marker isn't a |
| 336 // smi then the frame is a JavaScript frame -- and the marker is |
| 337 // really the function. |
| 338 const int offset = StandardFrameConstants::kMarkerOffset; |
| 339 Object* marker = Memory::Object_at(state->fp + offset); |
| 340 if (!marker->IsSmi()) return JAVA_SCRIPT; |
| 341 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); |
| 344 } | 342 } |
| 345 | 343 |
| 346 | 344 |
| 347 void StackFrame::Cook() { | |
| 348 Code* code = this->code(); | |
| 349 ASSERT(code->IsCode()); | |
| 350 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | |
| 351 it.handler()->Cook(code); | |
| 352 } | |
| 353 ASSERT(code->contains(pc())); | |
| 354 set_pc(AddressFrom<Address>(pc() - code->instruction_start())); | |
| 355 } | |
| 356 | |
| 357 | |
| 358 void StackFrame::Uncook() { | |
| 359 Code* code = this->code(); | |
| 360 ASSERT(code->IsCode()); | |
| 361 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | |
| 362 it.handler()->Uncook(code); | |
| 363 } | |
| 364 set_pc(code->instruction_start() + OffsetFrom(pc())); | |
| 365 ASSERT(code->contains(pc())); | |
| 366 } | |
| 367 | |
| 368 | 345 |
| 369 StackFrame::Type StackFrame::GetCallerState(State* state) const { | 346 StackFrame::Type StackFrame::GetCallerState(State* state) const { |
| 370 ComputeCallerState(state); | 347 ComputeCallerState(state); |
| 371 return ComputeType(state); | 348 return ComputeType(state); |
| 372 } | 349 } |
| 373 | 350 |
| 374 | 351 |
| 375 Code* EntryFrame::unchecked_code() const { | 352 Code* EntryFrame::unchecked_code() const { |
| 376 return Heap::raw_unchecked_js_entry_code(); | 353 return Heap::raw_unchecked_js_entry_code(); |
| 377 } | 354 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 state->pc_address | 395 state->pc_address |
| 419 = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset); | 396 = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset); |
| 420 } | 397 } |
| 421 | 398 |
| 422 | 399 |
| 423 void ExitFrame::SetCallerFp(Address caller_fp) { | 400 void ExitFrame::SetCallerFp(Address caller_fp) { |
| 424 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp; | 401 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp; |
| 425 } | 402 } |
| 426 | 403 |
| 427 | 404 |
| 405 void ExitFrame::Iterate(ObjectVisitor* v) const { |
| 406 // The arguments are traversed as part of the expression stack of |
| 407 // the calling frame. |
| 408 IteratePc(v, pc_address(), code()); |
| 409 v->VisitPointer(&code_slot()); |
| 410 } |
| 411 |
| 412 |
| 428 Address ExitFrame::GetCallerStackPointer() const { | 413 Address ExitFrame::GetCallerStackPointer() const { |
| 429 return fp() + ExitFrameConstants::kCallerSPDisplacement; | 414 return fp() + ExitFrameConstants::kCallerSPDisplacement; |
| 430 } | 415 } |
| 431 | 416 |
| 432 | 417 |
| 433 Address StandardFrame::GetExpressionAddress(int n) const { | 418 Address StandardFrame::GetExpressionAddress(int n) const { |
| 434 const int offset = StandardFrameConstants::kExpressionsOffset; | 419 const int offset = StandardFrameConstants::kExpressionsOffset; |
| 435 return fp() + offset - n * kPointerSize; | 420 return fp() + offset - n * kPointerSize; |
| 436 } | 421 } |
| 437 | 422 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 return IsConstructFrame(fp); | 477 return IsConstructFrame(fp); |
| 493 } | 478 } |
| 494 | 479 |
| 495 | 480 |
| 496 Code* JavaScriptFrame::unchecked_code() const { | 481 Code* JavaScriptFrame::unchecked_code() const { |
| 497 JSFunction* function = JSFunction::cast(this->function()); | 482 JSFunction* function = JSFunction::cast(this->function()); |
| 498 return function->unchecked_code(); | 483 return function->unchecked_code(); |
| 499 } | 484 } |
| 500 | 485 |
| 501 | 486 |
| 487 int JavaScriptFrame::GetProvidedParametersCount() const { |
| 488 return ComputeParametersCount(); |
| 489 } |
| 490 |
| 491 |
| 492 Address JavaScriptFrame::GetCallerStackPointer() const { |
| 493 int arguments; |
| 494 if (Heap::gc_state() != Heap::NOT_IN_GC || |
| 495 SafeStackFrameIterator::is_active()) { |
| 496 // If the we are currently iterating the safe stack the |
| 497 // arguments for frames are traversed as if they were |
| 498 // expression stack elements of the calling frame. The reason for |
| 499 // this rather strange decision is that we cannot access the |
| 500 // function during mark-compact GCs when objects may have been marked. |
| 501 // In fact accessing heap objects (like function->shared() below) |
| 502 // at all during GC is problematic. |
| 503 arguments = 0; |
| 504 } else { |
| 505 // Compute the number of arguments by getting the number of formal |
| 506 // parameters of the function. We must remember to take the |
| 507 // receiver into account (+1). |
| 508 JSFunction* function = JSFunction::cast(this->function()); |
| 509 arguments = function->shared()->formal_parameter_count() + 1; |
| 510 } |
| 511 const int offset = StandardFrameConstants::kCallerSPOffset; |
| 512 return fp() + offset + (arguments * kPointerSize); |
| 513 } |
| 514 |
| 515 |
| 516 Address ArgumentsAdaptorFrame::GetCallerStackPointer() const { |
| 517 const int arguments = Smi::cast(GetExpression(0))->value(); |
| 518 const int offset = StandardFrameConstants::kCallerSPOffset; |
| 519 return fp() + offset + (arguments + 1) * kPointerSize; |
| 520 } |
| 521 |
| 522 |
| 523 Address InternalFrame::GetCallerStackPointer() const { |
| 524 // Internal frames have no arguments. The stack pointer of the |
| 525 // caller is at a fixed offset from the frame pointer. |
| 526 return fp() + StandardFrameConstants::kCallerSPOffset; |
| 527 } |
| 528 |
| 529 |
| 502 Code* ArgumentsAdaptorFrame::unchecked_code() const { | 530 Code* ArgumentsAdaptorFrame::unchecked_code() const { |
| 503 return Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline); | 531 return Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline); |
| 504 } | 532 } |
| 505 | 533 |
| 506 | 534 |
| 507 Code* InternalFrame::unchecked_code() const { | 535 Code* InternalFrame::unchecked_code() const { |
| 508 const int offset = InternalFrameConstants::kCodeOffset; | 536 const int offset = InternalFrameConstants::kCodeOffset; |
| 509 Object* code = Memory::Object_at(fp() + offset); | 537 Object* code = Memory::Object_at(fp() + offset); |
| 510 ASSERT(code != NULL); | 538 ASSERT(code != NULL); |
| 511 return reinterpret_cast<Code*>(code); | 539 return reinterpret_cast<Code*>(code); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 | 715 |
| 688 accumulator->Add("}\n\n"); | 716 accumulator->Add("}\n\n"); |
| 689 } | 717 } |
| 690 | 718 |
| 691 | 719 |
| 692 void EntryFrame::Iterate(ObjectVisitor* v) const { | 720 void EntryFrame::Iterate(ObjectVisitor* v) const { |
| 693 StackHandlerIterator it(this, top_handler()); | 721 StackHandlerIterator it(this, top_handler()); |
| 694 ASSERT(!it.done()); | 722 ASSERT(!it.done()); |
| 695 StackHandler* handler = it.handler(); | 723 StackHandler* handler = it.handler(); |
| 696 ASSERT(handler->is_entry()); | 724 ASSERT(handler->is_entry()); |
| 697 handler->Iterate(v); | 725 handler->Iterate(v, code()); |
| 698 // Make sure that there's the entry frame does not contain more than | |
| 699 // one stack handler. | |
| 700 #ifdef DEBUG | 726 #ifdef DEBUG |
| 727 // Make sure that the entry frame does not contain more than one |
| 728 // stack handler. |
| 701 it.Advance(); | 729 it.Advance(); |
| 702 ASSERT(it.done()); | 730 ASSERT(it.done()); |
| 703 #endif | 731 #endif |
| 732 IteratePc(v, pc_address(), code()); |
| 704 } | 733 } |
| 705 | 734 |
| 706 | 735 |
| 707 void StandardFrame::IterateExpressions(ObjectVisitor* v) const { | 736 void StandardFrame::IterateExpressions(ObjectVisitor* v) const { |
| 708 const int offset = StandardFrameConstants::kContextOffset; | 737 const int offset = StandardFrameConstants::kContextOffset; |
| 709 Object** base = &Memory::Object_at(sp()); | 738 Object** base = &Memory::Object_at(sp()); |
| 710 Object** limit = &Memory::Object_at(fp() + offset) + 1; | 739 Object** limit = &Memory::Object_at(fp() + offset) + 1; |
| 711 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | 740 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { |
| 712 StackHandler* handler = it.handler(); | 741 StackHandler* handler = it.handler(); |
| 713 // Traverse pointers down to - but not including - the next | 742 // Traverse pointers down to - but not including - the next |
| 714 // handler in the handler chain. Update the base to skip the | 743 // handler in the handler chain. Update the base to skip the |
| 715 // handler and allow the handler to traverse its own pointers. | 744 // handler and allow the handler to traverse its own pointers. |
| 716 const Address address = handler->address(); | 745 const Address address = handler->address(); |
| 717 v->VisitPointers(base, reinterpret_cast<Object**>(address)); | 746 v->VisitPointers(base, reinterpret_cast<Object**>(address)); |
| 718 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize); | 747 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize); |
| 719 // Traverse the pointers in the handler itself. | 748 // Traverse the pointers in the handler itself. |
| 720 handler->Iterate(v); | 749 handler->Iterate(v, code()); |
| 721 } | 750 } |
| 722 v->VisitPointers(base, limit); | 751 v->VisitPointers(base, limit); |
| 723 } | 752 } |
| 724 | 753 |
| 725 | 754 |
| 726 void JavaScriptFrame::Iterate(ObjectVisitor* v) const { | 755 void JavaScriptFrame::Iterate(ObjectVisitor* v) const { |
| 727 IterateExpressions(v); | 756 IterateExpressions(v); |
| 757 IteratePc(v, pc_address(), code()); |
| 728 | 758 |
| 729 // Traverse callee-saved registers, receiver, and parameters. | 759 // Traverse callee-saved registers, receiver, and parameters. |
| 730 const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset; | 760 const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset; |
| 731 const int kLimitOffset = JavaScriptFrameConstants::kReceiverOffset; | 761 const int kLimitOffset = JavaScriptFrameConstants::kReceiverOffset; |
| 732 Object** base = &Memory::Object_at(fp() + kBaseOffset); | 762 Object** base = &Memory::Object_at(fp() + kBaseOffset); |
| 733 Object** limit = &Memory::Object_at(caller_sp() + kLimitOffset) + 1; | 763 Object** limit = &Memory::Object_at(caller_sp() + kLimitOffset) + 1; |
| 734 v->VisitPointers(base, limit); | 764 v->VisitPointers(base, limit); |
| 735 } | 765 } |
| 736 | 766 |
| 737 | 767 |
| 738 void InternalFrame::Iterate(ObjectVisitor* v) const { | 768 void InternalFrame::Iterate(ObjectVisitor* v) const { |
| 739 // Internal frames only have object pointers on the expression stack | 769 // Internal frames only have object pointers on the expression stack |
| 740 // as they never have any arguments. | 770 // as they never have any arguments. |
| 741 IterateExpressions(v); | 771 IterateExpressions(v); |
| 772 IteratePc(v, pc_address(), code()); |
| 742 } | 773 } |
| 743 | 774 |
| 744 | 775 |
| 745 // ------------------------------------------------------------------------- | 776 // ------------------------------------------------------------------------- |
| 746 | 777 |
| 747 | 778 |
| 748 JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) { | 779 JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) { |
| 749 ASSERT(n >= 0); | 780 ASSERT(n >= 0); |
| 750 for (int i = 0; i <= n; i++) { | 781 for (int i = 0; i <= n; i++) { |
| 751 while (!iterator_.frame()->is_java_script()) iterator_.Advance(); | 782 while (!iterator_.frame()->is_java_script()) iterator_.Advance(); |
| 752 if (i == n) return JavaScriptFrame::cast(iterator_.frame()); | 783 if (i == n) return JavaScriptFrame::cast(iterator_.frame()); |
| 753 iterator_.Advance(); | 784 iterator_.Advance(); |
| 754 } | 785 } |
| 755 UNREACHABLE(); | 786 UNREACHABLE(); |
| 756 return NULL; | 787 return NULL; |
| 757 } | 788 } |
| 758 | 789 |
| 759 | 790 |
| 760 // ------------------------------------------------------------------------- | 791 // ------------------------------------------------------------------------- |
| 761 | 792 |
| 762 | 793 |
| 794 Code* PcToCodeCache::GcSafeCastToCode(HeapObject* object, Address pc) { |
| 795 Code* code = reinterpret_cast<Code*>(object); |
| 796 ASSERT(code != NULL && code->contains(pc)); |
| 797 return code; |
| 798 } |
| 799 |
| 800 |
| 801 Code* PcToCodeCache::GcSafeFindCodeForPc(Address pc) { |
| 802 // Check if the pc points into a large object chunk. |
| 803 LargeObjectChunk* chunk = Heap::lo_space()->FindChunkContainingPc(pc); |
| 804 if (chunk != NULL) return GcSafeCastToCode(chunk->GetObject(), pc); |
| 805 |
| 806 // Iterate through the 8K page until we reach the end or find an |
| 807 // object starting after the pc. |
| 808 Page* page = Page::FromAddress(pc); |
| 809 HeapObjectIterator iterator(page, Heap::GcSafeSizeOfOldObjectFunction()); |
| 810 HeapObject* previous = NULL; |
| 811 while (true) { |
| 812 HeapObject* next = iterator.next(); |
| 813 if (next == NULL || next->address() >= pc) { |
| 814 return GcSafeCastToCode(previous, pc); |
| 815 } |
| 816 previous = next; |
| 817 } |
| 818 } |
| 819 |
| 820 PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) { |
| 821 Counters::pc_to_code.Increment(); |
| 822 ASSERT(IsPowerOf2(kPcToCodeCacheSize)); |
| 823 uint32_t hash = ComputeIntegerHash( |
| 824 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc))); |
| 825 uint32_t index = hash & (kPcToCodeCacheSize - 1); |
| 826 PcToCodeCacheEntry* entry = cache(index); |
| 827 if (entry->pc == pc) { |
| 828 Counters::pc_to_code_cached.Increment(); |
| 829 ASSERT(entry->code == GcSafeFindCodeForPc(pc)); |
| 830 } else { |
| 831 // Because this code may be interrupted by a profiling signal that |
| 832 // also queries the cache, we cannot update pc before the code has |
| 833 // been set. Otherwise, we risk trying to use a cache entry before |
| 834 // the code has been computed. |
| 835 entry->code = GcSafeFindCodeForPc(pc); |
| 836 entry->pc = pc; |
| 837 } |
| 838 return entry; |
| 839 } |
| 840 |
| 841 |
| 842 // ------------------------------------------------------------------------- |
| 843 |
| 763 int NumRegs(RegList reglist) { | 844 int NumRegs(RegList reglist) { |
| 764 int n = 0; | 845 int n = 0; |
| 765 while (reglist != 0) { | 846 while (reglist != 0) { |
| 766 n++; | 847 n++; |
| 767 reglist &= reglist - 1; // clear one bit | 848 reglist &= reglist - 1; // clear one bit |
| 768 } | 849 } |
| 769 return n; | 850 return n; |
| 770 } | 851 } |
| 771 | 852 |
| 772 | 853 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 817 ZoneList<StackFrame*> list(10); | 898 ZoneList<StackFrame*> list(10); |
| 818 for (StackFrameIterator it; !it.done(); it.Advance()) { | 899 for (StackFrameIterator it; !it.done(); it.Advance()) { |
| 819 StackFrame* frame = AllocateFrameCopy(it.frame()); | 900 StackFrame* frame = AllocateFrameCopy(it.frame()); |
| 820 list.Add(frame); | 901 list.Add(frame); |
| 821 } | 902 } |
| 822 return list.ToVector(); | 903 return list.ToVector(); |
| 823 } | 904 } |
| 824 | 905 |
| 825 | 906 |
| 826 } } // namespace v8::internal | 907 } } // namespace v8::internal |
| OLD | NEW |