Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/frames.cc

Issue 6529055: [Isolates] Merge crankshaft (r5922 from bleeding_edge). (Closed)
Patch Set: Win32 port Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/frames.h ('k') | src/full-codegen.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "ast.h"
31 #include "deoptimizer.h"
30 #include "frames-inl.h" 32 #include "frames-inl.h"
33 #include "full-codegen.h"
31 #include "mark-compact.h" 34 #include "mark-compact.h"
35 #include "safepoint-table.h"
32 #include "scopeinfo.h" 36 #include "scopeinfo.h"
33 #include "string-stream.h" 37 #include "string-stream.h"
34 38
35 namespace v8 { 39 namespace v8 {
36 namespace internal { 40 namespace internal {
37 41
38 42
39 int SafeStackFrameIterator::active_count_ = 0; 43 int SafeStackFrameIterator::active_count_ = 0;
40 44
41 // Iterator that supports traversing the stack handlers of a 45 // Iterator that supports traversing the stack handlers of a
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 thread_(Isolate::Current()->thread_local_top()), 78 thread_(Isolate::Current()->thread_local_top()),
75 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) { 79 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
76 Reset(); 80 Reset();
77 } 81 }
78 StackFrameIterator::StackFrameIterator(ThreadLocalTop* t) 82 StackFrameIterator::StackFrameIterator(ThreadLocalTop* t)
79 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) 83 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
80 frame_(NULL), handler_(NULL), thread_(t), 84 frame_(NULL), handler_(NULL), thread_(t),
81 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) { 85 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
82 Reset(); 86 Reset();
83 } 87 }
84 StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp) 88 StackFrameIterator::StackFrameIterator(Isolate* isolate,
89 bool use_top, Address fp, Address sp)
85 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) 90 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
86 frame_(NULL), handler_(NULL), 91 frame_(NULL), handler_(NULL),
87 thread_(use_top ? Isolate::Current()->thread_local_top() : NULL), 92 thread_(use_top ? isolate->thread_local_top() : NULL),
88 fp_(use_top ? NULL : fp), sp_(sp), 93 fp_(use_top ? NULL : fp), sp_(sp),
89 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler : 94 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
90 &StackFrameIterator::AdvanceWithoutHandler) { 95 &StackFrameIterator::AdvanceWithoutHandler) {
91 if (use_top || fp != NULL) { 96 if (use_top || fp != NULL) {
92 Reset(); 97 Reset();
93 } 98 }
94 } 99 }
95 100
96 #undef INITIALIZE_SINGLETON 101 #undef INITIALIZE_SINGLETON
97 102
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 StackFrame::State state; 215 StackFrame::State state;
211 ExitFrame::FillState(fp, sp, &state); 216 ExitFrame::FillState(fp, sp, &state);
212 if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) { 217 if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) {
213 return false; 218 return false;
214 } 219 }
215 return *state.pc_address != NULL; 220 return *state.pc_address != NULL;
216 } 221 }
217 222
218 223
219 SafeStackFrameIterator::SafeStackFrameIterator( 224 SafeStackFrameIterator::SafeStackFrameIterator(
225 Isolate* isolate,
220 Address fp, Address sp, Address low_bound, Address high_bound) : 226 Address fp, Address sp, Address low_bound, Address high_bound) :
221 maintainer_(), 227 maintainer_(),
222 stack_validator_(low_bound, high_bound), 228 stack_validator_(low_bound, high_bound),
223 is_valid_top_(IsValidTop(low_bound, high_bound)), 229 is_valid_top_(IsValidTop(isolate, low_bound, high_bound)),
224 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)), 230 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
225 is_working_iterator_(is_valid_top_ || is_valid_fp_), 231 is_working_iterator_(is_valid_top_ || is_valid_fp_),
226 iteration_done_(!is_working_iterator_), 232 iteration_done_(!is_working_iterator_),
227 iterator_(is_valid_top_, is_valid_fp_ ? fp : NULL, sp) { 233 iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
228 } 234 }
229 235
230 236
231 bool SafeStackFrameIterator::IsValidTop(Address low_bound, Address high_bound) { 237 bool SafeStackFrameIterator::IsValidTop(Isolate* isolate,
232 ThreadLocalTop* top = Isolate::Current()->thread_local_top(); 238 Address low_bound, Address high_bound) {
239 ThreadLocalTop* top = isolate->thread_local_top();
233 Address fp = Isolate::c_entry_fp(top); 240 Address fp = Isolate::c_entry_fp(top);
234 ExitFrameValidator validator(low_bound, high_bound); 241 ExitFrameValidator validator(low_bound, high_bound);
235 if (!validator.IsValidFP(fp)) return false; 242 if (!validator.IsValidFP(fp)) return false;
236 return Isolate::handler(top) != NULL; 243 return Isolate::handler(top) != NULL;
237 } 244 }
238 245
239 246
240 void SafeStackFrameIterator::Advance() { 247 void SafeStackFrameIterator::Advance() {
241 ASSERT(is_working_iterator_); 248 ASSERT(is_working_iterator_);
242 ASSERT(!done()); 249 ASSERT(!done());
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 iteration_done_ = false; 309 iteration_done_ = false;
303 } 310 }
304 } 311 }
305 312
306 313
307 // ------------------------------------------------------------------------- 314 // -------------------------------------------------------------------------
308 315
309 316
310 #ifdef ENABLE_LOGGING_AND_PROFILING 317 #ifdef ENABLE_LOGGING_AND_PROFILING
311 SafeStackTraceFrameIterator::SafeStackTraceFrameIterator( 318 SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
319 Isolate* isolate,
312 Address fp, Address sp, Address low_bound, Address high_bound) : 320 Address fp, Address sp, Address low_bound, Address high_bound) :
313 SafeJavaScriptFrameIterator(fp, sp, low_bound, high_bound) { 321 SafeJavaScriptFrameIterator(isolate, fp, sp, low_bound, high_bound) {
314 if (!done() && !frame()->is_java_script()) Advance(); 322 if (!done() && !frame()->is_java_script()) Advance();
315 } 323 }
316 324
317 325
318 void SafeStackTraceFrameIterator::Advance() { 326 void SafeStackTraceFrameIterator::Advance() {
319 while (true) { 327 while (true) {
320 SafeJavaScriptFrameIterator::Advance(); 328 SafeJavaScriptFrameIterator::Advance();
321 if (done()) return; 329 if (done()) return;
322 if (frame()->is_java_script()) return; 330 if (frame()->is_java_script()) return;
323 } 331 }
324 } 332 }
325 #endif 333 #endif
326 334
327 335
336 Code* StackFrame::GetSafepointData(Address pc,
337 uint8_t** safepoint_entry,
338 unsigned* stack_slots) {
339 Isolate* isolate = Isolate::Current();
340 PcToCodeCache::PcToCodeCacheEntry* entry =
341 isolate->pc_to_code_cache()->GetCacheEntry(pc);
342 uint8_t* cached_safepoint_entry = entry->safepoint_entry;
343 if (cached_safepoint_entry == NULL) {
344 cached_safepoint_entry = entry->code->GetSafepointEntry(pc);
345 ASSERT(cached_safepoint_entry != NULL); // No safepoint found.
346 entry->safepoint_entry = cached_safepoint_entry;
347 } else {
348 ASSERT(cached_safepoint_entry == entry->code->GetSafepointEntry(pc));
349 }
350
351 // Fill in the results and return the code.
352 Code* code = entry->code;
353 *safepoint_entry = cached_safepoint_entry;
354 *stack_slots = code->stack_slots();
355 return code;
356 }
357
358
328 bool StackFrame::HasHandler() const { 359 bool StackFrame::HasHandler() const {
329 StackHandlerIterator it(this, top_handler()); 360 StackHandlerIterator it(this, top_handler());
330 return !it.done(); 361 return !it.done();
331 } 362 }
332 363
364
333 void StackFrame::IteratePc(ObjectVisitor* v, 365 void StackFrame::IteratePc(ObjectVisitor* v,
334 Address* pc_address, 366 Address* pc_address,
335 Code* holder) { 367 Code* holder) {
336 Address pc = *pc_address; 368 Address pc = *pc_address;
337 ASSERT(holder->contains(pc)); 369 ASSERT(holder->contains(pc));
338 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start()); 370 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
339 Object* code = holder; 371 Object* code = holder;
340 v->VisitPointer(&code); 372 v->VisitPointer(&code);
341 if (code != holder) { 373 if (code != holder) {
342 holder = reinterpret_cast<Code*>(code); 374 holder = reinterpret_cast<Code*>(code);
343 pc = holder->instruction_start() + pc_offset; 375 pc = holder->instruction_start() + pc_offset;
344 *pc_address = pc; 376 *pc_address = pc;
345 } 377 }
346 } 378 }
347 379
348 380
349 StackFrame::Type StackFrame::ComputeType(State* state) { 381 StackFrame::Type StackFrame::ComputeType(State* state) {
350 ASSERT(state->fp != NULL); 382 ASSERT(state->fp != NULL);
351 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { 383 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
352 return ARGUMENTS_ADAPTOR; 384 return ARGUMENTS_ADAPTOR;
353 } 385 }
354 // The marker and function offsets overlap. If the marker isn't a 386 // The marker and function offsets overlap. If the marker isn't a
355 // smi then the frame is a JavaScript frame -- and the marker is 387 // smi then the frame is a JavaScript frame -- and the marker is
356 // really the function. 388 // really the function.
357 const int offset = StandardFrameConstants::kMarkerOffset; 389 const int offset = StandardFrameConstants::kMarkerOffset;
358 Object* marker = Memory::Object_at(state->fp + offset); 390 Object* marker = Memory::Object_at(state->fp + offset);
359 if (!marker->IsSmi()) return JAVA_SCRIPT; 391 if (!marker->IsSmi()) {
392 // If we're using a "safe" stack iterator, we treat optimized
393 // frames as normal JavaScript frames to avoid having to look
394 // into the heap to determine the state. This is safe as long
395 // as nobody tries to GC...
396 if (SafeStackFrameIterator::is_active()) return JAVA_SCRIPT;
397 Code::Kind kind = GetContainingCode(Isolate::Current(),
398 *(state->pc_address))->kind();
399 ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
400 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
401 }
360 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); 402 return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
361 } 403 }
362 404
363 405
364 406
365 StackFrame::Type StackFrame::GetCallerState(State* state) const { 407 StackFrame::Type StackFrame::GetCallerState(State* state) const {
366 ComputeCallerState(state); 408 ComputeCallerState(state);
367 return ComputeType(state); 409 return ComputeType(state);
368 } 410 }
369 411
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 524
483 bool StandardFrame::IsExpressionInsideHandler(int n) const { 525 bool StandardFrame::IsExpressionInsideHandler(int n) const {
484 Address address = GetExpressionAddress(n); 526 Address address = GetExpressionAddress(n);
485 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { 527 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
486 if (it.handler()->includes(address)) return true; 528 if (it.handler()->includes(address)) return true;
487 } 529 }
488 return false; 530 return false;
489 } 531 }
490 532
491 533
534 void OptimizedFrame::Iterate(ObjectVisitor* v) const {
535 #ifdef DEBUG
536 // Make sure that optimized frames do not contain any stack handlers.
537 StackHandlerIterator it(this, top_handler());
538 ASSERT(it.done());
539 #endif
540
541 // Make sure that we're not doing "safe" stack frame iteration. We cannot
542 // possibly find pointers in optimized frames in that state.
543 ASSERT(!SafeStackFrameIterator::is_active());
544
545 // Compute the safepoint information.
546 unsigned stack_slots = 0;
547 uint8_t* safepoint_entry = NULL;
548 Code* code = StackFrame::GetSafepointData(
549 pc(), &safepoint_entry, &stack_slots);
550 unsigned slot_space = stack_slots * kPointerSize;
551
552 // Visit the outgoing parameters. This is usually dealt with by the
553 // callee, but while GC'ing we artificially lower the number of
554 // arguments to zero and let the caller deal with it.
555 Object** parameters_base = &Memory::Object_at(sp());
556 Object** parameters_limit = &Memory::Object_at(
557 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
558
559 // Visit the registers that contain pointers if any.
560 if (SafepointTable::HasRegisters(safepoint_entry)) {
561 for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
562 if (SafepointTable::HasRegisterAt(safepoint_entry, i)) {
563 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
564 v->VisitPointer(parameters_base + reg_stack_index);
565 }
566 }
567 // Skip the words containing the register values.
568 parameters_base += kNumSafepointRegisters;
569 }
570
571 // We're done dealing with the register bits.
572 safepoint_entry += kNumSafepointRegisters >> kBitsPerByteLog2;
573
574 // Visit the rest of the parameters.
575 v->VisitPointers(parameters_base, parameters_limit);
576
577 // Visit pointer spill slots and locals.
578 for (unsigned index = 0; index < stack_slots; index++) {
579 int byte_index = index >> kBitsPerByteLog2;
580 int bit_index = index & (kBitsPerByte - 1);
581 if ((safepoint_entry[byte_index] & (1U << bit_index)) != 0) {
582 v->VisitPointer(parameters_limit + index);
583 }
584 }
585
586 // Visit the context and the function.
587 Object** fixed_base = &Memory::Object_at(
588 fp() + JavaScriptFrameConstants::kFunctionOffset);
589 Object** fixed_limit = &Memory::Object_at(fp());
590 v->VisitPointers(fixed_base, fixed_limit);
591
592 // Visit the return address in the callee and incoming arguments.
593 IteratePc(v, pc_address(), code);
594 IterateArguments(v);
595 }
596
597
492 Object* JavaScriptFrame::GetParameter(int index) const { 598 Object* JavaScriptFrame::GetParameter(int index) const {
493 ASSERT(index >= 0 && index < ComputeParametersCount()); 599 ASSERT(index >= 0 && index < ComputeParametersCount());
494 const int offset = JavaScriptFrameConstants::kParam0Offset; 600 const int offset = JavaScriptFrameConstants::kParam0Offset;
495 return Memory::Object_at(caller_sp() + offset - (index * kPointerSize)); 601 return Memory::Object_at(caller_sp() + offset - (index * kPointerSize));
496 } 602 }
497 603
498 604
499 int JavaScriptFrame::ComputeParametersCount() const { 605 int JavaScriptFrame::ComputeParametersCount() const {
500 Address base = caller_sp() + JavaScriptFrameConstants::kReceiverOffset; 606 Address base = caller_sp() + JavaScriptFrameConstants::kReceiverOffset;
501 Address limit = fp() + JavaScriptFrameConstants::kSavedRegistersOffset; 607 Address limit = fp() + JavaScriptFrameConstants::kSavedRegistersOffset;
(...skipping 17 matching lines...) Expand all
519 } 625 }
520 626
521 627
522 int JavaScriptFrame::GetProvidedParametersCount() const { 628 int JavaScriptFrame::GetProvidedParametersCount() const {
523 return ComputeParametersCount(); 629 return ComputeParametersCount();
524 } 630 }
525 631
526 632
527 Address JavaScriptFrame::GetCallerStackPointer() const { 633 Address JavaScriptFrame::GetCallerStackPointer() const {
528 int arguments; 634 int arguments;
529 if (HEAP->gc_state() != Heap::NOT_IN_GC || 635 if (SafeStackFrameIterator::is_active() ||
530 SafeStackFrameIterator::is_active()) { 636 HEAP->gc_state() != Heap::NOT_IN_GC) {
531 // If the we are currently iterating the safe stack the 637 // If the we are currently iterating the safe stack the
532 // arguments for frames are traversed as if they were 638 // arguments for frames are traversed as if they were
533 // expression stack elements of the calling frame. The reason for 639 // expression stack elements of the calling frame. The reason for
534 // this rather strange decision is that we cannot access the 640 // this rather strange decision is that we cannot access the
535 // function during mark-compact GCs when objects may have been marked. 641 // function during mark-compact GCs when objects may have been marked.
536 // In fact accessing heap objects (like function->shared() below) 642 // In fact accessing heap objects (like function->shared() below)
537 // at all during GC is problematic. 643 // at all during GC is problematic.
538 arguments = 0; 644 arguments = 0;
539 } else { 645 } else {
540 // Compute the number of arguments by getting the number of formal 646 // Compute the number of arguments by getting the number of formal
541 // parameters of the function. We must remember to take the 647 // parameters of the function. We must remember to take the
542 // receiver into account (+1). 648 // receiver into account (+1).
543 JSFunction* function = JSFunction::cast(this->function()); 649 JSFunction* function = JSFunction::cast(this->function());
544 arguments = function->shared()->formal_parameter_count() + 1; 650 arguments = function->shared()->formal_parameter_count() + 1;
545 } 651 }
546 const int offset = StandardFrameConstants::kCallerSPOffset; 652 const int offset = StandardFrameConstants::kCallerSPOffset;
547 return fp() + offset + (arguments * kPointerSize); 653 return fp() + offset + (arguments * kPointerSize);
548 } 654 }
549 655
550 656
657 void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) {
658 ASSERT(functions->length() == 0);
659 functions->Add(JSFunction::cast(function()));
660 }
661
662
663 void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
664 ASSERT(functions->length() == 0);
665 Code* code_pointer = LookupCode(Isolate::Current());
666 int offset = pc() - code_pointer->address();
667 FrameSummary summary(receiver(),
668 JSFunction::cast(function()),
669 code_pointer,
670 offset,
671 IsConstructor());
672 functions->Add(summary);
673 }
674
675
676 void FrameSummary::Print() {
677 PrintF("receiver: ");
678 receiver_->ShortPrint();
679 PrintF("\nfunction: ");
680 function_->shared()->DebugName()->ShortPrint();
681 PrintF("\ncode: ");
682 code_->ShortPrint();
683 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT");
684 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT");
685 PrintF("\npc: %d\n", offset_);
686 }
687
688
689 void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
690 ASSERT(frames->length() == 0);
691 ASSERT(is_optimized());
692
693 int deopt_index = AstNode::kNoNumber;
694 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
695
696 // BUG(3243555): Since we don't have a lazy-deopt registered at
697 // throw-statements, we can't use the translation at the call-site of
698 // throw. An entry with no deoptimization index indicates a call-site
699 // without a lazy-deopt. As a consequence we are not allowed to inline
700 // functions containing throw.
701 if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
702 JavaScriptFrame::Summarize(frames);
703 return;
704 }
705
706 TranslationIterator it(data->TranslationByteArray(),
707 data->TranslationIndex(deopt_index)->value());
708 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
709 ASSERT(opcode == Translation::BEGIN);
710 int frame_count = it.Next();
711
712 // We create the summary in reverse order because the frames
713 // in the deoptimization translation are ordered bottom-to-top.
714 int i = frame_count;
715 while (i > 0) {
716 opcode = static_cast<Translation::Opcode>(it.Next());
717 if (opcode == Translation::FRAME) {
718 // We don't inline constructor calls, so only the first, outermost
719 // frame can be a constructor frame in case of inlining.
720 bool is_constructor = (i == frame_count) && IsConstructor();
721
722 i--;
723 int ast_id = it.Next();
724 int function_id = it.Next();
725 it.Next(); // Skip height.
726 JSFunction* function =
727 JSFunction::cast(data->LiteralArray()->get(function_id));
728
729 // The translation commands are ordered and the receiver is always
730 // at the first position. Since we are always at a call when we need
731 // to construct a stack trace, the receiver is always in a stack slot.
732 opcode = static_cast<Translation::Opcode>(it.Next());
733 ASSERT(opcode == Translation::STACK_SLOT);
734 int input_slot_index = it.Next();
735
736 // Get the correct receiver in the optimized frame.
737 Object* receiver = NULL;
738 // Positive index means the value is spilled to the locals area. Negative
739 // means it is stored in the incoming parameter area.
740 if (input_slot_index >= 0) {
741 receiver = GetExpression(input_slot_index);
742 } else {
743 // Index -1 overlaps with last parameter, -n with the first parameter,
744 // (-n - 1) with the receiver with n being the number of parameters
745 // of the outermost, optimized frame.
746 int parameter_count = ComputeParametersCount();
747 int parameter_index = input_slot_index + parameter_count;
748 receiver = (parameter_index == -1)
749 ? this->receiver()
750 : this->GetParameter(parameter_index);
751 }
752
753 Code* code = function->shared()->code();
754 DeoptimizationOutputData* output_data =
755 DeoptimizationOutputData::cast(code->deoptimization_data());
756 unsigned entry = Deoptimizer::GetOutputInfo(output_data,
757 ast_id,
758 function->shared());
759 unsigned pc_offset =
760 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize;
761 ASSERT(pc_offset > 0);
762
763 FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
764 frames->Add(summary);
765 } else {
766 // Skip over operands to advance to the next opcode.
767 it.Skip(Translation::NumberOfOperandsFor(opcode));
768 }
769 }
770 }
771
772
773 DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
774 int* deopt_index) {
775 ASSERT(is_optimized());
776
777 JSFunction* opt_function = JSFunction::cast(function());
778 Code* code = opt_function->code();
779
780 // 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
782 // code object.
783 if (!code->contains(pc())) {
784 code = Isolate::Current()->pc_to_code_cache()->GcSafeFindCodeForPc(pc());
785 }
786 ASSERT(code != NULL);
787 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
788
789 SafepointTable table(code);
790 unsigned pc_offset = pc() - code->instruction_start();
791 for (unsigned i = 0; i < table.length(); i++) {
792 if (table.GetPcOffset(i) == pc_offset) {
793 *deopt_index = table.GetDeoptimizationIndex(i);
794 break;
795 }
796 }
797 ASSERT(*deopt_index != AstNode::kNoNumber);
798
799 return DeoptimizationInputData::cast(code->deoptimization_data());
800 }
801
802
803 void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
804 ASSERT(functions->length() == 0);
805 ASSERT(is_optimized());
806
807 int deopt_index = AstNode::kNoNumber;
808 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
809
810 TranslationIterator it(data->TranslationByteArray(),
811 data->TranslationIndex(deopt_index)->value());
812 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
813 ASSERT(opcode == Translation::BEGIN);
814 int frame_count = it.Next();
815
816 // We insert the frames in reverse order because the frames
817 // in the deoptimization translation are ordered bottom-to-top.
818 while (frame_count > 0) {
819 opcode = static_cast<Translation::Opcode>(it.Next());
820 if (opcode == Translation::FRAME) {
821 frame_count--;
822 it.Next(); // Skip ast id.
823 int function_id = it.Next();
824 it.Next(); // Skip height.
825 JSFunction* function =
826 JSFunction::cast(data->LiteralArray()->get(function_id));
827 functions->Add(function);
828 } else {
829 // Skip over operands to advance to the next opcode.
830 it.Skip(Translation::NumberOfOperandsFor(opcode));
831 }
832 }
833 }
834
835
551 Address ArgumentsAdaptorFrame::GetCallerStackPointer() const { 836 Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
552 const int arguments = Smi::cast(GetExpression(0))->value(); 837 const int arguments = Smi::cast(GetExpression(0))->value();
553 const int offset = StandardFrameConstants::kCallerSPOffset; 838 const int offset = StandardFrameConstants::kCallerSPOffset;
554 return fp() + offset + (arguments + 1) * kPointerSize; 839 return fp() + offset + (arguments + 1) * kPointerSize;
555 } 840 }
556 841
557 842
558 Address InternalFrame::GetCallerStackPointer() const { 843 Address InternalFrame::GetCallerStackPointer() const {
559 // Internal frames have no arguments. The stack pointer of the 844 // Internal frames have no arguments. The stack pointer of the
560 // caller is at a fixed offset from the frame pointer. 845 // caller is at a fixed offset from the frame pointer.
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 // Traverse the pointers in the handler itself. 1069 // Traverse the pointers in the handler itself.
785 handler->Iterate(v, LookupCode(Isolate::Current())); 1070 handler->Iterate(v, LookupCode(Isolate::Current()));
786 } 1071 }
787 v->VisitPointers(base, limit); 1072 v->VisitPointers(base, limit);
788 } 1073 }
789 1074
790 1075
791 void JavaScriptFrame::Iterate(ObjectVisitor* v) const { 1076 void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
792 IterateExpressions(v); 1077 IterateExpressions(v);
793 IteratePc(v, pc_address(), LookupCode(Isolate::Current())); 1078 IteratePc(v, pc_address(), LookupCode(Isolate::Current()));
1079 IterateArguments(v);
1080 }
794 1081
1082
1083 void JavaScriptFrame::IterateArguments(ObjectVisitor* v) const {
795 // Traverse callee-saved registers, receiver, and parameters. 1084 // Traverse callee-saved registers, receiver, and parameters.
796 const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset; 1085 const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset;
797 const int kLimitOffset = JavaScriptFrameConstants::kReceiverOffset; 1086 const int kLimitOffset = JavaScriptFrameConstants::kReceiverOffset;
798 Object** base = &Memory::Object_at(fp() + kBaseOffset); 1087 Object** base = &Memory::Object_at(fp() + kBaseOffset);
799 Object** limit = &Memory::Object_at(caller_sp() + kLimitOffset) + 1; 1088 Object** limit = &Memory::Object_at(caller_sp() + kLimitOffset) + 1;
800 v->VisitPointers(base, limit); 1089 v->VisitPointers(base, limit);
801 } 1090 }
802 1091
803 1092
804 void InternalFrame::Iterate(ObjectVisitor* v) const { 1093 void InternalFrame::Iterate(ObjectVisitor* v) const {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 HeapObject* previous = NULL; 1136 HeapObject* previous = NULL;
848 while (true) { 1137 while (true) {
849 HeapObject* next = iterator.next(); 1138 HeapObject* next = iterator.next();
850 if (next == NULL || next->address() >= pc) { 1139 if (next == NULL || next->address() >= pc) {
851 return GcSafeCastToCode(previous, pc); 1140 return GcSafeCastToCode(previous, pc);
852 } 1141 }
853 previous = next; 1142 previous = next;
854 } 1143 }
855 } 1144 }
856 1145
1146
857 PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) { 1147 PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) {
858 COUNTERS->pc_to_code()->Increment(); 1148 COUNTERS->pc_to_code()->Increment();
859 ASSERT(IsPowerOf2(kPcToCodeCacheSize)); 1149 ASSERT(IsPowerOf2(kPcToCodeCacheSize));
860 uint32_t hash = ComputeIntegerHash( 1150 uint32_t hash = ComputeIntegerHash(
861 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc))); 1151 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc)));
862 uint32_t index = hash & (kPcToCodeCacheSize - 1); 1152 uint32_t index = hash & (kPcToCodeCacheSize - 1);
863 PcToCodeCacheEntry* entry = cache(index); 1153 PcToCodeCacheEntry* entry = cache(index);
864 if (entry->pc == pc) { 1154 if (entry->pc == pc) {
865 COUNTERS->pc_to_code_cached()->Increment(); 1155 COUNTERS->pc_to_code_cached()->Increment();
866 ASSERT(entry->code == GcSafeFindCodeForPc(pc)); 1156 ASSERT(entry->code == GcSafeFindCodeForPc(pc));
867 } else { 1157 } else {
868 // Because this code may be interrupted by a profiling signal that 1158 // Because this code may be interrupted by a profiling signal that
869 // also queries the cache, we cannot update pc before the code has 1159 // also queries the cache, we cannot update pc before the code has
870 // been set. Otherwise, we risk trying to use a cache entry before 1160 // been set. Otherwise, we risk trying to use a cache entry before
871 // the code has been computed. 1161 // the code has been computed.
872 entry->code = GcSafeFindCodeForPc(pc); 1162 entry->code = GcSafeFindCodeForPc(pc);
1163 entry->safepoint_entry = NULL;
873 entry->pc = pc; 1164 entry->pc = pc;
874 } 1165 }
875 return entry; 1166 return entry;
876 } 1167 }
877 1168
878 1169
879 // ------------------------------------------------------------------------- 1170 // -------------------------------------------------------------------------
880 1171
881 int NumRegs(RegList reglist) { 1172 int NumRegs(RegList reglist) {
882 int n = 0; 1173 int n = 0;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
940 ZoneList<StackFrame*> list(10); 1231 ZoneList<StackFrame*> list(10);
941 for (StackFrameIterator it; !it.done(); it.Advance()) { 1232 for (StackFrameIterator it; !it.done(); it.Advance()) {
942 StackFrame* frame = AllocateFrameCopy(it.frame()); 1233 StackFrame* frame = AllocateFrameCopy(it.frame());
943 list.Add(frame); 1234 list.Add(frame);
944 } 1235 }
945 return list.ToVector(); 1236 return list.ToVector();
946 } 1237 }
947 1238
948 1239
949 } } // namespace v8::internal 1240 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/frames.h ('k') | src/full-codegen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698