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 550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 FunctionGetName, | 561 FunctionGetName, |
562 ReadOnlySetAccessor, | 562 ReadOnlySetAccessor, |
563 0 | 563 0 |
564 }; | 564 }; |
565 | 565 |
566 | 566 |
567 // | 567 // |
568 // Accessors::FunctionArguments | 568 // Accessors::FunctionArguments |
569 // | 569 // |
570 | 570 |
571 static Address SlotAddress(JavaScriptFrame* frame, int slot_index) { | |
572 if (slot_index >= 0) { | |
573 const int offset = JavaScriptFrameConstants::kLocal0Offset; | |
574 return frame->fp() + offset - (slot_index * kPointerSize); | |
575 } else { | |
576 const int offset = JavaScriptFrameConstants::kReceiverOffset; | |
577 return frame->caller_sp() + offset + (slot_index * kPointerSize); | |
578 } | |
579 } | |
580 | |
581 | |
582 // We can't intermix stack decoding and allocations because | |
583 // deoptimization infrastracture is not GC safe. | |
584 // Thus we build a temporary structure in malloced space. | |
585 class SlotRef BASE_EMBEDDED { | |
586 public: | |
587 enum SlotRepresentation { | |
588 UNKNOWN, | |
589 TAGGED, | |
590 INT32, | |
591 DOUBLE, | |
592 LITERAL | |
593 }; | |
594 | |
595 SlotRef() | |
596 : addr_(NULL), representation_(UNKNOWN) { } | |
597 | |
598 SlotRef(Address addr, SlotRepresentation representation) | |
599 : addr_(addr), representation_(representation) { } | |
600 | |
601 explicit SlotRef(Object* literal) | |
602 : literal_(literal), representation_(LITERAL) { } | |
603 | |
604 Handle<Object> GetValue() { | |
605 switch (representation_) { | |
606 case TAGGED: | |
607 return Handle<Object>(Memory::Object_at(addr_)); | |
608 | |
609 case INT32: { | |
610 int value = Memory::int32_at(addr_); | |
611 if (Smi::IsValid(value)) { | |
612 return Handle<Object>(Smi::FromInt(value)); | |
613 } else { | |
614 return Isolate::Current()->factory()->NewNumberFromInt(value); | |
615 } | |
616 } | |
617 | |
618 case DOUBLE: { | |
619 double value = Memory::double_at(addr_); | |
620 return Isolate::Current()->factory()->NewNumber(value); | |
621 } | |
622 | |
623 case LITERAL: | |
624 return literal_; | |
625 | |
626 default: | |
627 UNREACHABLE(); | |
628 return Handle<Object>::null(); | |
629 } | |
630 } | |
631 | |
632 private: | |
633 Address addr_; | |
634 Handle<Object> literal_; | |
635 SlotRepresentation representation_; | |
636 }; | |
637 | |
638 | |
639 static SlotRef ComputeSlotForNextArgument(TranslationIterator* iterator, | |
640 DeoptimizationInputData* data, | |
641 JavaScriptFrame* frame) { | |
642 Translation::Opcode opcode = | |
643 static_cast<Translation::Opcode>(iterator->Next()); | |
644 | |
645 switch (opcode) { | |
646 case Translation::BEGIN: | |
647 case Translation::FRAME: | |
648 // Peeled off before getting here. | |
649 break; | |
650 | |
651 case Translation::ARGUMENTS_OBJECT: | |
652 // This can be only emitted for local slots not for argument slots. | |
653 break; | |
654 | |
655 case Translation::REGISTER: | |
656 case Translation::INT32_REGISTER: | |
657 case Translation::DOUBLE_REGISTER: | |
658 case Translation::DUPLICATE: | |
659 // We are at safepoint which corresponds to call. All registers are | |
660 // saved by caller so there would be no live registers at this | |
661 // point. Thus these translation commands should not be used. | |
662 break; | |
663 | |
664 case Translation::STACK_SLOT: { | |
665 int slot_index = iterator->Next(); | |
666 Address slot_addr = SlotAddress(frame, slot_index); | |
667 return SlotRef(slot_addr, SlotRef::TAGGED); | |
668 } | |
669 | |
670 case Translation::INT32_STACK_SLOT: { | |
671 int slot_index = iterator->Next(); | |
672 Address slot_addr = SlotAddress(frame, slot_index); | |
673 return SlotRef(slot_addr, SlotRef::INT32); | |
674 } | |
675 | |
676 case Translation::DOUBLE_STACK_SLOT: { | |
677 int slot_index = iterator->Next(); | |
678 Address slot_addr = SlotAddress(frame, slot_index); | |
679 return SlotRef(slot_addr, SlotRef::DOUBLE); | |
680 } | |
681 | |
682 case Translation::LITERAL: { | |
683 int literal_index = iterator->Next(); | |
684 return SlotRef(data->LiteralArray()->get(literal_index)); | |
685 } | |
686 } | |
687 | |
688 UNREACHABLE(); | |
689 return SlotRef(); | |
690 } | |
691 | |
692 | |
693 | |
694 | |
695 | |
696 static void ComputeSlotMappingForArguments(JavaScriptFrame* frame, | |
697 int inlined_frame_index, | |
698 Vector<SlotRef>* args_slots) { | |
699 AssertNoAllocation no_gc; | |
700 int deopt_index = AstNode::kNoNumber; | |
701 DeoptimizationInputData* data = | |
702 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); | |
703 TranslationIterator it(data->TranslationByteArray(), | |
704 data->TranslationIndex(deopt_index)->value()); | |
705 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | |
706 ASSERT(opcode == Translation::BEGIN); | |
707 int frame_count = it.Next(); | |
708 USE(frame_count); | |
709 ASSERT(frame_count > inlined_frame_index); | |
710 int frames_to_skip = inlined_frame_index; | |
711 while (true) { | |
712 opcode = static_cast<Translation::Opcode>(it.Next()); | |
713 // Skip over operands to advance to the next opcode. | |
714 it.Skip(Translation::NumberOfOperandsFor(opcode)); | |
715 if (opcode == Translation::FRAME) { | |
716 if (frames_to_skip == 0) { | |
717 // We reached the frame corresponding to the inlined function | |
718 // in question. Process the translation commands for the | |
719 // arguments. | |
720 // | |
721 // Skip the translation command for the receiver. | |
722 it.Skip(Translation::NumberOfOperandsFor( | |
723 static_cast<Translation::Opcode>(it.Next()))); | |
724 // Compute slots for arguments. | |
725 for (int i = 0; i < args_slots->length(); ++i) { | |
726 (*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame); | |
727 } | |
728 return; | |
729 } | |
730 frames_to_skip--; | |
731 } | |
732 } | |
733 | |
734 UNREACHABLE(); | |
735 } | |
736 | |
737 | 571 |
738 static MaybeObject* ConstructArgumentsObjectForInlinedFunction( | 572 static MaybeObject* ConstructArgumentsObjectForInlinedFunction( |
739 JavaScriptFrame* frame, | 573 JavaScriptFrame* frame, |
740 Handle<JSFunction> inlined_function, | 574 Handle<JSFunction> inlined_function, |
741 int inlined_frame_index) { | 575 int inlined_frame_index) { |
742 Factory* factory = Isolate::Current()->factory(); | 576 Factory* factory = Isolate::Current()->factory(); |
743 int args_count = inlined_function->shared()->formal_parameter_count(); | 577 int args_count = inlined_function->shared()->formal_parameter_count(); |
744 ScopedVector<SlotRef> args_slots(args_count); | 578 ScopedVector<SlotRef> args_slots(args_count); |
745 ComputeSlotMappingForArguments(frame, inlined_frame_index, &args_slots); | 579 SlotRef::ComputeSlotMappingForArguments(frame, |
| 580 inlined_frame_index, |
| 581 &args_slots); |
746 Handle<JSObject> arguments = | 582 Handle<JSObject> arguments = |
747 factory->NewArgumentsObject(inlined_function, args_count); | 583 factory->NewArgumentsObject(inlined_function, args_count); |
748 Handle<FixedArray> array = factory->NewFixedArray(args_count); | 584 Handle<FixedArray> array = factory->NewFixedArray(args_count); |
749 for (int i = 0; i < args_count; ++i) { | 585 for (int i = 0; i < args_count; ++i) { |
750 Handle<Object> value = args_slots[i].GetValue(); | 586 Handle<Object> value = args_slots[i].GetValue(); |
751 array->set(i, *value); | 587 array->set(i, *value); |
752 } | 588 } |
753 arguments->set_elements(*array); | 589 arguments->set_elements(*array); |
754 | 590 |
755 // Return the freshly allocated arguments object. | 591 // Return the freshly allocated arguments object. |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
921 } | 757 } |
922 | 758 |
923 | 759 |
924 const AccessorDescriptor Accessors::ObjectPrototype = { | 760 const AccessorDescriptor Accessors::ObjectPrototype = { |
925 ObjectGetPrototype, | 761 ObjectGetPrototype, |
926 ObjectSetPrototype, | 762 ObjectSetPrototype, |
927 0 | 763 0 |
928 }; | 764 }; |
929 | 765 |
930 } } // namespace v8::internal | 766 } } // namespace v8::internal |
OLD | NEW |