1// Copyright 2012 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28#include "v8.h" 29 30#include "ast.h" 31#include "deoptimizer.h" 32#include "frames-inl.h" 33#include "full-codegen.h" 34#include "lazy-instance.h" 35#include "mark-compact.h" 36#include "safepoint-table.h" 37#include "scopeinfo.h" 38#include "string-stream.h" 39 40#include "allocation-inl.h" 41 42namespace v8 { 43namespace internal { 44 45 46static ReturnAddressLocationResolver return_address_location_resolver = NULL; 47 48 49// Resolves pc_address through the resolution address function if one is set. 50static inline Address* ResolveReturnAddressLocation(Address* pc_address) { 51 if (return_address_location_resolver == NULL) { 52 return pc_address; 53 } else { 54 return reinterpret_cast<Address*>( 55 return_address_location_resolver( 56 reinterpret_cast<uintptr_t>(pc_address))); 57 } 58} 59 60 61// Iterator that supports traversing the stack handlers of a 62// particular frame. Needs to know the top of the handler chain. 63class StackHandlerIterator BASE_EMBEDDED { 64 public: 65 StackHandlerIterator(const StackFrame* frame, StackHandler* handler) 66 : limit_(frame->fp()), handler_(handler) { 67 // Make sure the handler has already been unwound to this frame. 68 ASSERT(frame->sp() <= handler->address()); 69 } 70 71 StackHandler* handler() const { return handler_; } 72 73 bool done() { 74 return handler_ == NULL || handler_->address() > limit_; 75 } 76 void Advance() { 77 ASSERT(!done()); 78 handler_ = handler_->next(); 79 } 80 81 private: 82 const Address limit_; 83 StackHandler* handler_; 84}; 85 86 87// ------------------------------------------------------------------------- 88 89 90#define INITIALIZE_SINGLETON(type, field) field##_(this), 91StackFrameIterator::StackFrameIterator() 92 : isolate_(Isolate::Current()), 93 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) 94 frame_(NULL), handler_(NULL), 95 thread_(isolate_->thread_local_top()), 96 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) { 97 Reset(); 98} 99StackFrameIterator::StackFrameIterator(Isolate* isolate) 100 : isolate_(isolate), 101 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) 102 frame_(NULL), handler_(NULL), 103 thread_(isolate_->thread_local_top()), 104 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) { 105 Reset(); 106} 107StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t) 108 : isolate_(isolate), 109 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) 110 frame_(NULL), handler_(NULL), thread_(t), 111 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) { 112 Reset(); 113} 114StackFrameIterator::StackFrameIterator(Isolate* isolate, 115 bool use_top, Address fp, Address sp) 116 : isolate_(isolate), 117 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) 118 frame_(NULL), handler_(NULL), 119 thread_(use_top ? isolate_->thread_local_top() : NULL), 120 fp_(use_top ? NULL : fp), sp_(sp), 121 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler : 122 &StackFrameIterator::AdvanceWithoutHandler) { 123 if (use_top || fp != NULL) { 124 Reset(); 125 } 126} 127 128#undef INITIALIZE_SINGLETON 129 130 131void StackFrameIterator::AdvanceWithHandler() { 132 ASSERT(!done()); 133 // Compute the state of the calling frame before restoring 134 // callee-saved registers and unwinding handlers. This allows the 135 // frame code that computes the caller state to access the top 136 // handler and the value of any callee-saved register if needed. 137 StackFrame::State state; 138 StackFrame::Type type = frame_->GetCallerState(&state); 139 140 // Unwind handlers corresponding to the current frame. 141 StackHandlerIterator it(frame_, handler_); 142 while (!it.done()) it.Advance(); 143 handler_ = it.handler(); 144 145 // Advance to the calling frame. 146 frame_ = SingletonFor(type, &state); 147 148 // When we're done iterating over the stack frames, the handler 149 // chain must have been completely unwound. 150 ASSERT(!done() || handler_ == NULL); 151} 152 153 154void StackFrameIterator::AdvanceWithoutHandler() { 155 // A simpler version of Advance which doesn't care about handler. 156 ASSERT(!done()); 157 StackFrame::State state; 158 StackFrame::Type type = frame_->GetCallerState(&state); 159 frame_ = SingletonFor(type, &state); 160} 161 162 163void StackFrameIterator::Reset() { 164 StackFrame::State state; 165 StackFrame::Type type; 166 if (thread_ != NULL) { 167 type = ExitFrame::GetStateForFramePointer( 168 Isolate::c_entry_fp(thread_), &state); 169 handler_ = StackHandler::FromAddress( 170 Isolate::handler(thread_)); 171 } else { 172 ASSERT(fp_ != NULL); 173 state.fp = fp_; 174 state.sp = sp_; 175 state.pc_address = ResolveReturnAddressLocation( 176 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_))); 177 type = StackFrame::ComputeType(isolate(), &state); 178 } 179 if (SingletonFor(type) == NULL) return; 180 frame_ = SingletonFor(type, &state); 181} 182 183 184StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type, 185 StackFrame::State* state) { 186 if (type == StackFrame::NONE) return NULL; 187 StackFrame* result = SingletonFor(type); 188 ASSERT(result != NULL); 189 result->state_ = *state; 190 return result; 191} 192 193 194StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) { 195#define FRAME_TYPE_CASE(type, field) \ 196 case StackFrame::type: result = &field##_; break; 197 198 StackFrame* result = NULL; 199 switch (type) { 200 case StackFrame::NONE: return NULL; 201 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE) 202 default: break; 203 } 204 return result; 205 206#undef FRAME_TYPE_CASE 207} 208 209 210// ------------------------------------------------------------------------- 211 212 213StackTraceFrameIterator::StackTraceFrameIterator() { 214 if (!done() && !IsValidFrame()) Advance(); 215} 216 217 218StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate) 219 : JavaScriptFrameIterator(isolate) { 220 if (!done() && !IsValidFrame()) Advance(); 221} 222 223 224void StackTraceFrameIterator::Advance() { 225 while (true) { 226 JavaScriptFrameIterator::Advance(); 227 if (done()) return; 228 if (IsValidFrame()) return; 229 } 230} 231 232bool StackTraceFrameIterator::IsValidFrame() { 233 if (!frame()->function()->IsJSFunction()) return false; 234 Object* script = JSFunction::cast(frame()->function())->shared()->script(); 235 // Don't show functions from native scripts to user. 236 return (script->IsScript() && 237 Script::TYPE_NATIVE != Script::cast(script)->type()->value()); 238} 239 240 241// ------------------------------------------------------------------------- 242 243 244bool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) { 245 if (!validator_.IsValid(fp)) return false; 246 Address sp = ExitFrame::ComputeStackPointer(fp); 247 if (!validator_.IsValid(sp)) return false; 248 StackFrame::State state; 249 ExitFrame::FillState(fp, sp, &state); 250 if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) { 251 return false; 252 } 253 return *state.pc_address != NULL; 254} 255 256 257SafeStackFrameIterator::ActiveCountMaintainer::ActiveCountMaintainer( 258 Isolate* isolate) 259 : isolate_(isolate) { 260 isolate_->set_safe_stack_iterator_counter( 261 isolate_->safe_stack_iterator_counter() + 1); 262} 263 264 265SafeStackFrameIterator::ActiveCountMaintainer::~ActiveCountMaintainer() { 266 isolate_->set_safe_stack_iterator_counter( 267 isolate_->safe_stack_iterator_counter() - 1); 268} 269 270 271SafeStackFrameIterator::SafeStackFrameIterator( 272 Isolate* isolate, 273 Address fp, Address sp, Address low_bound, Address high_bound) : 274 maintainer_(isolate), 275 stack_validator_(low_bound, high_bound), 276 is_valid_top_(IsValidTop(isolate, low_bound, high_bound)), 277 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)), 278 is_working_iterator_(is_valid_top_ || is_valid_fp_), 279 iteration_done_(!is_working_iterator_), 280 iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) { 281} 282 283bool SafeStackFrameIterator::is_active(Isolate* isolate) { 284 return isolate->safe_stack_iterator_counter() > 0; 285} 286 287 288bool SafeStackFrameIterator::IsValidTop(Isolate* isolate, 289 Address low_bound, Address high_bound) { 290 ThreadLocalTop* top = isolate->thread_local_top(); 291 Address fp = Isolate::c_entry_fp(top); 292 ExitFrameValidator validator(low_bound, high_bound); 293 if (!validator.IsValidFP(fp)) return false; 294 return Isolate::handler(top) != NULL; 295} 296 297 298void SafeStackFrameIterator::Advance() { 299 ASSERT(is_working_iterator_); 300 ASSERT(!done()); 301 StackFrame* last_frame = iterator_.frame(); 302 Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); 303 // Before advancing to the next stack frame, perform pointer validity tests 304 iteration_done_ = !IsValidFrame(last_frame) || 305 !CanIterateHandles(last_frame, iterator_.handler()) || 306 !IsValidCaller(last_frame); 307 if (iteration_done_) return; 308 309 iterator_.Advance(); 310 if (iterator_.done()) return; 311 // Check that we have actually moved to the previous frame in the stack 312 StackFrame* prev_frame = iterator_.frame(); 313 iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp; 314} 315 316 317bool SafeStackFrameIterator::CanIterateHandles(StackFrame* frame, 318 StackHandler* handler) { 319 // If StackIterator iterates over StackHandles, verify that 320 // StackHandlerIterator can be instantiated (see StackHandlerIterator 321 // constructor.) 322 return !is_valid_top_ || (frame->sp() <= handler->address()); 323} 324 325 326bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const { 327 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp()); 328} 329 330 331bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) { 332 StackFrame::State state; 333 if (frame->is_entry() || frame->is_entry_construct()) { 334 // See EntryFrame::GetCallerState. It computes the caller FP address 335 // and calls ExitFrame::GetStateForFramePointer on it. We need to be 336 // sure that caller FP address is valid. 337 Address caller_fp = Memory::Address_at( 338 frame->fp() + EntryFrameConstants::kCallerFPOffset); 339 ExitFrameValidator validator(stack_validator_); 340 if (!validator.IsValidFP(caller_fp)) return false; 341 } else if (frame->is_arguments_adaptor()) { 342 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that 343 // the number of arguments is stored on stack as Smi. We need to check 344 // that it really an Smi. 345 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)-> 346 GetExpression(0); 347 if (!number_of_args->IsSmi()) { 348 return false; 349 } 350 } 351 frame->ComputeCallerState(&state); 352 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) && 353 iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL; 354} 355 356 357void SafeStackFrameIterator::Reset() { 358 if (is_working_iterator_) { 359 iterator_.Reset(); 360 iteration_done_ = false; 361 } 362} 363 364 365// ------------------------------------------------------------------------- 366 367 368SafeStackTraceFrameIterator::SafeStackTraceFrameIterator( 369 Isolate* isolate, 370 Address fp, Address sp, Address low_bound, Address high_bound) : 371 SafeJavaScriptFrameIterator(isolate, fp, sp, low_bound, high_bound) { 372 if (!done() && !frame()->is_java_script()) Advance(); 373} 374 375 376void SafeStackTraceFrameIterator::Advance() { 377 while (true) { 378 SafeJavaScriptFrameIterator::Advance(); 379 if (done()) return; 380 if (frame()->is_java_script()) return; 381 } 382} 383 384 385Code* StackFrame::GetSafepointData(Isolate* isolate, 386 Address inner_pointer, 387 SafepointEntry* safepoint_entry, 388 unsigned* stack_slots) { 389 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry = 390 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer); 391 if (!entry->safepoint_entry.is_valid()) { 392 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer); 393 ASSERT(entry->safepoint_entry.is_valid()); 394 } else { 395 ASSERT(entry->safepoint_entry.Equals( 396 entry->code->GetSafepointEntry(inner_pointer))); 397 } 398 399 // Fill in the results and return the code. 400 Code* code = entry->code; 401 *safepoint_entry = entry->safepoint_entry; 402 *stack_slots = code->stack_slots(); 403 return code; 404} 405 406 407bool StackFrame::HasHandler() const { 408 StackHandlerIterator it(this, top_handler()); 409 return !it.done(); 410} 411 412 413#ifdef DEBUG 414static bool GcSafeCodeContains(HeapObject* object, Address addr); 415#endif 416 417 418void StackFrame::IteratePc(ObjectVisitor* v, 419 Address* pc_address, 420 Code* holder) { 421 Address pc = *pc_address; 422 ASSERT(GcSafeCodeContains(holder, pc)); 423 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start()); 424 Object* code = holder; 425 v->VisitPointer(&code); 426 if (code != holder) { 427 holder = reinterpret_cast<Code*>(code); 428 pc = holder->instruction_start() + pc_offset; 429 *pc_address = pc; 430 } 431} 432 433 434void StackFrame::SetReturnAddressLocationResolver( 435 ReturnAddressLocationResolver resolver) { 436 ASSERT(return_address_location_resolver == NULL); 437 return_address_location_resolver = resolver; 438} 439 440 441StackFrame::Type StackFrame::ComputeType(Isolate* isolate, State* state) { 442 ASSERT(state->fp != NULL); 443 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { 444 return ARGUMENTS_ADAPTOR; 445 } 446 // The marker and function offsets overlap. If the marker isn't a 447 // smi then the frame is a JavaScript frame -- and the marker is 448 // really the function. 449 const int offset = StandardFrameConstants::kMarkerOffset; 450 Object* marker = Memory::Object_at(state->fp + offset); 451 if (!marker->IsSmi()) { 452 // If we're using a "safe" stack iterator, we treat optimized 453 // frames as normal JavaScript frames to avoid having to look 454 // into the heap to determine the state. This is safe as long 455 // as nobody tries to GC... 456 if (SafeStackFrameIterator::is_active(isolate)) return JAVA_SCRIPT; 457 Code::Kind kind = GetContainingCode(isolate, *(state->pc_address))->kind(); 458 ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION); 459 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT; 460 } 461 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); 462} 463 464 465 466StackFrame::Type StackFrame::GetCallerState(State* state) const { 467 ComputeCallerState(state); 468 return ComputeType(isolate(), state); 469} 470 471 472Code* EntryFrame::unchecked_code() const { 473 return HEAP->raw_unchecked_js_entry_code(); 474} 475 476 477void EntryFrame::ComputeCallerState(State* state) const { 478 GetCallerState(state); 479} 480 481 482void EntryFrame::SetCallerFp(Address caller_fp) { 483 const int offset = EntryFrameConstants::kCallerFPOffset; 484 Memory::Address_at(this->fp() + offset) = caller_fp; 485} 486 487 488StackFrame::Type EntryFrame::GetCallerState(State* state) const { 489 const int offset = EntryFrameConstants::kCallerFPOffset; 490 Address fp = Memory::Address_at(this->fp() + offset); 491 return ExitFrame::GetStateForFramePointer(fp, state); 492} 493 494 495Code* EntryConstructFrame::unchecked_code() const { 496 return HEAP->raw_unchecked_js_construct_entry_code(); 497} 498 499 500Object*& ExitFrame::code_slot() const { 501 const int offset = ExitFrameConstants::kCodeOffset; 502 return Memory::Object_at(fp() + offset); 503} 504 505 506Code* ExitFrame::unchecked_code() const { 507 return reinterpret_cast<Code*>(code_slot()); 508} 509 510 511void ExitFrame::ComputeCallerState(State* state) const { 512 // Set up the caller state. 513 state->sp = caller_sp(); 514 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset); 515 state->pc_address = ResolveReturnAddressLocation( 516 reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset)); 517} 518 519 520void ExitFrame::SetCallerFp(Address caller_fp) { 521 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp; 522} 523 524 525void ExitFrame::Iterate(ObjectVisitor* v) const { 526 // The arguments are traversed as part of the expression stack of 527 // the calling frame. 528 IteratePc(v, pc_address(), LookupCode()); 529 v->VisitPointer(&code_slot()); 530} 531 532 533Address ExitFrame::GetCallerStackPointer() const { 534 return fp() + ExitFrameConstants::kCallerSPDisplacement; 535} 536 537 538StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { 539 if (fp == 0) return NONE; 540 Address sp = ComputeStackPointer(fp); 541 FillState(fp, sp, state); 542 ASSERT(*state->pc_address != NULL); 543 return EXIT; 544} 545 546 547void ExitFrame::FillState(Address fp, Address sp, State* state) { 548 state->sp = sp; 549 state->fp = fp; 550 state->pc_address = ResolveReturnAddressLocation( 551 reinterpret_cast<Address*>(sp - 1 * kPointerSize)); 552} 553 554 555Address StandardFrame::GetExpressionAddress(int n) const { 556 const int offset = StandardFrameConstants::kExpressionsOffset; 557 return fp() + offset - n * kPointerSize; 558} 559 560 561Object* StandardFrame::GetExpression(Address fp, int index) { 562 return Memory::Object_at(GetExpressionAddress(fp, index)); 563} 564 565 566Address StandardFrame::GetExpressionAddress(Address fp, int n) { 567 const int offset = StandardFrameConstants::kExpressionsOffset; 568 return fp + offset - n * kPointerSize; 569} 570 571 572int StandardFrame::ComputeExpressionsCount() const { 573 const int offset = 574 StandardFrameConstants::kExpressionsOffset + kPointerSize; 575 Address base = fp() + offset; 576 Address limit = sp(); 577 ASSERT(base >= limit); // stack grows downwards 578 // Include register-allocated locals in number of expressions. 579 return static_cast<int>((base - limit) / kPointerSize); 580} 581 582 583void StandardFrame::ComputeCallerState(State* state) const { 584 state->sp = caller_sp(); 585 state->fp = caller_fp(); 586 state->pc_address = ResolveReturnAddressLocation( 587 reinterpret_cast<Address*>(ComputePCAddress(fp()))); 588} 589 590 591void StandardFrame::SetCallerFp(Address caller_fp) { 592 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) = 593 caller_fp; 594} 595 596 597bool StandardFrame::IsExpressionInsideHandler(int n) const { 598 Address address = GetExpressionAddress(n); 599 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { 600 if (it.handler()->includes(address)) return true; 601 } 602 return false; 603} 604 605 606void OptimizedFrame::Iterate(ObjectVisitor* v) const { 607#ifdef DEBUG 608 // Make sure that optimized frames do not contain any stack handlers. 609 StackHandlerIterator it(this, top_handler()); 610 ASSERT(it.done()); 611#endif 612 613 // Make sure that we're not doing "safe" stack frame iteration. We cannot 614 // possibly find pointers in optimized frames in that state. 615 ASSERT(!SafeStackFrameIterator::is_active(isolate())); 616 617 // Compute the safepoint information. 618 unsigned stack_slots = 0; 619 SafepointEntry safepoint_entry; 620 Code* code = StackFrame::GetSafepointData( 621 isolate(), pc(), &safepoint_entry, &stack_slots); 622 unsigned slot_space = stack_slots * kPointerSize; 623 624 // Visit the outgoing parameters. 625 Object** parameters_base = &Memory::Object_at(sp()); 626 Object** parameters_limit = &Memory::Object_at( 627 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space); 628 629 // Visit the parameters that may be on top of the saved registers. 630 if (safepoint_entry.argument_count() > 0) { 631 v->VisitPointers(parameters_base, 632 parameters_base + safepoint_entry.argument_count()); 633 parameters_base += safepoint_entry.argument_count(); 634 } 635 636 // Skip saved double registers. 637 if (safepoint_entry.has_doubles()) { 638 parameters_base += DoubleRegister::kNumAllocatableRegisters * 639 kDoubleSize / kPointerSize; 640 } 641 642 // Visit the registers that contain pointers if any. 643 if (safepoint_entry.HasRegisters()) { 644 for (int i = kNumSafepointRegisters - 1; i >=0; i--) { 645 if (safepoint_entry.HasRegisterAt(i)) { 646 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i); 647 v->VisitPointer(parameters_base + reg_stack_index); 648 } 649 } 650 // Skip the words containing the register values. 651 parameters_base += kNumSafepointRegisters; 652 } 653 654 // We're done dealing with the register bits. 655 uint8_t* safepoint_bits = safepoint_entry.bits(); 656 safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2; 657 658 // Visit the rest of the parameters. 659 v->VisitPointers(parameters_base, parameters_limit); 660 661 // Visit pointer spill slots and locals. 662 for (unsigned index = 0; index < stack_slots; index++) { 663 int byte_index = index >> kBitsPerByteLog2; 664 int bit_index = index & (kBitsPerByte - 1); 665 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) { 666 v->VisitPointer(parameters_limit + index); 667 } 668 } 669 670 // Visit the context and the function. 671 Object** fixed_base = &Memory::Object_at( 672 fp() + JavaScriptFrameConstants::kFunctionOffset); 673 Object** fixed_limit = &Memory::Object_at(fp()); 674 v->VisitPointers(fixed_base, fixed_limit); 675 676 // Visit the return address in the callee and incoming arguments. 677 IteratePc(v, pc_address(), code); 678} 679 680 681bool JavaScriptFrame::IsConstructor() const { 682 Address fp = caller_fp(); 683 if (has_adapted_arguments()) { 684 // Skip the arguments adaptor frame and look at the real caller. 685 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset); 686 } 687 return IsConstructFrame(fp); 688} 689 690 691int JavaScriptFrame::GetArgumentsLength() const { 692 // If there is an arguments adaptor frame get the arguments length from it. 693 if (has_adapted_arguments()) { 694 return Smi::cast(GetExpression(caller_fp(), 0))->value(); 695 } else { 696 return GetNumberOfIncomingArguments(); 697 } 698} 699 700 701Code* JavaScriptFrame::unchecked_code() const { 702 JSFunction* function = JSFunction::cast(this->function()); 703 return function->unchecked_code(); 704} 705 706 707int JavaScriptFrame::GetNumberOfIncomingArguments() const { 708 ASSERT(!SafeStackFrameIterator::is_active(isolate()) && 709 isolate()->heap()->gc_state() == Heap::NOT_IN_GC); 710 711 JSFunction* function = JSFunction::cast(this->function()); 712 return function->shared()->formal_parameter_count(); 713} 714 715 716Address JavaScriptFrame::GetCallerStackPointer() const { 717 return fp() + StandardFrameConstants::kCallerSPOffset; 718} 719 720 721void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) { 722 ASSERT(functions->length() == 0); 723 functions->Add(JSFunction::cast(function())); 724} 725 726 727void JavaScriptFrame::Summarize(List<FrameSummary>* functions) { 728 ASSERT(functions->length() == 0); 729 Code* code_pointer = LookupCode(); 730 int offset = static_cast<int>(pc() - code_pointer->address()); 731 FrameSummary summary(receiver(), 732 JSFunction::cast(function()), 733 code_pointer, 734 offset, 735 IsConstructor()); 736 functions->Add(summary); 737} 738 739 740void JavaScriptFrame::PrintTop(FILE* file, 741 bool print_args, 742 bool print_line_number) { 743 // constructor calls 744 HandleScope scope; 745 AssertNoAllocation no_allocation; 746 JavaScriptFrameIterator it; 747 while (!it.done()) { 748 if (it.frame()->is_java_script()) { 749 JavaScriptFrame* frame = it.frame(); 750 if (frame->IsConstructor()) PrintF(file, "new "); 751 // function name 752 Object* maybe_fun = frame->function(); 753 if (maybe_fun->IsJSFunction()) { 754 JSFunction* fun = JSFunction::cast(maybe_fun); 755 fun->PrintName(); 756 Code* js_code = frame->unchecked_code(); 757 Address pc = frame->pc(); 758 int code_offset = 759 static_cast<int>(pc - js_code->instruction_start()); 760 PrintF("+%d", code_offset); 761 SharedFunctionInfo* shared = fun->shared(); 762 if (print_line_number) { 763 Code* code = Code::cast( 764 v8::internal::Isolate::Current()->heap()->FindCodeObject(pc)); 765 int source_pos = code->SourcePosition(pc); 766 Object* maybe_script = shared->script(); 767 if (maybe_script->IsScript()) { 768 Handle<Script> script(Script::cast(maybe_script)); 769 int line = GetScriptLineNumberSafe(script, source_pos) + 1; 770 Object* script_name_raw = script->name(); 771 if (script_name_raw->IsString()) { 772 String* script_name = String::cast(script->name()); 773 SmartArrayPointer<char> c_script_name = 774 script_name->ToCString(DISALLOW_NULLS, 775 ROBUST_STRING_TRAVERSAL); 776 PrintF(file, " at %s:%d", *c_script_name, line); 777 } else { 778 PrintF(file, "at <unknown>:%d", line); 779 } 780 } else { 781 PrintF(file, " at <unknown>:<unknown>"); 782 } 783 } 784 } else { 785 PrintF("<unknown>"); 786 } 787 788 if (print_args) { 789 // function arguments 790 // (we are intentionally only printing the actually 791 // supplied parameters, not all parameters required) 792 PrintF(file, "(this="); 793 frame->receiver()->ShortPrint(file); 794 const int length = frame->ComputeParametersCount(); 795 for (int i = 0; i < length; i++) { 796 PrintF(file, ", "); 797 frame->GetParameter(i)->ShortPrint(file); 798 } 799 PrintF(file, ")"); 800 } 801 break; 802 } 803 it.Advance(); 804 } 805} 806 807 808void FrameSummary::Print() { 809 PrintF("receiver: "); 810 receiver_->ShortPrint(); 811 PrintF("\nfunction: "); 812 function_->shared()->DebugName()->ShortPrint(); 813 PrintF("\ncode: "); 814 code_->ShortPrint(); 815 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT"); 816 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT"); 817 PrintF("\npc: %d\n", offset_); 818} 819 820 821void OptimizedFrame::Summarize(List<FrameSummary>* frames) { 822 ASSERT(frames->length() == 0); 823 ASSERT(is_optimized()); 824 825 int deopt_index = Safepoint::kNoDeoptimizationIndex; 826 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); 827 828 // BUG(3243555): Since we don't have a lazy-deopt registered at 829 // throw-statements, we can't use the translation at the call-site of 830 // throw. An entry with no deoptimization index indicates a call-site 831 // without a lazy-deopt. As a consequence we are not allowed to inline 832 // functions containing throw. 833 if (deopt_index == Safepoint::kNoDeoptimizationIndex) { 834 JavaScriptFrame::Summarize(frames); 835 return; 836 } 837 838 TranslationIterator it(data->TranslationByteArray(), 839 data->TranslationIndex(deopt_index)->value()); 840 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); 841 ASSERT(opcode == Translation::BEGIN); 842 it.Next(); // Drop frame count. 843 int jsframe_count = it.Next(); 844 845 // We create the summary in reverse order because the frames 846 // in the deoptimization translation are ordered bottom-to-top. 847 bool is_constructor = IsConstructor(); 848 int i = jsframe_count; 849 while (i > 0) { 850 opcode = static_cast<Translation::Opcode>(it.Next()); 851 if (opcode == Translation::JS_FRAME) { 852 i--; 853 int ast_id = it.Next(); 854 int function_id = it.Next(); 855 it.Next(); // Skip height. 856 JSFunction* function = 857 JSFunction::cast(data->LiteralArray()->get(function_id)); 858 859 // The translation commands are ordered and the receiver is always 860 // at the first position. Since we are always at a call when we need 861 // to construct a stack trace, the receiver is always in a stack slot. 862 opcode = static_cast<Translation::Opcode>(it.Next()); 863 ASSERT(opcode == Translation::STACK_SLOT || 864 opcode == Translation::LITERAL); 865 int index = it.Next(); 866 867 // Get the correct receiver in the optimized frame. 868 Object* receiver = NULL; 869 if (opcode == Translation::LITERAL) { 870 receiver = data->LiteralArray()->get(index); 871 } else { 872 // Positive index means the value is spilled to the locals 873 // area. Negative means it is stored in the incoming parameter 874 // area. 875 if (index >= 0) { 876 receiver = GetExpression(index); 877 } else { 878 // Index -1 overlaps with last parameter, -n with the first parameter, 879 // (-n - 1) with the receiver with n being the number of parameters 880 // of the outermost, optimized frame. 881 int parameter_count = ComputeParametersCount(); 882 int parameter_index = index + parameter_count; 883 receiver = (parameter_index == -1) 884 ? this->receiver() 885 : this->GetParameter(parameter_index); 886 } 887 } 888 889 Code* code = function->shared()->code(); 890 DeoptimizationOutputData* output_data = 891 DeoptimizationOutputData::cast(code->deoptimization_data()); 892 unsigned entry = Deoptimizer::GetOutputInfo(output_data, 893 ast_id, 894 function->shared()); 895 unsigned pc_offset = 896 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize; 897 ASSERT(pc_offset > 0); 898 899 FrameSummary summary(receiver, function, code, pc_offset, is_constructor); 900 frames->Add(summary); 901 is_constructor = false; 902 } else if (opcode == Translation::CONSTRUCT_STUB_FRAME) { 903 // The next encountered JS_FRAME will be marked as a constructor call. 904 it.Skip(Translation::NumberOfOperandsFor(opcode)); 905 ASSERT(!is_constructor); 906 is_constructor = true; 907 } else { 908 // Skip over operands to advance to the next opcode. 909 it.Skip(Translation::NumberOfOperandsFor(opcode)); 910 } 911 } 912 ASSERT(!is_constructor); 913} 914 915 916DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData( 917 int* deopt_index) { 918 ASSERT(is_optimized()); 919 920 JSFunction* opt_function = JSFunction::cast(function()); 921 Code* code = opt_function->code(); 922 923 // The code object may have been replaced by lazy deoptimization. Fall 924 // back to a slow search in this case to find the original optimized 925 // code object. 926 if (!code->contains(pc())) { 927 code = isolate()->inner_pointer_to_code_cache()-> 928 GcSafeFindCodeForInnerPointer(pc()); 929 } 930 ASSERT(code != NULL); 931 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); 932 933 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc()); 934 *deopt_index = safepoint_entry.deoptimization_index(); 935 ASSERT(*deopt_index != Safepoint::kNoDeoptimizationIndex); 936 937 return DeoptimizationInputData::cast(code->deoptimization_data()); 938} 939 940 941int OptimizedFrame::GetInlineCount() { 942 ASSERT(is_optimized()); 943 944 int deopt_index = Safepoint::kNoDeoptimizationIndex; 945 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); 946 947 TranslationIterator it(data->TranslationByteArray(), 948 data->TranslationIndex(deopt_index)->value()); 949 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); 950 ASSERT(opcode == Translation::BEGIN); 951 USE(opcode); 952 it.Next(); // Drop frame count. 953 int jsframe_count = it.Next(); 954 return jsframe_count; 955} 956 957 958void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) { 959 ASSERT(functions->length() == 0); 960 ASSERT(is_optimized()); 961 962 int deopt_index = Safepoint::kNoDeoptimizationIndex; 963 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); 964 965 TranslationIterator it(data->TranslationByteArray(), 966 data->TranslationIndex(deopt_index)->value()); 967 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); 968 ASSERT(opcode == Translation::BEGIN); 969 it.Next(); // Drop frame count. 970 int jsframe_count = it.Next(); 971 972 // We insert the frames in reverse order because the frames 973 // in the deoptimization translation are ordered bottom-to-top. 974 while (jsframe_count > 0) { 975 opcode = static_cast<Translation::Opcode>(it.Next()); 976 if (opcode == Translation::JS_FRAME) { 977 jsframe_count--; 978 it.Next(); // Skip ast id. 979 int function_id = it.Next(); 980 it.Next(); // Skip height. 981 JSFunction* function = 982 JSFunction::cast(data->LiteralArray()->get(function_id)); 983 functions->Add(function); 984 } else { 985 // Skip over operands to advance to the next opcode. 986 it.Skip(Translation::NumberOfOperandsFor(opcode)); 987 } 988 } 989} 990 991 992int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const { 993 return Smi::cast(GetExpression(0))->value(); 994} 995 996 997Address ArgumentsAdaptorFrame::GetCallerStackPointer() const { 998 return fp() + StandardFrameConstants::kCallerSPOffset; 999} 1000 1001 1002Address InternalFrame::GetCallerStackPointer() const { 1003 // Internal frames have no arguments. The stack pointer of the 1004 // caller is at a fixed offset from the frame pointer. 1005 return fp() + StandardFrameConstants::kCallerSPOffset; 1006} 1007 1008 1009Code* ArgumentsAdaptorFrame::unchecked_code() const { 1010 return isolate()->builtins()->builtin( 1011 Builtins::kArgumentsAdaptorTrampoline); 1012} 1013 1014 1015Code* InternalFrame::unchecked_code() const { 1016 const int offset = InternalFrameConstants::kCodeOffset; 1017 Object* code = Memory::Object_at(fp() + offset); 1018 ASSERT(code != NULL); 1019 return reinterpret_cast<Code*>(code); 1020} 1021 1022 1023void StackFrame::PrintIndex(StringStream* accumulator, 1024 PrintMode mode, 1025 int index) { 1026 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index); 1027} 1028 1029 1030void JavaScriptFrame::Print(StringStream* accumulator, 1031 PrintMode mode, 1032 int index) const { 1033 HandleScope scope; 1034 Object* receiver = this->receiver(); 1035 Object* function = this->function(); 1036 1037 accumulator->PrintSecurityTokenIfChanged(function); 1038 PrintIndex(accumulator, mode, index); 1039 Code* code = NULL; 1040 if (IsConstructor()) accumulator->Add("new "); 1041 accumulator->PrintFunction(function, receiver, &code); 1042 1043 // Get scope information for nicer output, if possible. If code is NULL, or 1044 // doesn't contain scope info, scope_info will return 0 for the number of 1045 // parameters, stack local variables, context local variables, stack slots, 1046 // or context slots. 1047 Handle<ScopeInfo> scope_info(ScopeInfo::Empty()); 1048 1049 if (function->IsJSFunction()) { 1050 Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared()); 1051 scope_info = Handle<ScopeInfo>(shared->scope_info()); 1052 Object* script_obj = shared->script(); 1053 if (script_obj->IsScript()) { 1054 Handle<Script> script(Script::cast(script_obj)); 1055 accumulator->Add(" ["); 1056 accumulator->PrintName(script->name()); 1057 1058 Address pc = this->pc(); 1059 if (code != NULL && code->kind() == Code::FUNCTION && 1060 pc >= code->instruction_start() && pc < code->instruction_end()) { 1061 int source_pos = code->SourcePosition(pc); 1062 int line = GetScriptLineNumberSafe(script, source_pos) + 1; 1063 accumulator->Add(":%d", line); 1064 } else { 1065 int function_start_pos = shared->start_position(); 1066 int line = GetScriptLineNumberSafe(script, function_start_pos) + 1; 1067 accumulator->Add(":~%d", line); 1068 } 1069 1070 accumulator->Add("] "); 1071 } 1072 } 1073 1074 accumulator->Add("(this=%o", receiver); 1075 1076 // Print the parameters. 1077 int parameters_count = ComputeParametersCount(); 1078 for (int i = 0; i < parameters_count; i++) { 1079 accumulator->Add(","); 1080 // If we have a name for the parameter we print it. Nameless 1081 // parameters are either because we have more actual parameters 1082 // than formal parameters or because we have no scope information. 1083 if (i < scope_info->ParameterCount()) { 1084 accumulator->PrintName(scope_info->ParameterName(i)); 1085 accumulator->Add("="); 1086 } 1087 accumulator->Add("%o", GetParameter(i)); 1088 } 1089 1090 accumulator->Add(")"); 1091 if (mode == OVERVIEW) { 1092 accumulator->Add("\n"); 1093 return; 1094 } 1095 if (is_optimized()) { 1096 accumulator->Add(" {\n// optimized frame\n}\n"); 1097 return; 1098 } 1099 accumulator->Add(" {\n"); 1100 1101 // Compute the number of locals and expression stack elements. 1102 int stack_locals_count = scope_info->StackLocalCount(); 1103 int heap_locals_count = scope_info->ContextLocalCount(); 1104 int expressions_count = ComputeExpressionsCount(); 1105 1106 // Print stack-allocated local variables. 1107 if (stack_locals_count > 0) { 1108 accumulator->Add(" // stack-allocated locals\n"); 1109 } 1110 for (int i = 0; i < stack_locals_count; i++) { 1111 accumulator->Add(" var "); 1112 accumulator->PrintName(scope_info->StackLocalName(i)); 1113 accumulator->Add(" = "); 1114 if (i < expressions_count) { 1115 accumulator->Add("%o", GetExpression(i)); 1116 } else { 1117 accumulator->Add("// no expression found - inconsistent frame?"); 1118 } 1119 accumulator->Add("\n"); 1120 } 1121 1122 // Try to get hold of the context of this frame. 1123 Context* context = NULL; 1124 if (this->context() != NULL && this->context()->IsContext()) { 1125 context = Context::cast(this->context()); 1126 } 1127 1128 // Print heap-allocated local variables. 1129 if (heap_locals_count > 0) { 1130 accumulator->Add(" // heap-allocated locals\n"); 1131 } 1132 for (int i = 0; i < heap_locals_count; i++) { 1133 accumulator->Add(" var "); 1134 accumulator->PrintName(scope_info->ContextLocalName(i)); 1135 accumulator->Add(" = "); 1136 if (context != NULL) { 1137 if (i < context->length()) { 1138 accumulator->Add("%o", context->get(Context::MIN_CONTEXT_SLOTS + i)); 1139 } else { 1140 accumulator->Add( 1141 "// warning: missing context slot - inconsistent frame?"); 1142 } 1143 } else { 1144 accumulator->Add("// warning: no context found - inconsistent frame?"); 1145 } 1146 accumulator->Add("\n"); 1147 } 1148 1149 // Print the expression stack. 1150 int expressions_start = stack_locals_count; 1151 if (expressions_start < expressions_count) { 1152 accumulator->Add(" // expression stack (top to bottom)\n"); 1153 } 1154 for (int i = expressions_count - 1; i >= expressions_start; i--) { 1155 if (IsExpressionInsideHandler(i)) continue; 1156 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i)); 1157 } 1158 1159 // Print details about the function. 1160 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) { 1161 SharedFunctionInfo* shared = JSFunction::cast(function)->shared(); 1162 accumulator->Add("--------- s o u r c e c o d e ---------\n"); 1163 shared->SourceCodePrint(accumulator, FLAG_max_stack_trace_source_length); 1164 accumulator->Add("\n-----------------------------------------\n"); 1165 } 1166 1167 accumulator->Add("}\n\n"); 1168} 1169 1170 1171void ArgumentsAdaptorFrame::Print(StringStream* accumulator, 1172 PrintMode mode, 1173 int index) const { 1174 int actual = ComputeParametersCount(); 1175 int expected = -1; 1176 Object* function = this->function(); 1177 if (function->IsJSFunction()) { 1178 expected = JSFunction::cast(function)->shared()->formal_parameter_count(); 1179 } 1180 1181 PrintIndex(accumulator, mode, index); 1182 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected); 1183 if (mode == OVERVIEW) { 1184 accumulator->Add("\n"); 1185 return; 1186 } 1187 accumulator->Add(" {\n"); 1188 1189 // Print actual arguments. 1190 if (actual > 0) accumulator->Add(" // actual arguments\n"); 1191 for (int i = 0; i < actual; i++) { 1192 accumulator->Add(" [%02d] : %o", i, GetParameter(i)); 1193 if (expected != -1 && i >= expected) { 1194 accumulator->Add(" // not passed to callee"); 1195 } 1196 accumulator->Add("\n"); 1197 } 1198 1199 accumulator->Add("}\n\n"); 1200} 1201 1202 1203void EntryFrame::Iterate(ObjectVisitor* v) const { 1204 StackHandlerIterator it(this, top_handler()); 1205 ASSERT(!it.done()); 1206 StackHandler* handler = it.handler(); 1207 ASSERT(handler->is_js_entry()); 1208 handler->Iterate(v, LookupCode()); 1209#ifdef DEBUG 1210 // Make sure that the entry frame does not contain more than one 1211 // stack handler. 1212 it.Advance(); 1213 ASSERT(it.done()); 1214#endif 1215 IteratePc(v, pc_address(), LookupCode()); 1216} 1217 1218 1219void StandardFrame::IterateExpressions(ObjectVisitor* v) const { 1220 const int offset = StandardFrameConstants::kContextOffset; 1221 Object** base = &Memory::Object_at(sp()); 1222 Object** limit = &Memory::Object_at(fp() + offset) + 1; 1223 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { 1224 StackHandler* handler = it.handler(); 1225 // Traverse pointers down to - but not including - the next 1226 // handler in the handler chain. Update the base to skip the 1227 // handler and allow the handler to traverse its own pointers. 1228 const Address address = handler->address(); 1229 v->VisitPointers(base, reinterpret_cast<Object**>(address)); 1230 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize); 1231 // Traverse the pointers in the handler itself. 1232 handler->Iterate(v, LookupCode()); 1233 } 1234 v->VisitPointers(base, limit); 1235} 1236 1237 1238void JavaScriptFrame::Iterate(ObjectVisitor* v) const { 1239 IterateExpressions(v); 1240 IteratePc(v, pc_address(), LookupCode()); 1241} 1242 1243 1244void InternalFrame::Iterate(ObjectVisitor* v) const { 1245 // Internal frames only have object pointers on the expression stack 1246 // as they never have any arguments. 1247 IterateExpressions(v); 1248 IteratePc(v, pc_address(), LookupCode()); 1249} 1250 1251 1252// ------------------------------------------------------------------------- 1253 1254 1255JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) { 1256 ASSERT(n >= 0); 1257 for (int i = 0; i <= n; i++) { 1258 while (!iterator_.frame()->is_java_script()) iterator_.Advance(); 1259 if (i == n) return JavaScriptFrame::cast(iterator_.frame()); 1260 iterator_.Advance(); 1261 } 1262 UNREACHABLE(); 1263 return NULL; 1264} 1265 1266 1267// ------------------------------------------------------------------------- 1268 1269 1270static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) { 1271 MapWord map_word = object->map_word(); 1272 return map_word.IsForwardingAddress() ? 1273 map_word.ToForwardingAddress()->map() : map_word.ToMap(); 1274} 1275 1276 1277static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) { 1278 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object)); 1279} 1280 1281 1282#ifdef DEBUG 1283static bool GcSafeCodeContains(HeapObject* code, Address addr) { 1284 Map* map = GcSafeMapOfCodeSpaceObject(code); 1285 ASSERT(map == code->GetHeap()->code_map()); 1286 Address start = code->address(); 1287 Address end = code->address() + code->SizeFromMap(map); 1288 return start <= addr && addr < end; 1289} 1290#endif 1291 1292 1293Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object, 1294 Address inner_pointer) { 1295 Code* code = reinterpret_cast<Code*>(object); 1296 ASSERT(code != NULL && GcSafeCodeContains(code, inner_pointer)); 1297 return code; 1298} 1299 1300 1301Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer( 1302 Address inner_pointer) { 1303 Heap* heap = isolate_->heap(); 1304 // Check if the inner pointer points into a large object chunk. 1305 LargePage* large_page = heap->lo_space()->FindPage(inner_pointer); 1306 if (large_page != NULL) { 1307 return GcSafeCastToCode(large_page->GetObject(), inner_pointer); 1308 } 1309 1310 // Iterate through the page until we reach the end or find an object starting 1311 // after the inner pointer. 1312 Page* page = Page::FromAddress(inner_pointer); 1313 1314 Address addr = page->skip_list()->StartFor(inner_pointer); 1315 1316 Address top = heap->code_space()->top(); 1317 Address limit = heap->code_space()->limit(); 1318 1319 while (true) { 1320 if (addr == top && addr != limit) { 1321 addr = limit; 1322 continue; 1323 } 1324 1325 HeapObject* obj = HeapObject::FromAddress(addr); 1326 int obj_size = GcSafeSizeOfCodeSpaceObject(obj); 1327 Address next_addr = addr + obj_size; 1328 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer); 1329 addr = next_addr; 1330 } 1331} 1332 1333 1334InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* 1335 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) { 1336 isolate_->counters()->pc_to_code()->Increment(); 1337 ASSERT(IsPowerOf2(kInnerPointerToCodeCacheSize)); 1338 uint32_t hash = ComputeIntegerHash( 1339 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)), 1340 v8::internal::kZeroHashSeed); 1341 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1); 1342 InnerPointerToCodeCacheEntry* entry = cache(index); 1343 if (entry->inner_pointer == inner_pointer) { 1344 isolate_->counters()->pc_to_code_cached()->Increment(); 1345 ASSERT(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer)); 1346 } else { 1347 // Because this code may be interrupted by a profiling signal that 1348 // also queries the cache, we cannot update inner_pointer before the code 1349 // has been set. Otherwise, we risk trying to use a cache entry before 1350 // the code has been computed. 1351 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer); 1352 entry->safepoint_entry.Reset(); 1353 entry->inner_pointer = inner_pointer; 1354 } 1355 return entry; 1356} 1357 1358 1359// ------------------------------------------------------------------------- 1360 1361int NumRegs(RegList reglist) { 1362 int n = 0; 1363 while (reglist != 0) { 1364 n++; 1365 reglist &= reglist - 1; // clear one bit 1366 } 1367 return n; 1368} 1369 1370 1371struct JSCallerSavedCodeData { 1372 JSCallerSavedCodeData() { 1373 int i = 0; 1374 for (int r = 0; r < kNumRegs; r++) 1375 if ((kJSCallerSaved & (1 << r)) != 0) 1376 reg_code[i++] = r; 1377 1378 ASSERT(i == kNumJSCallerSaved); 1379 } 1380 int reg_code[kNumJSCallerSaved]; 1381}; 1382 1383 1384static LazyInstance<JSCallerSavedCodeData>::type caller_saved_code_data = 1385 LAZY_INSTANCE_INITIALIZER; 1386 1387int JSCallerSavedCode(int n) { 1388 ASSERT(0 <= n && n < kNumJSCallerSaved); 1389 return caller_saved_code_data.Get().reg_code[n]; 1390} 1391 1392 1393#define DEFINE_WRAPPER(type, field) \ 1394class field##_Wrapper : public ZoneObject { \ 1395 public: /* NOLINT */ \ 1396 field##_Wrapper(const field& original) : frame_(original) { \ 1397 } \ 1398 field frame_; \ 1399}; 1400STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER) 1401#undef DEFINE_WRAPPER 1402 1403static StackFrame* AllocateFrameCopy(StackFrame* frame) { 1404#define FRAME_TYPE_CASE(type, field) \ 1405 case StackFrame::type: { \ 1406 field##_Wrapper* wrapper = \ 1407 new field##_Wrapper(*(reinterpret_cast<field*>(frame))); \ 1408 return &wrapper->frame_; \ 1409 } 1410 1411 switch (frame->type()) { 1412 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE) 1413 default: UNREACHABLE(); 1414 } 1415#undef FRAME_TYPE_CASE 1416 return NULL; 1417} 1418 1419Vector<StackFrame*> CreateStackMap() { 1420 ZoneList<StackFrame*> list(10); 1421 for (StackFrameIterator it; !it.done(); it.Advance()) { 1422 StackFrame* frame = AllocateFrameCopy(it.frame()); 1423 list.Add(frame); 1424 } 1425 return list.ToVector(); 1426} 1427 1428 1429} } // namespace v8::internal 1430