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 |