1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef V8_DEOPTIMIZER_H_
6 #define V8_DEOPTIMIZER_H_
10 #include "src/allocation.h"
11 #include "src/macro-assembler.h"
12 #include "src/zone-inl.h"
19 static inline double read_double_value(Address p) {
21 memcpy(&d, p, sizeof(d));
25 static inline simd128_value_t read_simd128_value(Address p) {
26 return *reinterpret_cast<simd128_value_t*>(p);
29 class FrameDescription;
30 class TranslationIterator;
31 class DeoptimizedFrameInfo;
34 class HeapNumberMaterializationDescriptor BASE_EMBEDDED {
36 HeapNumberMaterializationDescriptor(T destination, double value)
37 : destination_(destination), value_(value) { }
39 T destination() const { return destination_; }
40 double value() const { return value_; }
49 class SIMD128MaterializationDescriptor BASE_EMBEDDED {
51 SIMD128MaterializationDescriptor(T destination, simd128_value_t value)
52 : destination_(destination), value_(value) { }
54 T destination() const { return destination_; }
55 simd128_value_t value() const { return value_; }
59 simd128_value_t value_;
63 class ObjectMaterializationDescriptor BASE_EMBEDDED {
65 ObjectMaterializationDescriptor(
66 Address slot_address, int frame, int length, int duplicate, bool is_args)
67 : slot_address_(slot_address),
68 jsframe_index_(frame),
69 object_length_(length),
70 duplicate_object_(duplicate),
71 is_arguments_(is_args) { }
73 Address slot_address() const { return slot_address_; }
74 int jsframe_index() const { return jsframe_index_; }
75 int object_length() const { return object_length_; }
76 int duplicate_object() const { return duplicate_object_; }
77 bool is_arguments() const { return is_arguments_; }
79 // Only used for allocated receivers in DoComputeConstructStubFrame.
80 void patch_slot_address(intptr_t slot) {
81 slot_address_ = reinterpret_cast<Address>(slot);
85 Address slot_address_;
88 int duplicate_object_;
93 class OptimizedFunctionVisitor BASE_EMBEDDED {
95 virtual ~OptimizedFunctionVisitor() {}
97 // Function which is called before iteration of any optimized functions
98 // from given native context.
99 virtual void EnterContext(Context* context) = 0;
101 virtual void VisitFunction(JSFunction* function) = 0;
103 // Function which is called after iteration of all optimized functions
104 // from given native context.
105 virtual void LeaveContext(Context* context) = 0;
109 class Deoptimizer : public Malloced {
115 // This last bailout type is not really a bailout, but used by the
116 // debugger to deoptimize stack frames to allow inspection.
120 static const int kBailoutTypesWithCodeEntry = SOFT + 1;
123 Reason(int r, const char* m, const char* d)
124 : raw_position(r), mnemonic(m), detail(d) {}
126 bool operator==(const Reason& other) const {
127 return raw_position == other.raw_position &&
128 CStringEquals(mnemonic, other.mnemonic) &&
129 CStringEquals(detail, other.detail);
132 bool operator!=(const Reason& other) const { return !(*this == other); }
135 const char* mnemonic;
139 struct JumpTableEntry : public ZoneObject {
140 inline JumpTableEntry(Address entry, const Reason& the_reason,
141 Deoptimizer::BailoutType type, bool frame)
146 needs_frame(frame) {}
148 bool IsEquivalentTo(const JumpTableEntry& other) const {
149 return address == other.address && bailout_type == other.bailout_type &&
150 needs_frame == other.needs_frame &&
151 (!FLAG_trace_deopt || reason == other.reason);
157 Deoptimizer::BailoutType bailout_type;
161 static bool TraceEnabledFor(BailoutType deopt_type,
162 StackFrame::Type frame_type);
163 static const char* MessageFor(BailoutType type);
165 int output_count() const { return output_count_; }
167 Handle<JSFunction> function() const { return Handle<JSFunction>(function_); }
168 Handle<Code> compiled_code() const { return Handle<Code>(compiled_code_); }
169 BailoutType bailout_type() const { return bailout_type_; }
171 // Number of created JS frames. Not all created frames are necessarily JS.
172 int jsframe_count() const { return jsframe_count_; }
174 static Deoptimizer* New(JSFunction* function,
180 static Deoptimizer* Grab(Isolate* isolate);
182 // The returned object with information on the optimized frame needs to be
183 // freed before another one can be generated.
184 static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame,
187 static void DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
190 // Makes sure that there is enough room in the relocation
191 // information of a code object to perform lazy deoptimization
192 // patching. If there is not enough room a new relocation
193 // information object is allocated and comments are added until it
195 static void EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code);
197 // Deoptimize the function now. Its current optimized code will never be run
198 // again and any activations of the optimized code will get deoptimized when
199 // execution returns.
200 static void DeoptimizeFunction(JSFunction* function);
202 // Deoptimize all code in the given isolate.
203 static void DeoptimizeAll(Isolate* isolate);
205 // Deoptimize code associated with the given global object.
206 static void DeoptimizeGlobalObject(JSObject* object);
208 // Deoptimizes all optimized code that has been previously marked
209 // (via code->set_marked_for_deoptimization) and unlinks all functions that
210 // refer to that code.
211 static void DeoptimizeMarkedCode(Isolate* isolate);
213 // Visit all the known optimized functions in a given isolate.
214 static void VisitAllOptimizedFunctions(
215 Isolate* isolate, OptimizedFunctionVisitor* visitor);
217 // The size in bytes of the code required at a lazy deopt patch site.
218 static int patch_size();
222 void MaterializeHeapObjects(JavaScriptFrameIterator* it);
224 void MaterializeHeapNumbersForDebuggerInspectableFrame(
225 Address parameters_top,
226 uint32_t parameters_size,
227 Address expressions_top,
228 uint32_t expressions_size,
229 DeoptimizedFrameInfo* info);
231 static void ComputeOutputFrames(Deoptimizer* deoptimizer);
235 CALCULATE_ENTRY_ADDRESS,
240 static Address GetDeoptimizationEntry(
244 GetEntryMode mode = ENSURE_ENTRY_CODE);
245 static int GetDeoptimizationId(Isolate* isolate,
248 static int GetOutputInfo(DeoptimizationOutputData* data,
250 SharedFunctionInfo* shared);
252 // Code generation support.
253 static int input_offset() { return OFFSET_OF(Deoptimizer, input_); }
254 static int output_count_offset() {
255 return OFFSET_OF(Deoptimizer, output_count_);
257 static int output_offset() { return OFFSET_OF(Deoptimizer, output_); }
259 static int has_alignment_padding_offset() {
260 return OFFSET_OF(Deoptimizer, has_alignment_padding_);
263 static int GetDeoptimizedCodeCount(Isolate* isolate);
265 static const int kNotDeoptimizationEntry = -1;
267 // Generators for the deoptimization entry code.
268 class EntryGenerator BASE_EMBEDDED {
270 EntryGenerator(MacroAssembler* masm, BailoutType type)
271 : masm_(masm), type_(type) { }
272 virtual ~EntryGenerator() { }
277 MacroAssembler* masm() const { return masm_; }
278 BailoutType type() const { return type_; }
279 Isolate* isolate() const { return masm_->isolate(); }
281 virtual void GeneratePrologue() { }
284 MacroAssembler* masm_;
285 Deoptimizer::BailoutType type_;
288 class TableEntryGenerator : public EntryGenerator {
290 TableEntryGenerator(MacroAssembler* masm, BailoutType type, int count)
291 : EntryGenerator(masm, type), count_(count) { }
294 virtual void GeneratePrologue();
297 int count() const { return count_; }
302 int ConvertJSFrameIndexToFrameIndex(int jsframe_index);
304 static size_t GetMaxDeoptTableSize();
306 static void EnsureCodeForDeoptimizationEntry(Isolate* isolate,
310 Isolate* isolate() const { return isolate_; }
313 static const int kMinNumberOfEntries = 64;
314 static const int kMaxNumberOfEntries = 16384;
316 Deoptimizer(Isolate* isolate,
317 JSFunction* function,
322 Code* optimized_code);
323 Code* FindOptimizedCode(JSFunction* function, Code* optimized_code);
324 void PrintFunctionName();
325 void DeleteFrameDescriptions();
327 void DoComputeOutputFrames();
328 void DoComputeJSFrame(TranslationIterator* iterator, int frame_index);
329 void DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
331 void DoComputeConstructStubFrame(TranslationIterator* iterator,
333 void DoComputeAccessorStubFrame(TranslationIterator* iterator,
335 bool is_setter_stub_frame);
336 void DoComputeCompiledStubFrame(TranslationIterator* iterator,
339 // Translate object, store the result into an auxiliary array
340 // (deferred_objects_tagged_values_).
341 void DoTranslateObject(TranslationIterator* iterator,
345 // Translate value, store the result into the given frame slot.
346 void DoTranslateCommand(TranslationIterator* iterator,
348 unsigned output_offset);
350 // Translate object, do not store the result anywhere (but do update
351 // the deferred materialization array).
352 void DoTranslateObjectAndSkip(TranslationIterator* iterator);
354 unsigned ComputeInputFrameSize() const;
355 unsigned ComputeFixedSize(JSFunction* function) const;
357 unsigned ComputeIncomingArgumentSize(JSFunction* function) const;
358 unsigned ComputeOutgoingArgumentSize() const;
360 Object* ComputeLiteral(int index) const;
362 void AddObjectStart(intptr_t slot_address, int argc, bool is_arguments);
363 void AddObjectDuplication(intptr_t slot, int object_index);
364 void AddObjectTaggedValue(intptr_t value);
365 void AddObjectDoubleValue(double value);
366 void AddObjectSIMD128Value(simd128_value_t value, int translation_opcode);
367 void AddDoubleValue(intptr_t slot_address, double value);
368 void AddSIMD128Value(intptr_t slot_address, simd128_value_t value,
369 int translation_opcode);
371 bool ArgumentsObjectIsAdapted(int object_index) {
372 ObjectMaterializationDescriptor desc = deferred_objects_.at(object_index);
373 int reverse_jsframe_index = jsframe_count_ - desc.jsframe_index() - 1;
374 return jsframe_has_adapted_arguments_[reverse_jsframe_index];
377 Handle<JSFunction> ArgumentsObjectFunction(int object_index) {
378 ObjectMaterializationDescriptor desc = deferred_objects_.at(object_index);
379 int reverse_jsframe_index = jsframe_count_ - desc.jsframe_index() - 1;
380 return jsframe_functions_[reverse_jsframe_index];
383 // Helper function for heap object materialization.
384 Handle<Object> MaterializeNextHeapObject();
385 Handle<Object> MaterializeNextValue();
387 static void GenerateDeoptimizationEntries(
388 MacroAssembler* masm, int count, BailoutType type);
390 // Marks all the code in the given context for deoptimization.
391 static void MarkAllCodeForContext(Context* native_context);
393 // Visit all the known optimized functions in a given context.
394 static void VisitAllOptimizedFunctionsForContext(
395 Context* context, OptimizedFunctionVisitor* visitor);
397 // Deoptimizes all code marked in the given context.
398 static void DeoptimizeMarkedCodeForContext(Context* native_context);
400 // Patch the given code so that it will deoptimize itself.
401 static void PatchCodeForDeoptimization(Isolate* isolate, Code* code);
403 // Searches the list of known deoptimizing code for a Code object
404 // containing the given address (which is supposedly faster than
405 // searching all code objects).
406 Code* FindDeoptimizingCode(Address addr);
408 // Fill the input from from a JavaScript frame. This is used when
409 // the debugger needs to inspect an optimized frame. For normal
410 // deoptimizations the input frame is filled in generated code.
411 void FillInputFrame(Address tos, JavaScriptFrame* frame);
413 // Fill the given output frame's registers to contain the failure handler
414 // address and the number of parameters for a stub failure trampoline.
415 void SetPlatformCompiledStubRegisters(FrameDescription* output_frame,
416 CodeStubDescriptor* desc);
418 // Fill the given output frame's double registers with the original values
419 // from the input frame's double registers.
420 void CopyDoubleRegisters(FrameDescription* output_frame);
422 // Fill the given output frame's simd128 registers with the original values
423 // from the input frame's simd128 registers.
424 void CopySIMD128Registers(FrameDescription* output_frame);
426 // Determines whether the input frame contains alignment padding by looking
427 // at the dynamic alignment state slot inside the frame.
428 bool HasAlignmentPadding(JSFunction* function);
431 JSFunction* function_;
432 Code* compiled_code_;
433 unsigned bailout_id_;
434 BailoutType bailout_type_;
437 int has_alignment_padding_;
439 // Input frame description.
440 FrameDescription* input_;
441 // Number of output frames.
443 // Number of output js frames.
445 // Array of output frame descriptions.
446 FrameDescription** output_;
448 // Deferred values to be materialized.
449 List<Object*> deferred_objects_tagged_values_;
450 List<HeapNumberMaterializationDescriptor<int> >
451 deferred_objects_double_values_;
452 List<SIMD128MaterializationDescriptor<int> >
453 deferred_objects_float32x4_values_;
454 List<SIMD128MaterializationDescriptor<int> >
455 deferred_objects_float64x2_values_;
456 List<SIMD128MaterializationDescriptor<int> >
457 deferred_objects_int32x4_values_;
458 List<ObjectMaterializationDescriptor> deferred_objects_;
459 List<HeapNumberMaterializationDescriptor<Address> > deferred_heap_numbers_;
460 List<SIMD128MaterializationDescriptor<Address> > deferred_float32x4s_;
461 List<SIMD128MaterializationDescriptor<Address> > deferred_float64x2s_;
462 List<SIMD128MaterializationDescriptor<Address> > deferred_int32x4s_;
464 // Key for lookup of previously materialized objects
466 Handle<FixedArray> previously_materialized_objects_;
467 int prev_materialized_count_;
469 // Output frame information. Only used during heap object materialization.
470 List<Handle<JSFunction> > jsframe_functions_;
471 List<bool> jsframe_has_adapted_arguments_;
473 // Materialized objects. Only used during heap object materialization.
474 List<Handle<Object> >* materialized_values_;
475 List<Handle<Object> >* materialized_objects_;
476 int materialization_value_index_;
477 int materialization_object_index_;
480 DisallowHeapAllocation* disallow_heap_allocation_;
483 CodeTracer::Scope* trace_scope_;
485 static const int table_entry_size_;
487 friend class FrameDescription;
488 friend class DeoptimizedFrameInfo;
492 class FrameDescription {
494 FrameDescription(uint32_t frame_size,
495 JSFunction* function);
497 void* operator new(size_t size, uint32_t frame_size) {
498 // Subtracts kPointerSize, as the member frame_content_ already supplies
499 // the first element of the area to store the frame.
500 return malloc(size + frame_size - kPointerSize);
503 void operator delete(void* pointer, uint32_t frame_size) {
507 void operator delete(void* description) {
511 uint32_t GetFrameSize() const {
512 DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_);
513 return static_cast<uint32_t>(frame_size_);
516 JSFunction* GetFunction() const { return function_; }
518 unsigned GetOffsetFromSlotIndex(int slot_index);
520 intptr_t GetFrameSlot(unsigned offset) {
521 return *GetFrameSlotPointer(offset);
524 double GetDoubleFrameSlot(unsigned offset) {
525 intptr_t* ptr = GetFrameSlotPointer(offset);
526 return read_double_value(reinterpret_cast<Address>(ptr));
529 simd128_value_t GetSIMD128FrameSlot(unsigned offset) {
530 intptr_t* ptr = GetFrameSlotPointer(offset);
531 return read_simd128_value(reinterpret_cast<Address>(ptr));
534 void SetFrameSlot(unsigned offset, intptr_t value) {
535 *GetFrameSlotPointer(offset) = value;
538 void SetCallerPc(unsigned offset, intptr_t value);
540 void SetCallerFp(unsigned offset, intptr_t value);
542 void SetCallerConstantPool(unsigned offset, intptr_t value);
544 intptr_t GetRegister(unsigned n) const {
546 // This convoluted DCHECK is needed to work around a gcc problem that
547 // improperly detects an array bounds overflow in optimized debug builds
548 // when using a plain DCHECK.
549 if (n >= arraysize(registers_)) {
554 return registers_[n];
557 double GetDoubleRegister(unsigned n) const;
559 simd128_value_t GetSIMD128Register(unsigned n) const;
561 void SetRegister(unsigned n, intptr_t value) {
562 DCHECK(n < arraysize(registers_));
563 registers_[n] = value;
566 void SetDoubleRegister(unsigned n, double value);
568 void SetSIMD128Register(unsigned n, simd128_value_t value);
570 intptr_t GetTop() const { return top_; }
571 void SetTop(intptr_t top) { top_ = top; }
573 intptr_t GetPc() const { return pc_; }
574 void SetPc(intptr_t pc) { pc_ = pc; }
576 intptr_t GetFp() const { return fp_; }
577 void SetFp(intptr_t fp) { fp_ = fp; }
579 intptr_t GetContext() const { return context_; }
580 void SetContext(intptr_t context) { context_ = context; }
582 intptr_t GetConstantPool() const { return constant_pool_; }
583 void SetConstantPool(intptr_t constant_pool) {
584 constant_pool_ = constant_pool;
587 Smi* GetState() const { return state_; }
588 void SetState(Smi* state) { state_ = state; }
590 void SetContinuation(intptr_t pc) { continuation_ = pc; }
592 StackFrame::Type GetFrameType() const { return type_; }
593 void SetFrameType(StackFrame::Type type) { type_ = type; }
595 // Get the incoming arguments count.
596 int ComputeParametersCount();
598 // Get a parameter value for an unoptimized frame.
599 Object* GetParameter(int index);
601 // Get the expression stack height for a unoptimized frame.
602 unsigned GetExpressionCount();
604 // Get the expression stack value for an unoptimized frame.
605 Object* GetExpression(int index);
607 static int registers_offset() {
608 return OFFSET_OF(FrameDescription, registers_);
611 static int double_registers_offset();
613 static int simd128_registers_offset();
615 static int frame_size_offset() {
616 return OFFSET_OF(FrameDescription, frame_size_);
619 static int pc_offset() {
620 return OFFSET_OF(FrameDescription, pc_);
623 static int state_offset() {
624 return OFFSET_OF(FrameDescription, state_);
627 static int continuation_offset() {
628 return OFFSET_OF(FrameDescription, continuation_);
631 static int frame_content_offset() {
632 return OFFSET_OF(FrameDescription, frame_content_);
636 static const uint32_t kZapUint32 = 0xbeeddead;
638 // Frame_size_ must hold a uint32_t value. It is only a uintptr_t to
639 // keep the variable-size array frame_content_ of type intptr_t at
640 // the end of the structure aligned.
641 uintptr_t frame_size_; // Number of bytes.
642 JSFunction* function_;
643 intptr_t registers_[Register::kNumRegisters];
644 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM
645 // For these architectures, the simd128 registers cover the double registers.
646 simd128_value_t simd128_registers_[SIMD128Register::kMaxNumRegisters];
648 double double_registers_[DoubleRegister::kMaxNumRegisters];
654 intptr_t constant_pool_;
655 StackFrame::Type type_;
658 // Continuation is the PC where the execution continues after
660 intptr_t continuation_;
662 // This must be at the end of the object as the object is allocated larger
663 // than it's definition indicate to extend this array.
664 intptr_t frame_content_[1];
666 intptr_t* GetFrameSlotPointer(unsigned offset) {
667 DCHECK(offset < frame_size_);
668 return reinterpret_cast<intptr_t*>(
669 reinterpret_cast<Address>(this) + frame_content_offset() + offset);
672 int ComputeFixedSize();
676 class DeoptimizerData {
678 explicit DeoptimizerData(MemoryAllocator* allocator);
681 void Iterate(ObjectVisitor* v);
684 MemoryAllocator* allocator_;
685 int deopt_entry_code_entries_[Deoptimizer::kBailoutTypesWithCodeEntry];
686 MemoryChunk* deopt_entry_code_[Deoptimizer::kBailoutTypesWithCodeEntry];
688 DeoptimizedFrameInfo* deoptimized_frame_info_;
690 Deoptimizer* current_;
692 friend class Deoptimizer;
694 DISALLOW_COPY_AND_ASSIGN(DeoptimizerData);
698 class TranslationBuffer BASE_EMBEDDED {
700 explicit TranslationBuffer(Zone* zone) : contents_(256, zone) { }
702 int CurrentIndex() const { return contents_.length(); }
703 void Add(int32_t value, Zone* zone);
705 Handle<ByteArray> CreateByteArray(Factory* factory);
708 ZoneList<uint8_t> contents_;
712 class TranslationIterator BASE_EMBEDDED {
714 TranslationIterator(ByteArray* buffer, int index)
715 : buffer_(buffer), index_(index) {
716 DCHECK(index >= 0 && index < buffer->length());
721 bool HasNext() const { return index_ < buffer_->length(); }
724 for (int i = 0; i < n; i++) Next();
733 #define TRANSLATION_OPCODE_LIST(V) \
736 V(CONSTRUCT_STUB_FRAME) \
737 V(GETTER_STUB_FRAME) \
738 V(SETTER_STUB_FRAME) \
739 V(ARGUMENTS_ADAPTOR_FRAME) \
740 V(COMPILED_STUB_FRAME) \
741 V(DUPLICATED_OBJECT) \
742 V(ARGUMENTS_OBJECT) \
748 V(FLOAT32x4_REGISTER) \
749 V(FLOAT64x2_REGISTER) \
750 V(INT32x4_REGISTER) \
752 V(INT32_STACK_SLOT) \
753 V(UINT32_STACK_SLOT) \
754 V(DOUBLE_STACK_SLOT) \
755 V(FLOAT32x4_STACK_SLOT) \
756 V(FLOAT64x2_STACK_SLOT) \
757 V(INT32x4_STACK_SLOT) \
761 class Translation BASE_EMBEDDED {
763 #define DECLARE_TRANSLATION_OPCODE_ENUM(item) item,
765 TRANSLATION_OPCODE_LIST(DECLARE_TRANSLATION_OPCODE_ENUM)
768 #undef DECLARE_TRANSLATION_OPCODE_ENUM
770 Translation(TranslationBuffer* buffer, int frame_count, int jsframe_count,
773 index_(buffer->CurrentIndex()),
775 buffer_->Add(BEGIN, zone);
776 buffer_->Add(frame_count, zone);
777 buffer_->Add(jsframe_count, zone);
780 int index() const { return index_; }
783 void BeginJSFrame(BailoutId node_id, int literal_id, unsigned height);
784 void BeginCompiledStubFrame();
785 void BeginArgumentsAdaptorFrame(int literal_id, unsigned height);
786 void BeginConstructStubFrame(int literal_id, unsigned height);
787 void BeginGetterStubFrame(int literal_id);
788 void BeginSetterStubFrame(int literal_id);
789 void BeginArgumentsObject(int args_length);
790 void BeginCapturedObject(int length);
791 void DuplicateObject(int object_index);
792 void StoreRegister(Register reg);
793 void StoreInt32Register(Register reg);
794 void StoreUint32Register(Register reg);
795 void StoreDoubleRegister(DoubleRegister reg);
796 void StoreSIMD128Register(SIMD128Register reg, Opcode opcode);
797 void StoreStackSlot(int index);
798 void StoreInt32StackSlot(int index);
799 void StoreUint32StackSlot(int index);
800 void StoreDoubleStackSlot(int index);
801 void StoreSIMD128StackSlot(int index, Opcode opcode);
802 void StoreLiteral(int literal_id);
803 void StoreArgumentsObject(bool args_known, int args_index, int args_length);
805 Zone* zone() const { return zone_; }
807 static int NumberOfOperandsFor(Opcode opcode);
809 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
810 static const char* StringFor(Opcode opcode);
813 // A literal id which refers to the JSFunction itself.
814 static const int kSelfLiteralId = -239;
817 TranslationBuffer* buffer_;
823 class SlotRef BASE_EMBEDDED {
825 enum SlotRepresentation {
835 DEFERRED_OBJECT, // Object captured by the escape analysis.
836 // The number of nested objects can be obtained
837 // with the DeferredObjectLength() method
838 // (the SlotRefs of the nested objects follow
839 // this SlotRef in the depth-first order.)
840 DUPLICATE_OBJECT, // Duplicated object of a deferred object.
841 ARGUMENTS_OBJECT // Arguments object - only used to keep indexing
842 // in sync, it should not be materialized.
846 : addr_(NULL), representation_(UNKNOWN) { }
848 SlotRef(Address addr, SlotRepresentation representation)
849 : addr_(addr), representation_(representation) { }
851 SlotRef(Isolate* isolate, Object* literal)
852 : literal_(literal, isolate), representation_(LITERAL) { }
854 static SlotRef NewArgumentsObject(int length) {
856 slot.representation_ = ARGUMENTS_OBJECT;
857 slot.deferred_object_length_ = length;
861 static SlotRef NewDeferredObject(int length) {
863 slot.representation_ = DEFERRED_OBJECT;
864 slot.deferred_object_length_ = length;
868 SlotRepresentation Representation() { return representation_; }
870 static SlotRef NewDuplicateObject(int id) {
872 slot.representation_ = DUPLICATE_OBJECT;
873 slot.duplicate_object_id_ = id;
877 int GetChildrenCount() {
878 if (representation_ == DEFERRED_OBJECT ||
879 representation_ == ARGUMENTS_OBJECT) {
880 return deferred_object_length_;
886 int DuplicateObjectId() { return duplicate_object_id_; }
888 Handle<Object> GetValue(Isolate* isolate);
892 Handle<Object> literal_;
893 SlotRepresentation representation_;
894 int deferred_object_length_;
895 int duplicate_object_id_;
898 class SlotRefValueBuilder BASE_EMBEDDED {
901 JavaScriptFrame* frame,
902 int inlined_frame_index,
903 int formal_parameter_count);
905 void Prepare(Isolate* isolate);
906 Handle<Object> GetNext(Isolate* isolate, int level);
907 void Finish(Isolate* isolate);
909 int args_length() { return args_length_; }
912 List<Handle<Object> > materialized_objects_;
913 Handle<FixedArray> previously_materialized_objects_;
914 int prev_materialized_count_;
915 Address stack_frame_id_;
916 List<SlotRef> slot_refs_;
919 int first_slot_index_;
921 static SlotRef ComputeSlotForNextArgument(
922 Translation::Opcode opcode,
923 TranslationIterator* iterator,
924 DeoptimizationInputData* data,
925 JavaScriptFrame* frame);
927 Handle<Object> GetPreviouslyMaterialized(Isolate* isolate, int length);
929 static Address SlotAddress(JavaScriptFrame* frame, int slot_index) {
930 if (slot_index >= 0) {
931 const int offset = JavaScriptFrameConstants::kLocal0Offset;
932 return frame->fp() + offset - (slot_index * kPointerSize);
934 const int offset = JavaScriptFrameConstants::kLastParameterOffset;
935 return frame->fp() + offset - ((slot_index + 1) * kPointerSize);
939 Handle<Object> GetDeferredObject(Isolate* isolate);
942 class MaterializedObjectStore {
944 explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) {
947 Handle<FixedArray> Get(Address fp);
948 void Set(Address fp, Handle<FixedArray> materialized_objects);
949 void Remove(Address fp);
952 Isolate* isolate() { return isolate_; }
953 Handle<FixedArray> GetStackEntries();
954 Handle<FixedArray> EnsureStackEntries(int size);
956 int StackIdToIndex(Address fp);
959 List<Address> frame_fps_;
963 // Class used to represent an unoptimized frame when the debugger
964 // needs to inspect a frame that is part of an optimized frame. The
965 // internally used FrameDescription objects are not GC safe so for use
966 // by the debugger frame information is copied to an object of this type.
967 // Represents parameters in unadapted form so their number might mismatch
968 // formal parameter count.
969 class DeoptimizedFrameInfo : public Malloced {
971 DeoptimizedFrameInfo(Deoptimizer* deoptimizer,
973 bool has_arguments_adaptor,
974 bool has_construct_stub);
975 virtual ~DeoptimizedFrameInfo();
978 void Iterate(ObjectVisitor* v);
980 // Return the number of incoming arguments.
981 int parameters_count() { return parameters_count_; }
983 // Return the height of the expression stack.
984 int expression_count() { return expression_count_; }
986 // Get the frame function.
987 JSFunction* GetFunction() {
991 // Get the frame context.
992 Object* GetContext() { return context_; }
994 // Check if this frame is preceded by construct stub frame. The bottom-most
995 // inlined frame might still be called by an uninlined construct stub.
996 bool HasConstructStub() {
997 return has_construct_stub_;
1000 // Get an incoming argument.
1001 Object* GetParameter(int index) {
1002 DCHECK(0 <= index && index < parameters_count());
1003 return parameters_[index];
1006 // Get an expression from the expression stack.
1007 Object* GetExpression(int index) {
1008 DCHECK(0 <= index && index < expression_count());
1009 return expression_stack_[index];
1012 int GetSourcePosition() {
1013 return source_position_;
1017 // Set an incoming argument.
1018 void SetParameter(int index, Object* obj) {
1019 DCHECK(0 <= index && index < parameters_count());
1020 parameters_[index] = obj;
1023 // Set an expression on the expression stack.
1024 void SetExpression(int index, Object* obj) {
1025 DCHECK(0 <= index && index < expression_count());
1026 expression_stack_[index] = obj;
1029 JSFunction* function_;
1031 bool has_construct_stub_;
1032 int parameters_count_;
1033 int expression_count_;
1034 Object** parameters_;
1035 Object** expression_stack_;
1036 int source_position_;
1038 friend class Deoptimizer;
1041 } } // namespace v8::internal
1043 #endif // V8_DEOPTIMIZER_H_