[stubs] Unify (and optimize) implementation of ToObject.
[platform/upstream/v8.git] / src / deoptimizer.h
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.
4
5 #ifndef V8_DEOPTIMIZER_H_
6 #define V8_DEOPTIMIZER_H_
7
8 #include "src/v8.h"
9
10 #include "src/allocation.h"
11 #include "src/macro-assembler.h"
12
13
14 namespace v8 {
15 namespace internal {
16
17 class FrameDescription;
18 class TranslationIterator;
19 class DeoptimizedFrameInfo;
20 class TranslatedState;
21 class RegisterValues;
22
23 class TranslatedValue {
24  public:
25   // Allocation-less getter of the value.
26   // Returns heap()->arguments_marker() if allocation would be
27   // necessary to get the value.
28   Object* GetRawValue() const;
29   Handle<Object> GetValue();
30
31   bool IsMaterializedObject() const;
32
33  private:
34   friend class TranslatedState;
35   friend class TranslatedFrame;
36
37   enum Kind {
38     kInvalid,
39     kTagged,
40     kInt32,
41     kUInt32,
42     kBoolBit,
43     kDouble,
44     kCapturedObject,    // Object captured by the escape analysis.
45                         // The number of nested objects can be obtained
46                         // with the DeferredObjectLength() method
47                         // (the values of the nested objects follow
48                         // this value in the depth-first order.)
49     kDuplicatedObject,  // Duplicated object of a deferred object.
50     kArgumentsObject    // Arguments object - only used to keep indexing
51                         // in sync, it should not be materialized.
52   };
53
54   TranslatedValue(TranslatedState* container, Kind kind)
55       : kind_(kind), container_(container) {}
56   Kind kind() const { return kind_; }
57   void Handlify();
58   int GetChildrenCount() const;
59
60   static TranslatedValue NewArgumentsObject(TranslatedState* container,
61                                             int length, int object_index);
62   static TranslatedValue NewDeferredObject(TranslatedState* container,
63                                            int length, int object_index);
64   static TranslatedValue NewDuplicateObject(TranslatedState* container, int id);
65   static TranslatedValue NewDouble(TranslatedState* container, double value);
66   static TranslatedValue NewInt32(TranslatedState* container, int32_t value);
67   static TranslatedValue NewUInt32(TranslatedState* container, uint32_t value);
68   static TranslatedValue NewBool(TranslatedState* container, uint32_t value);
69   static TranslatedValue NewTagged(TranslatedState* container, Object* literal);
70   static TranslatedValue NewInvalid(TranslatedState* container);
71
72   Isolate* isolate() const;
73   void MaterializeSimple();
74
75   Kind kind_;
76   TranslatedState* container_;  // This is only needed for materialization of
77                                 // objects and constructing handles (to get
78                                 // to the isolate).
79
80   MaybeHandle<Object> value_;  // Before handlification, this is always null,
81                                // after materialization it is never null,
82                                // in between it is only null if the value needs
83                                // to be materialized.
84
85   struct MaterializedObjectInfo {
86     int id_;
87     int length_;  // Applies only to kArgumentsObject or kCapturedObject kinds.
88   };
89
90   union {
91     // kind kTagged. After handlification it is always nullptr.
92     Object* raw_literal_;
93     // kind is kUInt32 or kBoolBit.
94     uint32_t uint32_value_;
95     // kind is kInt32.
96     int32_t int32_value_;
97     // kind is kDouble
98     double double_value_;
99     // kind is kDuplicatedObject or kArgumentsObject or kCapturedObject.
100     MaterializedObjectInfo materialization_info_;
101   };
102
103   // Checked accessors for the union members.
104   Object* raw_literal() const;
105   int32_t int32_value() const;
106   uint32_t uint32_value() const;
107   double double_value() const;
108   int object_length() const;
109   int object_index() const;
110 };
111
112
113 class TranslatedFrame {
114  public:
115   enum Kind {
116     kFunction,
117     kGetter,
118     kSetter,
119     kArgumentsAdaptor,
120     kConstructStub,
121     kCompiledStub,
122     kInvalid
123   };
124
125   int GetValueCount();
126
127   Kind kind() const { return kind_; }
128   BailoutId node_id() const { return node_id_; }
129   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
130   int height() const { return height_; }
131
132   class iterator {
133    public:
134     iterator& operator++() {
135       AdvanceIterator(&position_);
136       return *this;
137     }
138
139     iterator operator++(int) {
140       iterator original(position_);
141       AdvanceIterator(&position_);
142       return original;
143     }
144
145     bool operator==(const iterator& other) const {
146       return position_ == other.position_;
147     }
148     bool operator!=(const iterator& other) const { return !(*this == other); }
149
150     TranslatedValue& operator*() { return (*position_); }
151     TranslatedValue* operator->() { return &(*position_); }
152
153    private:
154     friend TranslatedFrame;
155
156     explicit iterator(std::deque<TranslatedValue>::iterator position)
157         : position_(position) {}
158
159     std::deque<TranslatedValue>::iterator position_;
160   };
161
162   typedef TranslatedValue& reference;
163   typedef TranslatedValue const& const_reference;
164
165   iterator begin() { return iterator(values_.begin()); }
166   iterator end() { return iterator(values_.end()); }
167
168   reference front() { return values_.front(); }
169   const_reference front() const { return values_.front(); }
170
171  private:
172   friend class TranslatedState;
173
174   // Constructor static methods.
175   static TranslatedFrame JSFrame(BailoutId node_id,
176                                  SharedFunctionInfo* shared_info, int height);
177   static TranslatedFrame AccessorFrame(Kind kind,
178                                        SharedFunctionInfo* shared_info);
179   static TranslatedFrame ArgumentsAdaptorFrame(SharedFunctionInfo* shared_info,
180                                                int height);
181   static TranslatedFrame ConstructStubFrame(SharedFunctionInfo* shared_info,
182                                             int height);
183   static TranslatedFrame CompiledStubFrame(int height, Isolate* isolate) {
184     return TranslatedFrame(kCompiledStub, isolate, nullptr, height);
185   }
186   static TranslatedFrame InvalidFrame() {
187     return TranslatedFrame(kInvalid, nullptr);
188   }
189
190   static void AdvanceIterator(std::deque<TranslatedValue>::iterator* iter);
191
192   TranslatedFrame(Kind kind, Isolate* isolate,
193                   SharedFunctionInfo* shared_info = nullptr, int height = 0)
194       : kind_(kind),
195         node_id_(BailoutId::None()),
196         raw_shared_info_(shared_info),
197         height_(height),
198         isolate_(isolate) {}
199
200
201   void Add(const TranslatedValue& value) { values_.push_back(value); }
202   void Handlify();
203
204   Kind kind_;
205   BailoutId node_id_;
206   SharedFunctionInfo* raw_shared_info_;
207   Handle<SharedFunctionInfo> shared_info_;
208   int height_;
209   Isolate* isolate_;
210
211   typedef std::deque<TranslatedValue> ValuesContainer;
212
213   ValuesContainer values_;
214 };
215
216
217 // Auxiliary class for translating deoptimization values.
218 // Typical usage sequence:
219 //
220 // 1. Construct the instance. This will involve reading out the translations
221 //    and resolving them to values using the supplied frame pointer and
222 //    machine state (registers). This phase is guaranteed not to allocate
223 //    and not to use any HandleScope. Any object pointers will be stored raw.
224 //
225 // 2. Handlify pointers. This will convert all the raw pointers to handles.
226 //
227 // 3. Reading out the frame values.
228 //
229 // Note: After the instance is constructed, it is possible to iterate over
230 // the values eagerly.
231
232 class TranslatedState {
233  public:
234   TranslatedState();
235   explicit TranslatedState(JavaScriptFrame* frame);
236
237   void Prepare(bool has_adapted_arguments, Address stack_frame_pointer);
238
239   // Store newly materialized values into the isolate.
240   void StoreMaterializedValuesAndDeopt();
241
242   typedef std::vector<TranslatedFrame>::iterator iterator;
243   iterator begin() { return frames_.begin(); }
244   iterator end() { return frames_.end(); }
245
246   typedef std::vector<TranslatedFrame>::const_iterator const_iterator;
247   const_iterator begin() const { return frames_.begin(); }
248   const_iterator end() const { return frames_.end(); }
249
250   std::vector<TranslatedFrame>& frames() { return frames_; }
251
252   TranslatedFrame* GetArgumentsInfoFromJSFrameIndex(int jsframe_index,
253                                                     int* arguments_count);
254
255   Isolate* isolate() { return isolate_; }
256
257   void Init(Address input_frame_pointer, JSFunction* input_frame_function,
258             TranslationIterator* iterator, FixedArray* literal_array,
259             RegisterValues* registers, FILE* trace_file);
260
261  private:
262   friend TranslatedValue;
263
264   TranslatedFrame CreateNextTranslatedFrame(TranslationIterator* iterator,
265                                             FixedArray* literal_array,
266                                             Address fp,
267                                             JSFunction* frame_function,
268                                             FILE* trace_file);
269   TranslatedValue CreateNextTranslatedValue(int frame_index, int value_index,
270                                             TranslationIterator* iterator,
271                                             FixedArray* literal_array,
272                                             Address fp,
273                                             RegisterValues* registers,
274                                             FILE* trace_file);
275
276   void UpdateFromPreviouslyMaterializedObjects();
277   Handle<Object> MaterializeAt(int frame_index, int* value_index);
278   Handle<Object> MaterializeObjectAt(int object_index);
279   bool GetAdaptedArguments(Handle<JSObject>* result, int frame_index);
280
281   static int SlotOffsetFp(int slot_index);
282   static Address SlotAddress(Address fp, int slot_index);
283   static uint32_t GetUInt32Slot(Address fp, int slot_index);
284
285   std::vector<TranslatedFrame> frames_;
286   Isolate* isolate_;
287   Address stack_frame_pointer_;
288   bool has_adapted_arguments_;
289
290   struct ObjectPosition {
291     int frame_index_;
292     int value_index_;
293   };
294   std::deque<ObjectPosition> object_positions_;
295 };
296
297
298 class OptimizedFunctionVisitor BASE_EMBEDDED {
299  public:
300   virtual ~OptimizedFunctionVisitor() {}
301
302   // Function which is called before iteration of any optimized functions
303   // from given native context.
304   virtual void EnterContext(Context* context) = 0;
305
306   virtual void VisitFunction(JSFunction* function) = 0;
307
308   // Function which is called after iteration of all optimized functions
309   // from given native context.
310   virtual void LeaveContext(Context* context) = 0;
311 };
312
313
314 #define DEOPT_MESSAGES_LIST(V)                                                 \
315   V(kNoReason, "no reason")                                                    \
316   V(kConstantGlobalVariableAssignment, "Constant global variable assignment")  \
317   V(kConversionOverflow, "conversion overflow")                                \
318   V(kDivisionByZero, "division by zero")                                       \
319   V(kElementsKindUnhandledInKeyedLoadGenericStub,                              \
320     "ElementsKind unhandled in KeyedLoadGenericStub")                          \
321   V(kExpectedHeapNumber, "Expected heap number")                               \
322   V(kExpectedSmi, "Expected smi")                                              \
323   V(kForcedDeoptToRuntime, "Forced deopt to runtime")                          \
324   V(kHole, "hole")                                                             \
325   V(kHoleyArrayDespitePackedElements_kindFeedback,                             \
326     "Holey array despite packed elements_kind feedback")                       \
327   V(kInstanceMigrationFailed, "instance migration failed")                     \
328   V(kInsufficientTypeFeedbackForCallWithArguments,                             \
329     "Insufficient type feedback for call with arguments")                      \
330   V(kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation,                 \
331     "Insufficient type feedback for combined type of binary operation")        \
332   V(kInsufficientTypeFeedbackForGenericNamedAccess,                            \
333     "Insufficient type feedback for generic named access")                     \
334   V(kInsufficientTypeFeedbackForKeyedLoad,                                     \
335     "Insufficient type feedback for keyed load")                               \
336   V(kInsufficientTypeFeedbackForKeyedStore,                                    \
337     "Insufficient type feedback for keyed store")                              \
338   V(kInsufficientTypeFeedbackForLHSOfBinaryOperation,                          \
339     "Insufficient type feedback for LHS of binary operation")                  \
340   V(kInsufficientTypeFeedbackForRHSOfBinaryOperation,                          \
341     "Insufficient type feedback for RHS of binary operation")                  \
342   V(kKeyIsNegative, "key is negative")                                         \
343   V(kLostPrecision, "lost precision")                                          \
344   V(kLostPrecisionOrNaN, "lost precision or NaN")                              \
345   V(kMementoFound, "memento found")                                            \
346   V(kMinusZero, "minus zero")                                                  \
347   V(kNaN, "NaN")                                                               \
348   V(kNegativeKeyEncountered, "Negative key encountered")                       \
349   V(kNegativeValue, "negative value")                                          \
350   V(kNoCache, "no cache")                                                      \
351   V(kNonStrictElementsInKeyedLoadGenericStub,                                  \
352     "non-strict elements in KeyedLoadGenericStub")                             \
353   V(kNotADateObject, "not a date object")                                      \
354   V(kNotAHeapNumber, "not a heap number")                                      \
355   V(kNotAHeapNumberUndefinedBoolean, "not a heap number/undefined/true/false") \
356   V(kNotAHeapNumberUndefined, "not a heap number/undefined")                   \
357   V(kNotAJavaScriptObject, "not a JavaScript object")                          \
358   V(kNotASmi, "not a Smi")                                                     \
359   V(kNull, "null")                                                             \
360   V(kOutOfBounds, "out of bounds")                                             \
361   V(kOutsideOfRange, "Outside of range")                                       \
362   V(kOverflow, "overflow")                                                     \
363   V(kReceiverWasAGlobalObject, "receiver was a global object")                 \
364   V(kSmi, "Smi")                                                               \
365   V(kTooManyArguments, "too many arguments")                                   \
366   V(kTooManyUndetectableTypes, "Too many undetectable types")                  \
367   V(kTracingElementsTransitions, "Tracing elements transitions")               \
368   V(kTypeMismatchBetweenFeedbackAndConstant,                                   \
369     "Type mismatch between feedback and constant")                             \
370   V(kUndefined, "undefined")                                                   \
371   V(kUnexpectedCellContentsInConstantGlobalStore,                              \
372     "Unexpected cell contents in constant global store")                       \
373   V(kUnexpectedCellContentsInGlobalStore,                                      \
374     "Unexpected cell contents in global store")                                \
375   V(kUnexpectedObject, "unexpected object")                                    \
376   V(kUnexpectedRHSOfBinaryOperation, "Unexpected RHS of binary operation")     \
377   V(kUninitializedBoilerplateInFastClone,                                      \
378     "Uninitialized boilerplate in fast clone")                                 \
379   V(kUninitializedBoilerplateLiterals, "Uninitialized boilerplate literals")   \
380   V(kUnknownMapInPolymorphicAccess, "Unknown map in polymorphic access")       \
381   V(kUnknownMapInPolymorphicCall, "Unknown map in polymorphic call")           \
382   V(kUnknownMapInPolymorphicElementAccess,                                     \
383     "Unknown map in polymorphic element access")                               \
384   V(kUnknownMap, "Unknown map")                                                \
385   V(kValueMismatch, "value mismatch")                                          \
386   V(kWrongInstanceType, "wrong instance type")                                 \
387   V(kWrongMap, "wrong map")                                                    \
388   V(kUndefinedOrNullInForIn, "null or undefined in for-in")                    \
389   V(kUndefinedOrNullInToObject, "null or undefined in ToObject")
390
391
392 class Deoptimizer : public Malloced {
393  public:
394   enum BailoutType {
395     EAGER,
396     LAZY,
397     SOFT,
398     // This last bailout type is not really a bailout, but used by the
399     // debugger to deoptimize stack frames to allow inspection.
400     DEBUGGER,
401     kBailoutTypesWithCodeEntry = SOFT + 1
402   };
403
404 #define DEOPT_MESSAGES_CONSTANTS(C, T) C,
405   enum DeoptReason {
406     DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_CONSTANTS) kLastDeoptReason
407   };
408 #undef DEOPT_MESSAGES_CONSTANTS
409   static const char* GetDeoptReason(DeoptReason deopt_reason);
410
411   struct DeoptInfo {
412     DeoptInfo(SourcePosition position, const char* m, DeoptReason d)
413         : position(position), mnemonic(m), deopt_reason(d), inlining_id(0) {}
414
415     SourcePosition position;
416     const char* mnemonic;
417     DeoptReason deopt_reason;
418     int inlining_id;
419   };
420
421   static DeoptInfo GetDeoptInfo(Code* code, byte* from);
422
423   struct JumpTableEntry : public ZoneObject {
424     inline JumpTableEntry(Address entry, const DeoptInfo& deopt_info,
425                           Deoptimizer::BailoutType type, bool frame)
426         : label(),
427           address(entry),
428           deopt_info(deopt_info),
429           bailout_type(type),
430           needs_frame(frame) {}
431
432     bool IsEquivalentTo(const JumpTableEntry& other) const {
433       return address == other.address && bailout_type == other.bailout_type &&
434              needs_frame == other.needs_frame;
435     }
436
437     Label label;
438     Address address;
439     DeoptInfo deopt_info;
440     Deoptimizer::BailoutType bailout_type;
441     bool needs_frame;
442   };
443
444   static bool TraceEnabledFor(BailoutType deopt_type,
445                               StackFrame::Type frame_type);
446   static const char* MessageFor(BailoutType type);
447
448   int output_count() const { return output_count_; }
449
450   Handle<JSFunction> function() const { return Handle<JSFunction>(function_); }
451   Handle<Code> compiled_code() const { return Handle<Code>(compiled_code_); }
452   BailoutType bailout_type() const { return bailout_type_; }
453
454   // Number of created JS frames. Not all created frames are necessarily JS.
455   int jsframe_count() const { return jsframe_count_; }
456
457   static Deoptimizer* New(JSFunction* function,
458                           BailoutType type,
459                           unsigned bailout_id,
460                           Address from,
461                           int fp_to_sp_delta,
462                           Isolate* isolate);
463   static Deoptimizer* Grab(Isolate* isolate);
464
465   // The returned object with information on the optimized frame needs to be
466   // freed before another one can be generated.
467   static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame,
468                                                         int jsframe_index,
469                                                         Isolate* isolate);
470   static void DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
471                                              Isolate* isolate);
472
473   // Makes sure that there is enough room in the relocation
474   // information of a code object to perform lazy deoptimization
475   // patching. If there is not enough room a new relocation
476   // information object is allocated and comments are added until it
477   // is big enough.
478   static void EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code);
479
480   // Deoptimize the function now. Its current optimized code will never be run
481   // again and any activations of the optimized code will get deoptimized when
482   // execution returns.
483   static void DeoptimizeFunction(JSFunction* function);
484
485   // Deoptimize all code in the given isolate.
486   static void DeoptimizeAll(Isolate* isolate);
487
488   // Deoptimizes all optimized code that has been previously marked
489   // (via code->set_marked_for_deoptimization) and unlinks all functions that
490   // refer to that code.
491   static void DeoptimizeMarkedCode(Isolate* isolate);
492
493   // Visit all the known optimized functions in a given isolate.
494   static void VisitAllOptimizedFunctions(
495       Isolate* isolate, OptimizedFunctionVisitor* visitor);
496
497   // The size in bytes of the code required at a lazy deopt patch site.
498   static int patch_size();
499
500   ~Deoptimizer();
501
502   void MaterializeHeapObjects(JavaScriptFrameIterator* it);
503
504   void MaterializeHeapNumbersForDebuggerInspectableFrame(
505       int frame_index, int parameter_count, int expression_count,
506       DeoptimizedFrameInfo* info);
507
508   static void ComputeOutputFrames(Deoptimizer* deoptimizer);
509
510
511   enum GetEntryMode {
512     CALCULATE_ENTRY_ADDRESS,
513     ENSURE_ENTRY_CODE
514   };
515
516
517   static Address GetDeoptimizationEntry(
518       Isolate* isolate,
519       int id,
520       BailoutType type,
521       GetEntryMode mode = ENSURE_ENTRY_CODE);
522   static int GetDeoptimizationId(Isolate* isolate,
523                                  Address addr,
524                                  BailoutType type);
525   static int GetOutputInfo(DeoptimizationOutputData* data,
526                            BailoutId node_id,
527                            SharedFunctionInfo* shared);
528
529   // Code generation support.
530   static int input_offset() { return OFFSET_OF(Deoptimizer, input_); }
531   static int output_count_offset() {
532     return OFFSET_OF(Deoptimizer, output_count_);
533   }
534   static int output_offset() { return OFFSET_OF(Deoptimizer, output_); }
535
536   static int has_alignment_padding_offset() {
537     return OFFSET_OF(Deoptimizer, has_alignment_padding_);
538   }
539
540   static int GetDeoptimizedCodeCount(Isolate* isolate);
541
542   static const int kNotDeoptimizationEntry = -1;
543
544   // Generators for the deoptimization entry code.
545   class TableEntryGenerator BASE_EMBEDDED {
546    public:
547     TableEntryGenerator(MacroAssembler* masm, BailoutType type, int count)
548         : masm_(masm), type_(type), count_(count) {}
549
550     void Generate();
551
552    protected:
553     MacroAssembler* masm() const { return masm_; }
554     BailoutType type() const { return type_; }
555     Isolate* isolate() const { return masm_->isolate(); }
556
557     void GeneratePrologue();
558
559    private:
560     int count() const { return count_; }
561
562     MacroAssembler* masm_;
563     Deoptimizer::BailoutType type_;
564     int count_;
565   };
566
567   int ConvertJSFrameIndexToFrameIndex(int jsframe_index);
568
569   static size_t GetMaxDeoptTableSize();
570
571   static void EnsureCodeForDeoptimizationEntry(Isolate* isolate,
572                                                BailoutType type,
573                                                int max_entry_id);
574
575   Isolate* isolate() const { return isolate_; }
576
577  private:
578   static const int kMinNumberOfEntries = 64;
579   static const int kMaxNumberOfEntries = 16384;
580
581   Deoptimizer(Isolate* isolate,
582               JSFunction* function,
583               BailoutType type,
584               unsigned bailout_id,
585               Address from,
586               int fp_to_sp_delta,
587               Code* optimized_code);
588   Code* FindOptimizedCode(JSFunction* function, Code* optimized_code);
589   void PrintFunctionName();
590   void DeleteFrameDescriptions();
591
592   void DoComputeOutputFrames();
593   void DoComputeJSFrame(TranslationIterator* iterator, int frame_index);
594   void DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
595                                       int frame_index);
596   void DoComputeConstructStubFrame(TranslationIterator* iterator,
597                                    int frame_index);
598   void DoComputeAccessorStubFrame(TranslationIterator* iterator,
599                                   int frame_index,
600                                   bool is_setter_stub_frame);
601   void DoComputeCompiledStubFrame(TranslationIterator* iterator,
602                                   int frame_index);
603
604   void WriteTranslatedValueToOutput(
605       TranslatedFrame::iterator* iterator, int* input_index, int frame_index,
606       unsigned output_offset, const char* debug_hint_string = nullptr,
607       Address output_address_for_materialization = nullptr);
608   void WriteValueToOutput(Object* value, int input_index, int frame_index,
609                           unsigned output_offset,
610                           const char* debug_hint_string);
611   void DebugPrintOutputSlot(intptr_t value, int frame_index,
612                             unsigned output_offset,
613                             const char* debug_hint_string);
614
615   unsigned ComputeInputFrameSize() const;
616   unsigned ComputeFixedSize(JSFunction* function) const;
617
618   unsigned ComputeIncomingArgumentSize(JSFunction* function) const;
619   unsigned ComputeOutgoingArgumentSize() const;
620
621   Object* ComputeLiteral(int index) const;
622
623   static void GenerateDeoptimizationEntries(
624       MacroAssembler* masm, int count, BailoutType type);
625
626   // Marks all the code in the given context for deoptimization.
627   static void MarkAllCodeForContext(Context* native_context);
628
629   // Visit all the known optimized functions in a given context.
630   static void VisitAllOptimizedFunctionsForContext(
631       Context* context, OptimizedFunctionVisitor* visitor);
632
633   // Deoptimizes all code marked in the given context.
634   static void DeoptimizeMarkedCodeForContext(Context* native_context);
635
636   // Patch the given code so that it will deoptimize itself.
637   static void PatchCodeForDeoptimization(Isolate* isolate, Code* code);
638
639   // Searches the list of known deoptimizing code for a Code object
640   // containing the given address (which is supposedly faster than
641   // searching all code objects).
642   Code* FindDeoptimizingCode(Address addr);
643
644   // Fill the input from from a JavaScript frame. This is used when
645   // the debugger needs to inspect an optimized frame. For normal
646   // deoptimizations the input frame is filled in generated code.
647   void FillInputFrame(Address tos, JavaScriptFrame* frame);
648
649   // Fill the given output frame's registers to contain the failure handler
650   // address and the number of parameters for a stub failure trampoline.
651   void SetPlatformCompiledStubRegisters(FrameDescription* output_frame,
652                                         CodeStubDescriptor* desc);
653
654   // Fill the given output frame's double registers with the original values
655   // from the input frame's double registers.
656   void CopyDoubleRegisters(FrameDescription* output_frame);
657
658   // Determines whether the input frame contains alignment padding by looking
659   // at the dynamic alignment state slot inside the frame.
660   bool HasAlignmentPadding(JSFunction* function);
661
662   Isolate* isolate_;
663   JSFunction* function_;
664   Code* compiled_code_;
665   unsigned bailout_id_;
666   BailoutType bailout_type_;
667   Address from_;
668   int fp_to_sp_delta_;
669   int has_alignment_padding_;
670
671   // Input frame description.
672   FrameDescription* input_;
673   // Number of output frames.
674   int output_count_;
675   // Number of output js frames.
676   int jsframe_count_;
677   // Array of output frame descriptions.
678   FrameDescription** output_;
679
680   // Key for lookup of previously materialized objects
681   Address stack_fp_;
682
683   TranslatedState translated_state_;
684   struct ValueToMaterialize {
685     Address output_slot_address_;
686     TranslatedFrame::iterator value_;
687   };
688   std::vector<ValueToMaterialize> values_to_materialize_;
689
690 #ifdef DEBUG
691   DisallowHeapAllocation* disallow_heap_allocation_;
692 #endif  // DEBUG
693
694   CodeTracer::Scope* trace_scope_;
695
696   static const int table_entry_size_;
697
698   friend class FrameDescription;
699   friend class DeoptimizedFrameInfo;
700 };
701
702
703 class RegisterValues {
704  public:
705   intptr_t GetRegister(unsigned n) const {
706 #if DEBUG
707     // This convoluted DCHECK is needed to work around a gcc problem that
708     // improperly detects an array bounds overflow in optimized debug builds
709     // when using a plain DCHECK.
710     if (n >= arraysize(registers_)) {
711       DCHECK(false);
712       return 0;
713     }
714 #endif
715     return registers_[n];
716   }
717
718   double GetDoubleRegister(unsigned n) const {
719     DCHECK(n < arraysize(double_registers_));
720     return double_registers_[n];
721   }
722
723   void SetRegister(unsigned n, intptr_t value) {
724     DCHECK(n < arraysize(registers_));
725     registers_[n] = value;
726   }
727
728   void SetDoubleRegister(unsigned n, double value) {
729     DCHECK(n < arraysize(double_registers_));
730     double_registers_[n] = value;
731   }
732
733   intptr_t registers_[Register::kNumRegisters];
734   double double_registers_[DoubleRegister::kMaxNumRegisters];
735 };
736
737
738 class FrameDescription {
739  public:
740   FrameDescription(uint32_t frame_size,
741                    JSFunction* function);
742
743   void* operator new(size_t size, uint32_t frame_size) {
744     // Subtracts kPointerSize, as the member frame_content_ already supplies
745     // the first element of the area to store the frame.
746     return malloc(size + frame_size - kPointerSize);
747   }
748
749 // Bug in VS2015 RC, reported fixed in RTM. Microsoft bug: 1153909.
750 #if !defined(_MSC_FULL_VER) || _MSC_FULL_VER != 190022816
751   void operator delete(void* pointer, uint32_t frame_size) {
752     free(pointer);
753   }
754 #endif  // _MSC_FULL_VER
755
756   void operator delete(void* description) {
757     free(description);
758   }
759
760   uint32_t GetFrameSize() const {
761     DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_);
762     return static_cast<uint32_t>(frame_size_);
763   }
764
765   JSFunction* GetFunction() const { return function_; }
766
767   unsigned GetOffsetFromSlotIndex(int slot_index);
768
769   intptr_t GetFrameSlot(unsigned offset) {
770     return *GetFrameSlotPointer(offset);
771   }
772
773   Address GetFramePointerAddress() {
774     int fp_offset = GetFrameSize() -
775                     (ComputeParametersCount() + 1) * kPointerSize -
776                     StandardFrameConstants::kCallerSPOffset;
777     return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset));
778   }
779
780   RegisterValues* GetRegisterValues() { return &register_values_; }
781
782   void SetFrameSlot(unsigned offset, intptr_t value) {
783     *GetFrameSlotPointer(offset) = value;
784   }
785
786   void SetCallerPc(unsigned offset, intptr_t value);
787
788   void SetCallerFp(unsigned offset, intptr_t value);
789
790   void SetCallerConstantPool(unsigned offset, intptr_t value);
791
792   intptr_t GetRegister(unsigned n) const {
793     return register_values_.GetRegister(n);
794   }
795
796   double GetDoubleRegister(unsigned n) const {
797     return register_values_.GetDoubleRegister(n);
798   }
799
800   void SetRegister(unsigned n, intptr_t value) {
801     register_values_.SetRegister(n, value);
802   }
803
804   void SetDoubleRegister(unsigned n, double value) {
805     register_values_.SetDoubleRegister(n, value);
806   }
807
808   intptr_t GetTop() const { return top_; }
809   void SetTop(intptr_t top) { top_ = top; }
810
811   intptr_t GetPc() const { return pc_; }
812   void SetPc(intptr_t pc) { pc_ = pc; }
813
814   intptr_t GetFp() const { return fp_; }
815   void SetFp(intptr_t fp) { fp_ = fp; }
816
817   intptr_t GetContext() const { return context_; }
818   void SetContext(intptr_t context) { context_ = context; }
819
820   intptr_t GetConstantPool() const { return constant_pool_; }
821   void SetConstantPool(intptr_t constant_pool) {
822     constant_pool_ = constant_pool;
823   }
824
825   Smi* GetState() const { return state_; }
826   void SetState(Smi* state) { state_ = state; }
827
828   void SetContinuation(intptr_t pc) { continuation_ = pc; }
829
830   StackFrame::Type GetFrameType() const { return type_; }
831   void SetFrameType(StackFrame::Type type) { type_ = type; }
832
833   // Get the incoming arguments count.
834   int ComputeParametersCount();
835
836   // Get a parameter value for an unoptimized frame.
837   Object* GetParameter(int index);
838
839   // Get the expression stack height for a unoptimized frame.
840   unsigned GetExpressionCount();
841
842   // Get the expression stack value for an unoptimized frame.
843   Object* GetExpression(int index);
844
845   static int registers_offset() {
846     return OFFSET_OF(FrameDescription, register_values_.registers_);
847   }
848
849   static int double_registers_offset() {
850     return OFFSET_OF(FrameDescription, register_values_.double_registers_);
851   }
852
853   static int frame_size_offset() {
854     return offsetof(FrameDescription, frame_size_);
855   }
856
857   static int pc_offset() { return offsetof(FrameDescription, pc_); }
858
859   static int state_offset() { return offsetof(FrameDescription, state_); }
860
861   static int continuation_offset() {
862     return offsetof(FrameDescription, continuation_);
863   }
864
865   static int frame_content_offset() {
866     return offsetof(FrameDescription, frame_content_);
867   }
868
869  private:
870   static const uint32_t kZapUint32 = 0xbeeddead;
871
872   // Frame_size_ must hold a uint32_t value.  It is only a uintptr_t to
873   // keep the variable-size array frame_content_ of type intptr_t at
874   // the end of the structure aligned.
875   uintptr_t frame_size_;  // Number of bytes.
876   JSFunction* function_;
877   RegisterValues register_values_;
878   intptr_t top_;
879   intptr_t pc_;
880   intptr_t fp_;
881   intptr_t context_;
882   intptr_t constant_pool_;
883   StackFrame::Type type_;
884   Smi* state_;
885
886   // Continuation is the PC where the execution continues after
887   // deoptimizing.
888   intptr_t continuation_;
889
890   // This must be at the end of the object as the object is allocated larger
891   // than it's definition indicate to extend this array.
892   intptr_t frame_content_[1];
893
894   intptr_t* GetFrameSlotPointer(unsigned offset) {
895     DCHECK(offset < frame_size_);
896     return reinterpret_cast<intptr_t*>(
897         reinterpret_cast<Address>(this) + frame_content_offset() + offset);
898   }
899
900   int ComputeFixedSize();
901 };
902
903
904 class DeoptimizerData {
905  public:
906   explicit DeoptimizerData(MemoryAllocator* allocator);
907   ~DeoptimizerData();
908
909   void Iterate(ObjectVisitor* v);
910
911  private:
912   MemoryAllocator* allocator_;
913   int deopt_entry_code_entries_[Deoptimizer::kBailoutTypesWithCodeEntry];
914   MemoryChunk* deopt_entry_code_[Deoptimizer::kBailoutTypesWithCodeEntry];
915
916   DeoptimizedFrameInfo* deoptimized_frame_info_;
917
918   Deoptimizer* current_;
919
920   friend class Deoptimizer;
921
922   DISALLOW_COPY_AND_ASSIGN(DeoptimizerData);
923 };
924
925
926 class TranslationBuffer BASE_EMBEDDED {
927  public:
928   explicit TranslationBuffer(Zone* zone) : contents_(256, zone) { }
929
930   int CurrentIndex() const { return contents_.length(); }
931   void Add(int32_t value, Zone* zone);
932
933   Handle<ByteArray> CreateByteArray(Factory* factory);
934
935  private:
936   ZoneList<uint8_t> contents_;
937 };
938
939
940 class TranslationIterator BASE_EMBEDDED {
941  public:
942   TranslationIterator(ByteArray* buffer, int index)
943       : buffer_(buffer), index_(index) {
944     DCHECK(index >= 0 && index < buffer->length());
945   }
946
947   int32_t Next();
948
949   bool HasNext() const { return index_ < buffer_->length(); }
950
951   void Skip(int n) {
952     for (int i = 0; i < n; i++) Next();
953   }
954
955  private:
956   ByteArray* buffer_;
957   int index_;
958 };
959
960
961 #define TRANSLATION_OPCODE_LIST(V) \
962   V(BEGIN)                         \
963   V(JS_FRAME)                      \
964   V(CONSTRUCT_STUB_FRAME)          \
965   V(GETTER_STUB_FRAME)             \
966   V(SETTER_STUB_FRAME)             \
967   V(ARGUMENTS_ADAPTOR_FRAME)       \
968   V(COMPILED_STUB_FRAME)           \
969   V(DUPLICATED_OBJECT)             \
970   V(ARGUMENTS_OBJECT)              \
971   V(CAPTURED_OBJECT)               \
972   V(REGISTER)                      \
973   V(INT32_REGISTER)                \
974   V(UINT32_REGISTER)               \
975   V(BOOL_REGISTER)                 \
976   V(DOUBLE_REGISTER)               \
977   V(STACK_SLOT)                    \
978   V(INT32_STACK_SLOT)              \
979   V(UINT32_STACK_SLOT)             \
980   V(BOOL_STACK_SLOT)               \
981   V(DOUBLE_STACK_SLOT)             \
982   V(LITERAL)                       \
983   V(JS_FRAME_FUNCTION)
984
985
986 class Translation BASE_EMBEDDED {
987  public:
988 #define DECLARE_TRANSLATION_OPCODE_ENUM(item) item,
989   enum Opcode {
990     TRANSLATION_OPCODE_LIST(DECLARE_TRANSLATION_OPCODE_ENUM)
991     LAST = LITERAL
992   };
993 #undef DECLARE_TRANSLATION_OPCODE_ENUM
994
995   Translation(TranslationBuffer* buffer, int frame_count, int jsframe_count,
996               Zone* zone)
997       : buffer_(buffer),
998         index_(buffer->CurrentIndex()),
999         zone_(zone) {
1000     buffer_->Add(BEGIN, zone);
1001     buffer_->Add(frame_count, zone);
1002     buffer_->Add(jsframe_count, zone);
1003   }
1004
1005   int index() const { return index_; }
1006
1007   // Commands.
1008   void BeginJSFrame(BailoutId node_id, int literal_id, unsigned height);
1009   void BeginCompiledStubFrame(int height);
1010   void BeginArgumentsAdaptorFrame(int literal_id, unsigned height);
1011   void BeginConstructStubFrame(int literal_id, unsigned height);
1012   void BeginGetterStubFrame(int literal_id);
1013   void BeginSetterStubFrame(int literal_id);
1014   void BeginArgumentsObject(int args_length);
1015   void BeginCapturedObject(int length);
1016   void DuplicateObject(int object_index);
1017   void StoreRegister(Register reg);
1018   void StoreInt32Register(Register reg);
1019   void StoreUint32Register(Register reg);
1020   void StoreBoolRegister(Register reg);
1021   void StoreDoubleRegister(DoubleRegister reg);
1022   void StoreStackSlot(int index);
1023   void StoreInt32StackSlot(int index);
1024   void StoreUint32StackSlot(int index);
1025   void StoreBoolStackSlot(int index);
1026   void StoreDoubleStackSlot(int index);
1027   void StoreLiteral(int literal_id);
1028   void StoreArgumentsObject(bool args_known, int args_index, int args_length);
1029   void StoreJSFrameFunction();
1030
1031   Zone* zone() const { return zone_; }
1032
1033   static int NumberOfOperandsFor(Opcode opcode);
1034
1035 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
1036   static const char* StringFor(Opcode opcode);
1037 #endif
1038
1039  private:
1040   TranslationBuffer* buffer_;
1041   int index_;
1042   Zone* zone_;
1043 };
1044
1045
1046 class MaterializedObjectStore {
1047  public:
1048   explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) {
1049   }
1050
1051   Handle<FixedArray> Get(Address fp);
1052   void Set(Address fp, Handle<FixedArray> materialized_objects);
1053   bool Remove(Address fp);
1054
1055  private:
1056   Isolate* isolate() { return isolate_; }
1057   Handle<FixedArray> GetStackEntries();
1058   Handle<FixedArray> EnsureStackEntries(int size);
1059
1060   int StackIdToIndex(Address fp);
1061
1062   Isolate* isolate_;
1063   List<Address> frame_fps_;
1064 };
1065
1066
1067 // Class used to represent an unoptimized frame when the debugger
1068 // needs to inspect a frame that is part of an optimized frame. The
1069 // internally used FrameDescription objects are not GC safe so for use
1070 // by the debugger frame information is copied to an object of this type.
1071 // Represents parameters in unadapted form so their number might mismatch
1072 // formal parameter count.
1073 class DeoptimizedFrameInfo : public Malloced {
1074  public:
1075   DeoptimizedFrameInfo(Deoptimizer* deoptimizer,
1076                        int frame_index,
1077                        bool has_arguments_adaptor,
1078                        bool has_construct_stub);
1079   virtual ~DeoptimizedFrameInfo();
1080
1081   // GC support.
1082   void Iterate(ObjectVisitor* v);
1083
1084   // Return the number of incoming arguments.
1085   int parameters_count() { return parameters_count_; }
1086
1087   // Return the height of the expression stack.
1088   int expression_count() { return expression_count_; }
1089
1090   // Get the frame function.
1091   JSFunction* GetFunction() {
1092     return function_;
1093   }
1094
1095   // Get the frame context.
1096   Object* GetContext() { return context_; }
1097
1098   // Check if this frame is preceded by construct stub frame.  The bottom-most
1099   // inlined frame might still be called by an uninlined construct stub.
1100   bool HasConstructStub() {
1101     return has_construct_stub_;
1102   }
1103
1104   // Get an incoming argument.
1105   Object* GetParameter(int index) {
1106     DCHECK(0 <= index && index < parameters_count());
1107     return parameters_[index];
1108   }
1109
1110   // Get an expression from the expression stack.
1111   Object* GetExpression(int index) {
1112     DCHECK(0 <= index && index < expression_count());
1113     return expression_stack_[index];
1114   }
1115
1116   int GetSourcePosition() {
1117     return source_position_;
1118   }
1119
1120  private:
1121   // Set an incoming argument.
1122   void SetParameter(int index, Object* obj) {
1123     DCHECK(0 <= index && index < parameters_count());
1124     parameters_[index] = obj;
1125   }
1126
1127   // Set an expression on the expression stack.
1128   void SetExpression(int index, Object* obj) {
1129     DCHECK(0 <= index && index < expression_count());
1130     expression_stack_[index] = obj;
1131   }
1132
1133   JSFunction* function_;
1134   Object* context_;
1135   bool has_construct_stub_;
1136   int parameters_count_;
1137   int expression_count_;
1138   Object** parameters_;
1139   Object** expression_stack_;
1140   int source_position_;
1141
1142   friend class Deoptimizer;
1143 };
1144
1145 }  // namespace internal
1146 }  // namespace v8
1147
1148 #endif  // V8_DEOPTIMIZER_H_