| 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 17 matching lines...) Expand all Loading... |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "ast.h" | 30 #include "ast.h" |
| 31 #include "deoptimizer.h" | 31 #include "deoptimizer.h" |
| 32 #include "frames-inl.h" | 32 #include "frames-inl.h" |
| 33 #include "full-codegen.h" | 33 #include "full-codegen.h" |
| 34 #include "mark-compact.h" | 34 #include "mark-compact.h" |
| 35 #include "safepoint-table.h" | 35 #include "safepoint-table.h" |
| 36 #include "scopeinfo.h" | 36 #include "scopeinfo.h" |
| 37 #include "string-stream.h" | 37 #include "string-stream.h" |
| 38 #include "top.h" | |
| 39 | 38 |
| 40 namespace v8 { | 39 namespace v8 { |
| 41 namespace internal { | 40 namespace internal { |
| 42 | 41 |
| 43 PcToCodeCache::PcToCodeCacheEntry | |
| 44 PcToCodeCache::cache_[PcToCodeCache::kPcToCodeCacheSize]; | |
| 45 | 42 |
| 46 int SafeStackFrameIterator::active_count_ = 0; | 43 int SafeStackFrameIterator::active_count_ = 0; |
| 47 | 44 |
| 48 // Iterator that supports traversing the stack handlers of a | 45 // Iterator that supports traversing the stack handlers of a |
| 49 // particular frame. Needs to know the top of the handler chain. | 46 // particular frame. Needs to know the top of the handler chain. |
| 50 class StackHandlerIterator BASE_EMBEDDED { | 47 class StackHandlerIterator BASE_EMBEDDED { |
| 51 public: | 48 public: |
| 52 StackHandlerIterator(const StackFrame* frame, StackHandler* handler) | 49 StackHandlerIterator(const StackFrame* frame, StackHandler* handler) |
| 53 : limit_(frame->fp()), handler_(handler) { | 50 : limit_(frame->fp()), handler_(handler) { |
| 54 // Make sure the handler has already been unwound to this frame. | 51 // Make sure the handler has already been unwound to this frame. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 70 StackHandler* handler_; | 67 StackHandler* handler_; |
| 71 }; | 68 }; |
| 72 | 69 |
| 73 | 70 |
| 74 // ------------------------------------------------------------------------- | 71 // ------------------------------------------------------------------------- |
| 75 | 72 |
| 76 | 73 |
| 77 #define INITIALIZE_SINGLETON(type, field) field##_(this), | 74 #define INITIALIZE_SINGLETON(type, field) field##_(this), |
| 78 StackFrameIterator::StackFrameIterator() | 75 StackFrameIterator::StackFrameIterator() |
| 79 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | 76 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) |
| 80 frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()), | 77 frame_(NULL), handler_(NULL), |
| 78 thread_(Isolate::Current()->thread_local_top()), |
| 81 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) { | 79 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) { |
| 82 Reset(); | 80 Reset(); |
| 83 } | 81 } |
| 84 StackFrameIterator::StackFrameIterator(ThreadLocalTop* t) | 82 StackFrameIterator::StackFrameIterator(ThreadLocalTop* t) |
| 85 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | 83 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) |
| 86 frame_(NULL), handler_(NULL), thread_(t), | 84 frame_(NULL), handler_(NULL), thread_(t), |
| 87 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) { | 85 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) { |
| 88 Reset(); | 86 Reset(); |
| 89 } | 87 } |
| 90 StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp) | 88 StackFrameIterator::StackFrameIterator(Isolate* isolate, |
| 89 bool use_top, Address fp, Address sp) |
| 91 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | 90 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) |
| 92 frame_(NULL), handler_(NULL), | 91 frame_(NULL), handler_(NULL), |
| 93 thread_(use_top ? Top::GetCurrentThread() : NULL), | 92 thread_(use_top ? isolate->thread_local_top() : NULL), |
| 94 fp_(use_top ? NULL : fp), sp_(sp), | 93 fp_(use_top ? NULL : fp), sp_(sp), |
| 95 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler : | 94 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler : |
| 96 &StackFrameIterator::AdvanceWithoutHandler) { | 95 &StackFrameIterator::AdvanceWithoutHandler) { |
| 97 if (use_top || fp != NULL) { | 96 if (use_top || fp != NULL) { |
| 98 Reset(); | 97 Reset(); |
| 99 } | 98 } |
| 100 } | 99 } |
| 101 | 100 |
| 102 #undef INITIALIZE_SINGLETON | 101 #undef INITIALIZE_SINGLETON |
| 103 | 102 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 131 StackFrame::State state; | 130 StackFrame::State state; |
| 132 StackFrame::Type type = frame_->GetCallerState(&state); | 131 StackFrame::Type type = frame_->GetCallerState(&state); |
| 133 frame_ = SingletonFor(type, &state); | 132 frame_ = SingletonFor(type, &state); |
| 134 } | 133 } |
| 135 | 134 |
| 136 | 135 |
| 137 void StackFrameIterator::Reset() { | 136 void StackFrameIterator::Reset() { |
| 138 StackFrame::State state; | 137 StackFrame::State state; |
| 139 StackFrame::Type type; | 138 StackFrame::Type type; |
| 140 if (thread_ != NULL) { | 139 if (thread_ != NULL) { |
| 141 type = ExitFrame::GetStateForFramePointer(Top::c_entry_fp(thread_), &state); | 140 type = ExitFrame::GetStateForFramePointer( |
| 142 handler_ = StackHandler::FromAddress(Top::handler(thread_)); | 141 Isolate::c_entry_fp(thread_), &state); |
| 142 handler_ = StackHandler::FromAddress( |
| 143 Isolate::handler(thread_)); |
| 143 } else { | 144 } else { |
| 144 ASSERT(fp_ != NULL); | 145 ASSERT(fp_ != NULL); |
| 145 state.fp = fp_; | 146 state.fp = fp_; |
| 146 state.sp = sp_; | 147 state.sp = sp_; |
| 147 state.pc_address = | 148 state.pc_address = |
| 148 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_)); | 149 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_)); |
| 149 type = StackFrame::ComputeType(&state); | 150 type = StackFrame::ComputeType(&state); |
| 150 } | 151 } |
| 151 if (SingletonFor(type) == NULL) return; | 152 if (SingletonFor(type) == NULL) return; |
| 152 frame_ = SingletonFor(type, &state); | 153 frame_ = SingletonFor(type, &state); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 StackFrame::State state; | 215 StackFrame::State state; |
| 215 ExitFrame::FillState(fp, sp, &state); | 216 ExitFrame::FillState(fp, sp, &state); |
| 216 if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) { | 217 if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) { |
| 217 return false; | 218 return false; |
| 218 } | 219 } |
| 219 return *state.pc_address != NULL; | 220 return *state.pc_address != NULL; |
| 220 } | 221 } |
| 221 | 222 |
| 222 | 223 |
| 223 SafeStackFrameIterator::SafeStackFrameIterator( | 224 SafeStackFrameIterator::SafeStackFrameIterator( |
| 225 Isolate* isolate, |
| 224 Address fp, Address sp, Address low_bound, Address high_bound) : | 226 Address fp, Address sp, Address low_bound, Address high_bound) : |
| 225 maintainer_(), | 227 maintainer_(), |
| 226 stack_validator_(low_bound, high_bound), | 228 stack_validator_(low_bound, high_bound), |
| 227 is_valid_top_(IsValidTop(low_bound, high_bound)), | 229 is_valid_top_(IsValidTop(isolate, low_bound, high_bound)), |
| 228 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)), | 230 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)), |
| 229 is_working_iterator_(is_valid_top_ || is_valid_fp_), | 231 is_working_iterator_(is_valid_top_ || is_valid_fp_), |
| 230 iteration_done_(!is_working_iterator_), | 232 iteration_done_(!is_working_iterator_), |
| 231 iterator_(is_valid_top_, is_valid_fp_ ? fp : NULL, sp) { | 233 iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) { |
| 232 } | 234 } |
| 233 | 235 |
| 234 | 236 |
| 235 bool SafeStackFrameIterator::IsValidTop(Address low_bound, Address high_bound) { | 237 bool SafeStackFrameIterator::IsValidTop(Isolate* isolate, |
| 236 Address fp = Top::c_entry_fp(Top::GetCurrentThread()); | 238 Address low_bound, Address high_bound) { |
| 239 ThreadLocalTop* top = isolate->thread_local_top(); |
| 240 Address fp = Isolate::c_entry_fp(top); |
| 237 ExitFrameValidator validator(low_bound, high_bound); | 241 ExitFrameValidator validator(low_bound, high_bound); |
| 238 if (!validator.IsValidFP(fp)) return false; | 242 if (!validator.IsValidFP(fp)) return false; |
| 239 return Top::handler(Top::GetCurrentThread()) != NULL; | 243 return Isolate::handler(top) != NULL; |
| 240 } | 244 } |
| 241 | 245 |
| 242 | 246 |
| 243 void SafeStackFrameIterator::Advance() { | 247 void SafeStackFrameIterator::Advance() { |
| 244 ASSERT(is_working_iterator_); | 248 ASSERT(is_working_iterator_); |
| 245 ASSERT(!done()); | 249 ASSERT(!done()); |
| 246 StackFrame* last_frame = iterator_.frame(); | 250 StackFrame* last_frame = iterator_.frame(); |
| 247 Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); | 251 Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); |
| 248 // Before advancing to the next stack frame, perform pointer validity tests | 252 // Before advancing to the next stack frame, perform pointer validity tests |
| 249 iteration_done_ = !IsValidFrame(last_frame) || | 253 iteration_done_ = !IsValidFrame(last_frame) || |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 iteration_done_ = false; | 309 iteration_done_ = false; |
| 306 } | 310 } |
| 307 } | 311 } |
| 308 | 312 |
| 309 | 313 |
| 310 // ------------------------------------------------------------------------- | 314 // ------------------------------------------------------------------------- |
| 311 | 315 |
| 312 | 316 |
| 313 #ifdef ENABLE_LOGGING_AND_PROFILING | 317 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 314 SafeStackTraceFrameIterator::SafeStackTraceFrameIterator( | 318 SafeStackTraceFrameIterator::SafeStackTraceFrameIterator( |
| 319 Isolate* isolate, |
| 315 Address fp, Address sp, Address low_bound, Address high_bound) : | 320 Address fp, Address sp, Address low_bound, Address high_bound) : |
| 316 SafeJavaScriptFrameIterator(fp, sp, low_bound, high_bound) { | 321 SafeJavaScriptFrameIterator(isolate, fp, sp, low_bound, high_bound) { |
| 317 if (!done() && !frame()->is_java_script()) Advance(); | 322 if (!done() && !frame()->is_java_script()) Advance(); |
| 318 } | 323 } |
| 319 | 324 |
| 320 | 325 |
| 321 void SafeStackTraceFrameIterator::Advance() { | 326 void SafeStackTraceFrameIterator::Advance() { |
| 322 while (true) { | 327 while (true) { |
| 323 SafeJavaScriptFrameIterator::Advance(); | 328 SafeJavaScriptFrameIterator::Advance(); |
| 324 if (done()) return; | 329 if (done()) return; |
| 325 if (frame()->is_java_script()) return; | 330 if (frame()->is_java_script()) return; |
| 326 } | 331 } |
| 327 } | 332 } |
| 328 #endif | 333 #endif |
| 329 | 334 |
| 330 | 335 |
| 331 Code* StackFrame::GetSafepointData(Address pc, | 336 Code* StackFrame::GetSafepointData(Address pc, |
| 332 SafepointEntry* safepoint_entry, | 337 SafepointEntry* safepoint_entry, |
| 333 unsigned* stack_slots) { | 338 unsigned* stack_slots) { |
| 334 PcToCodeCache::PcToCodeCacheEntry* entry = PcToCodeCache::GetCacheEntry(pc); | 339 Isolate* isolate = Isolate::Current(); |
| 340 PcToCodeCache::PcToCodeCacheEntry* entry = |
| 341 isolate->pc_to_code_cache()->GetCacheEntry(pc); |
| 335 SafepointEntry cached_safepoint_entry = entry->safepoint_entry; | 342 SafepointEntry cached_safepoint_entry = entry->safepoint_entry; |
| 336 if (!entry->safepoint_entry.is_valid()) { | 343 if (!entry->safepoint_entry.is_valid()) { |
| 337 entry->safepoint_entry = entry->code->GetSafepointEntry(pc); | 344 entry->safepoint_entry = entry->code->GetSafepointEntry(pc); |
| 338 ASSERT(entry->safepoint_entry.is_valid()); | 345 ASSERT(entry->safepoint_entry.is_valid()); |
| 339 } else { | 346 } else { |
| 340 ASSERT(entry->safepoint_entry.Equals(entry->code->GetSafepointEntry(pc))); | 347 ASSERT(entry->safepoint_entry.Equals(entry->code->GetSafepointEntry(pc))); |
| 341 } | 348 } |
| 342 | 349 |
| 343 // Fill in the results and return the code. | 350 // Fill in the results and return the code. |
| 344 Code* code = entry->code; | 351 Code* code = entry->code; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 // smi then the frame is a JavaScript frame -- and the marker is | 386 // smi then the frame is a JavaScript frame -- and the marker is |
| 380 // really the function. | 387 // really the function. |
| 381 const int offset = StandardFrameConstants::kMarkerOffset; | 388 const int offset = StandardFrameConstants::kMarkerOffset; |
| 382 Object* marker = Memory::Object_at(state->fp + offset); | 389 Object* marker = Memory::Object_at(state->fp + offset); |
| 383 if (!marker->IsSmi()) { | 390 if (!marker->IsSmi()) { |
| 384 // If we're using a "safe" stack iterator, we treat optimized | 391 // If we're using a "safe" stack iterator, we treat optimized |
| 385 // frames as normal JavaScript frames to avoid having to look | 392 // frames as normal JavaScript frames to avoid having to look |
| 386 // into the heap to determine the state. This is safe as long | 393 // into the heap to determine the state. This is safe as long |
| 387 // as nobody tries to GC... | 394 // as nobody tries to GC... |
| 388 if (SafeStackFrameIterator::is_active()) return JAVA_SCRIPT; | 395 if (SafeStackFrameIterator::is_active()) return JAVA_SCRIPT; |
| 389 Code::Kind kind = GetContainingCode(*(state->pc_address))->kind(); | 396 Code::Kind kind = GetContainingCode(Isolate::Current(), |
| 397 *(state->pc_address))->kind(); |
| 390 ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION); | 398 ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION); |
| 391 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT; | 399 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT; |
| 392 } | 400 } |
| 393 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); | 401 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); |
| 394 } | 402 } |
| 395 | 403 |
| 396 | 404 |
| 397 | 405 |
| 398 StackFrame::Type StackFrame::GetCallerState(State* state) const { | 406 StackFrame::Type StackFrame::GetCallerState(State* state) const { |
| 399 ComputeCallerState(state); | 407 ComputeCallerState(state); |
| 400 return ComputeType(state); | 408 return ComputeType(state); |
| 401 } | 409 } |
| 402 | 410 |
| 403 | 411 |
| 404 Code* EntryFrame::unchecked_code() const { | 412 Code* EntryFrame::unchecked_code() const { |
| 405 return Heap::raw_unchecked_js_entry_code(); | 413 return HEAP->raw_unchecked_js_entry_code(); |
| 406 } | 414 } |
| 407 | 415 |
| 408 | 416 |
| 409 void EntryFrame::ComputeCallerState(State* state) const { | 417 void EntryFrame::ComputeCallerState(State* state) const { |
| 410 GetCallerState(state); | 418 GetCallerState(state); |
| 411 } | 419 } |
| 412 | 420 |
| 413 | 421 |
| 414 void EntryFrame::SetCallerFp(Address caller_fp) { | 422 void EntryFrame::SetCallerFp(Address caller_fp) { |
| 415 const int offset = EntryFrameConstants::kCallerFPOffset; | 423 const int offset = EntryFrameConstants::kCallerFPOffset; |
| 416 Memory::Address_at(this->fp() + offset) = caller_fp; | 424 Memory::Address_at(this->fp() + offset) = caller_fp; |
| 417 } | 425 } |
| 418 | 426 |
| 419 | 427 |
| 420 StackFrame::Type EntryFrame::GetCallerState(State* state) const { | 428 StackFrame::Type EntryFrame::GetCallerState(State* state) const { |
| 421 const int offset = EntryFrameConstants::kCallerFPOffset; | 429 const int offset = EntryFrameConstants::kCallerFPOffset; |
| 422 Address fp = Memory::Address_at(this->fp() + offset); | 430 Address fp = Memory::Address_at(this->fp() + offset); |
| 423 return ExitFrame::GetStateForFramePointer(fp, state); | 431 return ExitFrame::GetStateForFramePointer(fp, state); |
| 424 } | 432 } |
| 425 | 433 |
| 426 | 434 |
| 427 Code* EntryConstructFrame::unchecked_code() const { | 435 Code* EntryConstructFrame::unchecked_code() const { |
| 428 return Heap::raw_unchecked_js_construct_entry_code(); | 436 return HEAP->raw_unchecked_js_construct_entry_code(); |
| 429 } | 437 } |
| 430 | 438 |
| 431 | 439 |
| 432 Object*& ExitFrame::code_slot() const { | 440 Object*& ExitFrame::code_slot() const { |
| 433 const int offset = ExitFrameConstants::kCodeOffset; | 441 const int offset = ExitFrameConstants::kCodeOffset; |
| 434 return Memory::Object_at(fp() + offset); | 442 return Memory::Object_at(fp() + offset); |
| 435 } | 443 } |
| 436 | 444 |
| 437 | 445 |
| 438 Code* ExitFrame::unchecked_code() const { | 446 Code* ExitFrame::unchecked_code() const { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 450 | 458 |
| 451 | 459 |
| 452 void ExitFrame::SetCallerFp(Address caller_fp) { | 460 void ExitFrame::SetCallerFp(Address caller_fp) { |
| 453 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp; | 461 Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp; |
| 454 } | 462 } |
| 455 | 463 |
| 456 | 464 |
| 457 void ExitFrame::Iterate(ObjectVisitor* v) const { | 465 void ExitFrame::Iterate(ObjectVisitor* v) const { |
| 458 // The arguments are traversed as part of the expression stack of | 466 // The arguments are traversed as part of the expression stack of |
| 459 // the calling frame. | 467 // the calling frame. |
| 460 IteratePc(v, pc_address(), code()); | 468 IteratePc(v, pc_address(), LookupCode(Isolate::Current())); |
| 461 v->VisitPointer(&code_slot()); | 469 v->VisitPointer(&code_slot()); |
| 462 } | 470 } |
| 463 | 471 |
| 464 | 472 |
| 465 Address ExitFrame::GetCallerStackPointer() const { | 473 Address ExitFrame::GetCallerStackPointer() const { |
| 466 return fp() + ExitFrameConstants::kCallerSPDisplacement; | 474 return fp() + ExitFrameConstants::kCallerSPDisplacement; |
| 467 } | 475 } |
| 468 | 476 |
| 469 | 477 |
| 470 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { | 478 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 | 633 |
| 626 | 634 |
| 627 Code* JavaScriptFrame::unchecked_code() const { | 635 Code* JavaScriptFrame::unchecked_code() const { |
| 628 JSFunction* function = JSFunction::cast(this->function()); | 636 JSFunction* function = JSFunction::cast(this->function()); |
| 629 return function->unchecked_code(); | 637 return function->unchecked_code(); |
| 630 } | 638 } |
| 631 | 639 |
| 632 | 640 |
| 633 Address JavaScriptFrame::GetCallerStackPointer() const { | 641 Address JavaScriptFrame::GetCallerStackPointer() const { |
| 634 int arguments; | 642 int arguments; |
| 635 if (Heap::gc_state() != Heap::NOT_IN_GC || | 643 if (SafeStackFrameIterator::is_active() || |
| 636 SafeStackFrameIterator::is_active()) { | 644 HEAP->gc_state() != Heap::NOT_IN_GC) { |
| 637 // If the we are currently iterating the safe stack the | 645 // If the we are currently iterating the safe stack the |
| 638 // arguments for frames are traversed as if they were | 646 // arguments for frames are traversed as if they were |
| 639 // expression stack elements of the calling frame. The reason for | 647 // expression stack elements of the calling frame. The reason for |
| 640 // this rather strange decision is that we cannot access the | 648 // this rather strange decision is that we cannot access the |
| 641 // function during mark-compact GCs when objects may have been marked. | 649 // function during mark-compact GCs when objects may have been marked. |
| 642 // In fact accessing heap objects (like function->shared() below) | 650 // In fact accessing heap objects (like function->shared() below) |
| 643 // at all during GC is problematic. | 651 // at all during GC is problematic. |
| 644 arguments = 0; | 652 arguments = 0; |
| 645 } else { | 653 } else { |
| 646 // Compute the number of arguments by getting the number of formal | 654 // Compute the number of arguments by getting the number of formal |
| 647 // parameters of the function. We must remember to take the | 655 // parameters of the function. We must remember to take the |
| 648 // receiver into account (+1). | 656 // receiver into account (+1). |
| 649 JSFunction* function = JSFunction::cast(this->function()); | 657 JSFunction* function = JSFunction::cast(this->function()); |
| 650 arguments = function->shared()->formal_parameter_count() + 1; | 658 arguments = function->shared()->formal_parameter_count() + 1; |
| 651 } | 659 } |
| 652 const int offset = StandardFrameConstants::kCallerSPOffset; | 660 const int offset = StandardFrameConstants::kCallerSPOffset; |
| 653 return fp() + offset + (arguments * kPointerSize); | 661 return fp() + offset + (arguments * kPointerSize); |
| 654 } | 662 } |
| 655 | 663 |
| 656 | 664 |
| 657 void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) { | 665 void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) { |
| 658 ASSERT(functions->length() == 0); | 666 ASSERT(functions->length() == 0); |
| 659 functions->Add(JSFunction::cast(function())); | 667 functions->Add(JSFunction::cast(function())); |
| 660 } | 668 } |
| 661 | 669 |
| 662 | 670 |
| 663 void JavaScriptFrame::Summarize(List<FrameSummary>* functions) { | 671 void JavaScriptFrame::Summarize(List<FrameSummary>* functions) { |
| 664 ASSERT(functions->length() == 0); | 672 ASSERT(functions->length() == 0); |
| 665 Code* code_pointer = code(); | 673 Code* code_pointer = LookupCode(Isolate::Current()); |
| 666 int offset = static_cast<int>(pc() - code_pointer->address()); | 674 int offset = static_cast<int>(pc() - code_pointer->address()); |
| 667 FrameSummary summary(receiver(), | 675 FrameSummary summary(receiver(), |
| 668 JSFunction::cast(function()), | 676 JSFunction::cast(function()), |
| 669 code_pointer, | 677 code_pointer, |
| 670 offset, | 678 offset, |
| 671 IsConstructor()); | 679 IsConstructor()); |
| 672 functions->Add(summary); | 680 functions->Add(summary); |
| 673 } | 681 } |
| 674 | 682 |
| 675 | 683 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 int* deopt_index) { | 782 int* deopt_index) { |
| 775 ASSERT(is_optimized()); | 783 ASSERT(is_optimized()); |
| 776 | 784 |
| 777 JSFunction* opt_function = JSFunction::cast(function()); | 785 JSFunction* opt_function = JSFunction::cast(function()); |
| 778 Code* code = opt_function->code(); | 786 Code* code = opt_function->code(); |
| 779 | 787 |
| 780 // The code object may have been replaced by lazy deoptimization. Fall | 788 // The code object may have been replaced by lazy deoptimization. Fall |
| 781 // back to a slow search in this case to find the original optimized | 789 // back to a slow search in this case to find the original optimized |
| 782 // code object. | 790 // code object. |
| 783 if (!code->contains(pc())) { | 791 if (!code->contains(pc())) { |
| 784 code = PcToCodeCache::GcSafeFindCodeForPc(pc()); | 792 code = Isolate::Current()->pc_to_code_cache()->GcSafeFindCodeForPc(pc()); |
| 785 } | 793 } |
| 786 ASSERT(code != NULL); | 794 ASSERT(code != NULL); |
| 787 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); | 795 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); |
| 788 | 796 |
| 789 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc()); | 797 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc()); |
| 790 *deopt_index = safepoint_entry.deoptimization_index(); | 798 *deopt_index = safepoint_entry.deoptimization_index(); |
| 791 ASSERT(*deopt_index != Safepoint::kNoDeoptimizationIndex); | 799 ASSERT(*deopt_index != Safepoint::kNoDeoptimizationIndex); |
| 792 | 800 |
| 793 return DeoptimizationInputData::cast(code->deoptimization_data()); | 801 return DeoptimizationInputData::cast(code->deoptimization_data()); |
| 794 } | 802 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 | 843 |
| 836 | 844 |
| 837 Address InternalFrame::GetCallerStackPointer() const { | 845 Address InternalFrame::GetCallerStackPointer() const { |
| 838 // Internal frames have no arguments. The stack pointer of the | 846 // Internal frames have no arguments. The stack pointer of the |
| 839 // caller is at a fixed offset from the frame pointer. | 847 // caller is at a fixed offset from the frame pointer. |
| 840 return fp() + StandardFrameConstants::kCallerSPOffset; | 848 return fp() + StandardFrameConstants::kCallerSPOffset; |
| 841 } | 849 } |
| 842 | 850 |
| 843 | 851 |
| 844 Code* ArgumentsAdaptorFrame::unchecked_code() const { | 852 Code* ArgumentsAdaptorFrame::unchecked_code() const { |
| 845 return Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline); | 853 return Isolate::Current()->builtins()->builtin( |
| 854 Builtins::ArgumentsAdaptorTrampoline); |
| 846 } | 855 } |
| 847 | 856 |
| 848 | 857 |
| 849 Code* InternalFrame::unchecked_code() const { | 858 Code* InternalFrame::unchecked_code() const { |
| 850 const int offset = InternalFrameConstants::kCodeOffset; | 859 const int offset = InternalFrameConstants::kCodeOffset; |
| 851 Object* code = Memory::Object_at(fp() + offset); | 860 Object* code = Memory::Object_at(fp() + offset); |
| 852 ASSERT(code != NULL); | 861 ASSERT(code != NULL); |
| 853 return reinterpret_cast<Code*>(code); | 862 return reinterpret_cast<Code*>(code); |
| 854 } | 863 } |
| 855 | 864 |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1029 | 1038 |
| 1030 accumulator->Add("}\n\n"); | 1039 accumulator->Add("}\n\n"); |
| 1031 } | 1040 } |
| 1032 | 1041 |
| 1033 | 1042 |
| 1034 void EntryFrame::Iterate(ObjectVisitor* v) const { | 1043 void EntryFrame::Iterate(ObjectVisitor* v) const { |
| 1035 StackHandlerIterator it(this, top_handler()); | 1044 StackHandlerIterator it(this, top_handler()); |
| 1036 ASSERT(!it.done()); | 1045 ASSERT(!it.done()); |
| 1037 StackHandler* handler = it.handler(); | 1046 StackHandler* handler = it.handler(); |
| 1038 ASSERT(handler->is_entry()); | 1047 ASSERT(handler->is_entry()); |
| 1039 handler->Iterate(v, code()); | 1048 handler->Iterate(v, LookupCode(Isolate::Current())); |
| 1040 #ifdef DEBUG | 1049 #ifdef DEBUG |
| 1041 // Make sure that the entry frame does not contain more than one | 1050 // Make sure that the entry frame does not contain more than one |
| 1042 // stack handler. | 1051 // stack handler. |
| 1043 it.Advance(); | 1052 it.Advance(); |
| 1044 ASSERT(it.done()); | 1053 ASSERT(it.done()); |
| 1045 #endif | 1054 #endif |
| 1046 IteratePc(v, pc_address(), code()); | 1055 IteratePc(v, pc_address(), LookupCode(Isolate::Current())); |
| 1047 } | 1056 } |
| 1048 | 1057 |
| 1049 | 1058 |
| 1050 void StandardFrame::IterateExpressions(ObjectVisitor* v) const { | 1059 void StandardFrame::IterateExpressions(ObjectVisitor* v) const { |
| 1051 const int offset = StandardFrameConstants::kContextOffset; | 1060 const int offset = StandardFrameConstants::kContextOffset; |
| 1052 Object** base = &Memory::Object_at(sp()); | 1061 Object** base = &Memory::Object_at(sp()); |
| 1053 Object** limit = &Memory::Object_at(fp() + offset) + 1; | 1062 Object** limit = &Memory::Object_at(fp() + offset) + 1; |
| 1054 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | 1063 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { |
| 1055 StackHandler* handler = it.handler(); | 1064 StackHandler* handler = it.handler(); |
| 1056 // Traverse pointers down to - but not including - the next | 1065 // Traverse pointers down to - but not including - the next |
| 1057 // handler in the handler chain. Update the base to skip the | 1066 // handler in the handler chain. Update the base to skip the |
| 1058 // handler and allow the handler to traverse its own pointers. | 1067 // handler and allow the handler to traverse its own pointers. |
| 1059 const Address address = handler->address(); | 1068 const Address address = handler->address(); |
| 1060 v->VisitPointers(base, reinterpret_cast<Object**>(address)); | 1069 v->VisitPointers(base, reinterpret_cast<Object**>(address)); |
| 1061 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize); | 1070 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize); |
| 1062 // Traverse the pointers in the handler itself. | 1071 // Traverse the pointers in the handler itself. |
| 1063 handler->Iterate(v, code()); | 1072 handler->Iterate(v, LookupCode(Isolate::Current())); |
| 1064 } | 1073 } |
| 1065 v->VisitPointers(base, limit); | 1074 v->VisitPointers(base, limit); |
| 1066 } | 1075 } |
| 1067 | 1076 |
| 1068 | 1077 |
| 1069 void JavaScriptFrame::Iterate(ObjectVisitor* v) const { | 1078 void JavaScriptFrame::Iterate(ObjectVisitor* v) const { |
| 1070 IterateExpressions(v); | 1079 IterateExpressions(v); |
| 1071 IteratePc(v, pc_address(), code()); | 1080 IteratePc(v, pc_address(), LookupCode(Isolate::Current())); |
| 1072 IterateArguments(v); | 1081 IterateArguments(v); |
| 1073 } | 1082 } |
| 1074 | 1083 |
| 1075 | 1084 |
| 1076 void JavaScriptFrame::IterateArguments(ObjectVisitor* v) const { | 1085 void JavaScriptFrame::IterateArguments(ObjectVisitor* v) const { |
| 1077 // Traverse callee-saved registers, receiver, and parameters. | 1086 // Traverse callee-saved registers, receiver, and parameters. |
| 1078 const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset; | 1087 const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset; |
| 1079 const int kLimitOffset = JavaScriptFrameConstants::kReceiverOffset; | 1088 const int kLimitOffset = JavaScriptFrameConstants::kReceiverOffset; |
| 1080 Object** base = &Memory::Object_at(fp() + kBaseOffset); | 1089 Object** base = &Memory::Object_at(fp() + kBaseOffset); |
| 1081 Object** limit = &Memory::Object_at(caller_sp() + kLimitOffset) + 1; | 1090 Object** limit = &Memory::Object_at(caller_sp() + kLimitOffset) + 1; |
| 1082 v->VisitPointers(base, limit); | 1091 v->VisitPointers(base, limit); |
| 1083 } | 1092 } |
| 1084 | 1093 |
| 1085 | 1094 |
| 1086 void InternalFrame::Iterate(ObjectVisitor* v) const { | 1095 void InternalFrame::Iterate(ObjectVisitor* v) const { |
| 1087 // Internal frames only have object pointers on the expression stack | 1096 // Internal frames only have object pointers on the expression stack |
| 1088 // as they never have any arguments. | 1097 // as they never have any arguments. |
| 1089 IterateExpressions(v); | 1098 IterateExpressions(v); |
| 1090 IteratePc(v, pc_address(), code()); | 1099 IteratePc(v, pc_address(), LookupCode(Isolate::Current())); |
| 1091 } | 1100 } |
| 1092 | 1101 |
| 1093 | 1102 |
| 1094 // ------------------------------------------------------------------------- | 1103 // ------------------------------------------------------------------------- |
| 1095 | 1104 |
| 1096 | 1105 |
| 1097 JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) { | 1106 JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) { |
| 1098 ASSERT(n >= 0); | 1107 ASSERT(n >= 0); |
| 1099 for (int i = 0; i <= n; i++) { | 1108 for (int i = 0; i <= n; i++) { |
| 1100 while (!iterator_.frame()->is_java_script()) iterator_.Advance(); | 1109 while (!iterator_.frame()->is_java_script()) iterator_.Advance(); |
| 1101 if (i == n) return JavaScriptFrame::cast(iterator_.frame()); | 1110 if (i == n) return JavaScriptFrame::cast(iterator_.frame()); |
| 1102 iterator_.Advance(); | 1111 iterator_.Advance(); |
| 1103 } | 1112 } |
| 1104 UNREACHABLE(); | 1113 UNREACHABLE(); |
| 1105 return NULL; | 1114 return NULL; |
| 1106 } | 1115 } |
| 1107 | 1116 |
| 1108 | 1117 |
| 1109 // ------------------------------------------------------------------------- | 1118 // ------------------------------------------------------------------------- |
| 1110 | 1119 |
| 1111 | 1120 |
| 1112 Code* PcToCodeCache::GcSafeCastToCode(HeapObject* object, Address pc) { | 1121 Code* PcToCodeCache::GcSafeCastToCode(HeapObject* object, Address pc) { |
| 1113 Code* code = reinterpret_cast<Code*>(object); | 1122 Code* code = reinterpret_cast<Code*>(object); |
| 1114 ASSERT(code != NULL && code->contains(pc)); | 1123 ASSERT(code != NULL && code->contains(pc)); |
| 1115 return code; | 1124 return code; |
| 1116 } | 1125 } |
| 1117 | 1126 |
| 1118 | 1127 |
| 1119 Code* PcToCodeCache::GcSafeFindCodeForPc(Address pc) { | 1128 Code* PcToCodeCache::GcSafeFindCodeForPc(Address pc) { |
| 1129 Heap* heap = isolate_->heap(); |
| 1120 // Check if the pc points into a large object chunk. | 1130 // Check if the pc points into a large object chunk. |
| 1121 LargeObjectChunk* chunk = Heap::lo_space()->FindChunkContainingPc(pc); | 1131 LargeObjectChunk* chunk = heap->lo_space()->FindChunkContainingPc(pc); |
| 1122 if (chunk != NULL) return GcSafeCastToCode(chunk->GetObject(), pc); | 1132 if (chunk != NULL) return GcSafeCastToCode(chunk->GetObject(), pc); |
| 1123 | 1133 |
| 1124 // Iterate through the 8K page until we reach the end or find an | 1134 // Iterate through the 8K page until we reach the end or find an |
| 1125 // object starting after the pc. | 1135 // object starting after the pc. |
| 1126 Page* page = Page::FromAddress(pc); | 1136 Page* page = Page::FromAddress(pc); |
| 1127 HeapObjectIterator iterator(page, Heap::GcSafeSizeOfOldObjectFunction()); | 1137 HeapObjectIterator iterator(page, heap->GcSafeSizeOfOldObjectFunction()); |
| 1128 HeapObject* previous = NULL; | 1138 HeapObject* previous = NULL; |
| 1129 while (true) { | 1139 while (true) { |
| 1130 HeapObject* next = iterator.next(); | 1140 HeapObject* next = iterator.next(); |
| 1131 if (next == NULL || next->address() >= pc) { | 1141 if (next == NULL || next->address() >= pc) { |
| 1132 return GcSafeCastToCode(previous, pc); | 1142 return GcSafeCastToCode(previous, pc); |
| 1133 } | 1143 } |
| 1134 previous = next; | 1144 previous = next; |
| 1135 } | 1145 } |
| 1136 } | 1146 } |
| 1137 | 1147 |
| 1138 | 1148 |
| 1139 PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) { | 1149 PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) { |
| 1140 Counters::pc_to_code.Increment(); | 1150 COUNTERS->pc_to_code()->Increment(); |
| 1141 ASSERT(IsPowerOf2(kPcToCodeCacheSize)); | 1151 ASSERT(IsPowerOf2(kPcToCodeCacheSize)); |
| 1142 uint32_t hash = ComputeIntegerHash( | 1152 uint32_t hash = ComputeIntegerHash( |
| 1143 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc))); | 1153 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc))); |
| 1144 uint32_t index = hash & (kPcToCodeCacheSize - 1); | 1154 uint32_t index = hash & (kPcToCodeCacheSize - 1); |
| 1145 PcToCodeCacheEntry* entry = cache(index); | 1155 PcToCodeCacheEntry* entry = cache(index); |
| 1146 if (entry->pc == pc) { | 1156 if (entry->pc == pc) { |
| 1147 Counters::pc_to_code_cached.Increment(); | 1157 COUNTERS->pc_to_code_cached()->Increment(); |
| 1148 ASSERT(entry->code == GcSafeFindCodeForPc(pc)); | 1158 ASSERT(entry->code == GcSafeFindCodeForPc(pc)); |
| 1149 } else { | 1159 } else { |
| 1150 // Because this code may be interrupted by a profiling signal that | 1160 // Because this code may be interrupted by a profiling signal that |
| 1151 // also queries the cache, we cannot update pc before the code has | 1161 // also queries the cache, we cannot update pc before the code has |
| 1152 // been set. Otherwise, we risk trying to use a cache entry before | 1162 // been set. Otherwise, we risk trying to use a cache entry before |
| 1153 // the code has been computed. | 1163 // the code has been computed. |
| 1154 entry->code = GcSafeFindCodeForPc(pc); | 1164 entry->code = GcSafeFindCodeForPc(pc); |
| 1155 entry->safepoint_entry.Reset(); | 1165 entry->safepoint_entry.Reset(); |
| 1156 entry->pc = pc; | 1166 entry->pc = pc; |
| 1157 } | 1167 } |
| 1158 return entry; | 1168 return entry; |
| 1159 } | 1169 } |
| 1160 | 1170 |
| 1161 | 1171 |
| 1162 // ------------------------------------------------------------------------- | 1172 // ------------------------------------------------------------------------- |
| 1163 | 1173 |
| 1164 int NumRegs(RegList reglist) { | 1174 int NumRegs(RegList reglist) { |
| 1165 int n = 0; | 1175 int n = 0; |
| 1166 while (reglist != 0) { | 1176 while (reglist != 0) { |
| 1167 n++; | 1177 n++; |
| 1168 reglist &= reglist - 1; // clear one bit | 1178 reglist &= reglist - 1; // clear one bit |
| 1169 } | 1179 } |
| 1170 return n; | 1180 return n; |
| 1171 } | 1181 } |
| 1172 | 1182 |
| 1173 | 1183 |
| 1174 int JSCallerSavedCode(int n) { | 1184 struct JSCallerSavedCodeData { |
| 1175 static int reg_code[kNumJSCallerSaved]; | 1185 JSCallerSavedCodeData() { |
| 1176 static bool initialized = false; | |
| 1177 if (!initialized) { | |
| 1178 initialized = true; | |
| 1179 int i = 0; | 1186 int i = 0; |
| 1180 for (int r = 0; r < kNumRegs; r++) | 1187 for (int r = 0; r < kNumRegs; r++) |
| 1181 if ((kJSCallerSaved & (1 << r)) != 0) | 1188 if ((kJSCallerSaved & (1 << r)) != 0) |
| 1182 reg_code[i++] = r; | 1189 reg_code[i++] = r; |
| 1183 | 1190 |
| 1184 ASSERT(i == kNumJSCallerSaved); | 1191 ASSERT(i == kNumJSCallerSaved); |
| 1185 } | 1192 } |
| 1193 int reg_code[kNumJSCallerSaved]; |
| 1194 }; |
| 1195 |
| 1196 |
| 1197 static const JSCallerSavedCodeData kCallerSavedCodeData; |
| 1198 |
| 1199 |
| 1200 int JSCallerSavedCode(int n) { |
| 1186 ASSERT(0 <= n && n < kNumJSCallerSaved); | 1201 ASSERT(0 <= n && n < kNumJSCallerSaved); |
| 1187 return reg_code[n]; | 1202 return kCallerSavedCodeData.reg_code[n]; |
| 1188 } | 1203 } |
| 1189 | 1204 |
| 1190 | 1205 |
| 1191 #define DEFINE_WRAPPER(type, field) \ | 1206 #define DEFINE_WRAPPER(type, field) \ |
| 1192 class field##_Wrapper : public ZoneObject { \ | 1207 class field##_Wrapper : public ZoneObject { \ |
| 1193 public: /* NOLINT */ \ | 1208 public: /* NOLINT */ \ |
| 1194 field##_Wrapper(const field& original) : frame_(original) { \ | 1209 field##_Wrapper(const field& original) : frame_(original) { \ |
| 1195 } \ | 1210 } \ |
| 1196 field frame_; \ | 1211 field frame_; \ |
| 1197 }; | 1212 }; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1218 ZoneList<StackFrame*> list(10); | 1233 ZoneList<StackFrame*> list(10); |
| 1219 for (StackFrameIterator it; !it.done(); it.Advance()) { | 1234 for (StackFrameIterator it; !it.done(); it.Advance()) { |
| 1220 StackFrame* frame = AllocateFrameCopy(it.frame()); | 1235 StackFrame* frame = AllocateFrameCopy(it.frame()); |
| 1221 list.Add(frame); | 1236 list.Add(frame); |
| 1222 } | 1237 } |
| 1223 return list.ToVector(); | 1238 return list.ToVector(); |
| 1224 } | 1239 } |
| 1225 | 1240 |
| 1226 | 1241 |
| 1227 } } // namespace v8::internal | 1242 } } // namespace v8::internal |
| OLD | NEW |