Home | History | Annotate | Download | only in src
      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 <stack>
      9 #include <vector>
     10 
     11 #include "src/allocation.h"
     12 #include "src/base/macros.h"
     13 #include "src/boxed-float.h"
     14 #include "src/code-tracer.h"
     15 #include "src/deoptimize-reason.h"
     16 #include "src/feedback-vector.h"
     17 #include "src/frame-constants.h"
     18 #include "src/globals.h"
     19 #include "src/isolate.h"
     20 #include "src/macro-assembler.h"
     21 #include "src/objects/shared-function-info.h"
     22 #include "src/source-position.h"
     23 #include "src/zone/zone-chunk-list.h"
     24 
     25 namespace v8 {
     26 namespace internal {
     27 
     28 class FrameDescription;
     29 class TranslationIterator;
     30 class DeoptimizedFrameInfo;
     31 class TranslatedState;
     32 class RegisterValues;
     33 
     34 class TranslatedValue {
     35  public:
     36   // Allocation-less getter of the value.
     37   // Returns ReadOnlyRoots::arguments_marker() if allocation would be necessary
     38   // to get the value.
     39   Object* GetRawValue() const;
     40 
     41   // Getter for the value, takes care of materializing the subgraph
     42   // reachable from this value.
     43   Handle<Object> GetValue();
     44 
     45   bool IsMaterializedObject() const;
     46   bool IsMaterializableByDebugger() const;
     47 
     48  private:
     49   friend class TranslatedState;
     50   friend class TranslatedFrame;
     51 
     52   enum Kind : uint8_t {
     53     kInvalid,
     54     kTagged,
     55     kInt32,
     56     kUInt32,
     57     kBoolBit,
     58     kFloat,
     59     kDouble,
     60     kCapturedObject,   // Object captured by the escape analysis.
     61                        // The number of nested objects can be obtained
     62                        // with the DeferredObjectLength() method
     63                        // (the values of the nested objects follow
     64                        // this value in the depth-first order.)
     65     kDuplicatedObject  // Duplicated object of a deferred object.
     66   };
     67 
     68   enum MaterializationState : uint8_t {
     69     kUninitialized,
     70     kAllocated,  // Storage for the object has been allocated (or
     71                  // enqueued for allocation).
     72     kFinished,   // The object has been initialized (or enqueued for
     73                  // initialization).
     74   };
     75 
     76   TranslatedValue(TranslatedState* container, Kind kind)
     77       : kind_(kind), container_(container) {}
     78   Kind kind() const { return kind_; }
     79   MaterializationState materialization_state() const {
     80     return materialization_state_;
     81   }
     82   void Handlify();
     83   int GetChildrenCount() const;
     84 
     85   static TranslatedValue NewDeferredObject(TranslatedState* container,
     86                                            int length, int object_index);
     87   static TranslatedValue NewDuplicateObject(TranslatedState* container, int id);
     88   static TranslatedValue NewFloat(TranslatedState* container, Float32 value);
     89   static TranslatedValue NewDouble(TranslatedState* container, Float64 value);
     90   static TranslatedValue NewInt32(TranslatedState* container, int32_t value);
     91   static TranslatedValue NewUInt32(TranslatedState* container, uint32_t value);
     92   static TranslatedValue NewBool(TranslatedState* container, uint32_t value);
     93   static TranslatedValue NewTagged(TranslatedState* container, Object* literal);
     94   static TranslatedValue NewInvalid(TranslatedState* container);
     95 
     96   Isolate* isolate() const;
     97   void MaterializeSimple();
     98 
     99   void set_storage(Handle<HeapObject> storage) { storage_ = storage; }
    100   void set_initialized_storage(Handle<Object> storage);
    101   void mark_finished() { materialization_state_ = kFinished; }
    102   void mark_allocated() { materialization_state_ = kAllocated; }
    103 
    104   Handle<Object> GetStorage() {
    105     DCHECK_NE(kUninitialized, materialization_state());
    106     return storage_;
    107   }
    108 
    109   Kind kind_;
    110   MaterializationState materialization_state_ = kUninitialized;
    111   TranslatedState* container_;  // This is only needed for materialization of
    112                                 // objects and constructing handles (to get
    113                                 // to the isolate).
    114 
    115   Handle<Object> storage_;  // Contains the materialized value or the
    116                             // byte-array that will be later morphed into
    117                             // the materialized object.
    118 
    119   struct MaterializedObjectInfo {
    120     int id_;
    121     int length_;  // Applies only to kCapturedObject kinds.
    122   };
    123 
    124   union {
    125     // kind kTagged. After handlification it is always nullptr.
    126     Object* raw_literal_;
    127     // kind is kUInt32 or kBoolBit.
    128     uint32_t uint32_value_;
    129     // kind is kInt32.
    130     int32_t int32_value_;
    131     // kind is kFloat
    132     Float32 float_value_;
    133     // kind is kDouble
    134     Float64 double_value_;
    135     // kind is kDuplicatedObject or kCapturedObject.
    136     MaterializedObjectInfo materialization_info_;
    137   };
    138 
    139   // Checked accessors for the union members.
    140   Object* raw_literal() const;
    141   int32_t int32_value() const;
    142   uint32_t uint32_value() const;
    143   Float32 float_value() const;
    144   Float64 double_value() const;
    145   int object_length() const;
    146   int object_index() const;
    147 };
    148 
    149 
    150 class TranslatedFrame {
    151  public:
    152   enum Kind {
    153     kInterpretedFunction,
    154     kArgumentsAdaptor,
    155     kConstructStub,
    156     kBuiltinContinuation,
    157     kJavaScriptBuiltinContinuation,
    158     kJavaScriptBuiltinContinuationWithCatch,
    159     kInvalid
    160   };
    161 
    162   int GetValueCount();
    163 
    164   Kind kind() const { return kind_; }
    165   BailoutId node_id() const { return node_id_; }
    166   Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
    167   int height() const { return height_; }
    168 
    169   SharedFunctionInfo* raw_shared_info() const {
    170     CHECK_NOT_NULL(raw_shared_info_);
    171     return raw_shared_info_;
    172   }
    173 
    174   class iterator {
    175    public:
    176     iterator& operator++() {
    177       ++input_index_;
    178       AdvanceIterator(&position_);
    179       return *this;
    180     }
    181 
    182     iterator operator++(int) {
    183       ++input_index_;
    184       iterator original(position_);
    185       AdvanceIterator(&position_);
    186       return original;
    187     }
    188 
    189     bool operator==(const iterator& other) const {
    190       // Ignore {input_index_} for equality.
    191       return position_ == other.position_;
    192     }
    193     bool operator!=(const iterator& other) const { return !(*this == other); }
    194 
    195     TranslatedValue& operator*() { return (*position_); }
    196     TranslatedValue* operator->() { return &(*position_); }
    197     const TranslatedValue& operator*() const { return (*position_); }
    198     const TranslatedValue* operator->() const { return &(*position_); }
    199 
    200     int input_index() const { return input_index_; }
    201 
    202    private:
    203     friend TranslatedFrame;
    204 
    205     explicit iterator(std::deque<TranslatedValue>::iterator position)
    206         : position_(position), input_index_(0) {}
    207 
    208     std::deque<TranslatedValue>::iterator position_;
    209     int input_index_;
    210   };
    211 
    212   typedef TranslatedValue& reference;
    213   typedef TranslatedValue const& const_reference;
    214 
    215   iterator begin() { return iterator(values_.begin()); }
    216   iterator end() { return iterator(values_.end()); }
    217 
    218   reference front() { return values_.front(); }
    219   const_reference front() const { return values_.front(); }
    220 
    221  private:
    222   friend class TranslatedState;
    223 
    224   // Constructor static methods.
    225   static TranslatedFrame InterpretedFrame(BailoutId bytecode_offset,
    226                                           SharedFunctionInfo* shared_info,
    227                                           int height);
    228   static TranslatedFrame AccessorFrame(Kind kind,
    229                                        SharedFunctionInfo* shared_info);
    230   static TranslatedFrame ArgumentsAdaptorFrame(SharedFunctionInfo* shared_info,
    231                                                int height);
    232   static TranslatedFrame ConstructStubFrame(BailoutId bailout_id,
    233                                             SharedFunctionInfo* shared_info,
    234                                             int height);
    235   static TranslatedFrame BuiltinContinuationFrame(
    236       BailoutId bailout_id, SharedFunctionInfo* shared_info, int height);
    237   static TranslatedFrame JavaScriptBuiltinContinuationFrame(
    238       BailoutId bailout_id, SharedFunctionInfo* shared_info, int height);
    239   static TranslatedFrame JavaScriptBuiltinContinuationWithCatchFrame(
    240       BailoutId bailout_id, SharedFunctionInfo* shared_info, int height);
    241   static TranslatedFrame InvalidFrame() {
    242     return TranslatedFrame(kInvalid, nullptr);
    243   }
    244 
    245   static void AdvanceIterator(std::deque<TranslatedValue>::iterator* iter);
    246 
    247   TranslatedFrame(Kind kind, SharedFunctionInfo* shared_info = nullptr,
    248                   int height = 0)
    249       : kind_(kind),
    250         node_id_(BailoutId::None()),
    251         raw_shared_info_(shared_info),
    252         height_(height) {}
    253 
    254   void Add(const TranslatedValue& value) { values_.push_back(value); }
    255   TranslatedValue* ValueAt(int index) { return &(values_[index]); }
    256   void Handlify();
    257 
    258   Kind kind_;
    259   BailoutId node_id_;
    260   SharedFunctionInfo* raw_shared_info_;
    261   Handle<SharedFunctionInfo> shared_info_;
    262   int height_;
    263 
    264   typedef std::deque<TranslatedValue> ValuesContainer;
    265 
    266   ValuesContainer values_;
    267 };
    268 
    269 
    270 // Auxiliary class for translating deoptimization values.
    271 // Typical usage sequence:
    272 //
    273 // 1. Construct the instance. This will involve reading out the translations
    274 //    and resolving them to values using the supplied frame pointer and
    275 //    machine state (registers). This phase is guaranteed not to allocate
    276 //    and not to use any HandleScope. Any object pointers will be stored raw.
    277 //
    278 // 2. Handlify pointers. This will convert all the raw pointers to handles.
    279 //
    280 // 3. Reading out the frame values.
    281 //
    282 // Note: After the instance is constructed, it is possible to iterate over
    283 // the values eagerly.
    284 
    285 class TranslatedState {
    286  public:
    287   TranslatedState() {}
    288   explicit TranslatedState(const JavaScriptFrame* frame);
    289 
    290   void Prepare(Address stack_frame_pointer);
    291 
    292   // Store newly materialized values into the isolate.
    293   void StoreMaterializedValuesAndDeopt(JavaScriptFrame* frame);
    294 
    295   typedef std::vector<TranslatedFrame>::iterator iterator;
    296   iterator begin() { return frames_.begin(); }
    297   iterator end() { return frames_.end(); }
    298 
    299   typedef std::vector<TranslatedFrame>::const_iterator const_iterator;
    300   const_iterator begin() const { return frames_.begin(); }
    301   const_iterator end() const { return frames_.end(); }
    302 
    303   std::vector<TranslatedFrame>& frames() { return frames_; }
    304 
    305   TranslatedFrame* GetFrameFromJSFrameIndex(int jsframe_index);
    306   TranslatedFrame* GetArgumentsInfoFromJSFrameIndex(int jsframe_index,
    307                                                     int* arguments_count);
    308 
    309   Isolate* isolate() { return isolate_; }
    310 
    311   void Init(Isolate* isolate, Address input_frame_pointer,
    312             TranslationIterator* iterator, FixedArray* literal_array,
    313             RegisterValues* registers, FILE* trace_file, int parameter_count);
    314 
    315   void VerifyMaterializedObjects();
    316   bool DoUpdateFeedback();
    317 
    318  private:
    319   friend TranslatedValue;
    320 
    321   TranslatedFrame CreateNextTranslatedFrame(TranslationIterator* iterator,
    322                                             FixedArray* literal_array,
    323                                             Address fp,
    324                                             FILE* trace_file);
    325   int CreateNextTranslatedValue(int frame_index, TranslationIterator* iterator,
    326                                 FixedArray* literal_array, Address fp,
    327                                 RegisterValues* registers, FILE* trace_file);
    328   Address ComputeArgumentsPosition(Address input_frame_pointer,
    329                                    CreateArgumentsType type, int* length);
    330   void CreateArgumentsElementsTranslatedValues(int frame_index,
    331                                                Address input_frame_pointer,
    332                                                CreateArgumentsType type,
    333                                                FILE* trace_file);
    334 
    335   void UpdateFromPreviouslyMaterializedObjects();
    336   void MaterializeFixedDoubleArray(TranslatedFrame* frame, int* value_index,
    337                                    TranslatedValue* slot, Handle<Map> map);
    338   void MaterializeMutableHeapNumber(TranslatedFrame* frame, int* value_index,
    339                                     TranslatedValue* slot);
    340 
    341   void EnsureObjectAllocatedAt(TranslatedValue* slot);
    342 
    343   void SkipSlots(int slots_to_skip, TranslatedFrame* frame, int* value_index);
    344 
    345   Handle<ByteArray> AllocateStorageFor(TranslatedValue* slot);
    346   void EnsureJSObjectAllocated(TranslatedValue* slot, Handle<Map> map);
    347   void EnsurePropertiesAllocatedAndMarked(TranslatedValue* properties_slot,
    348                                           Handle<Map> map);
    349   void EnsureChildrenAllocated(int count, TranslatedFrame* frame,
    350                                int* value_index, std::stack<int>* worklist);
    351   void EnsureCapturedObjectAllocatedAt(int object_index,
    352                                        std::stack<int>* worklist);
    353   Handle<Object> InitializeObjectAt(TranslatedValue* slot);
    354   void InitializeCapturedObjectAt(int object_index, std::stack<int>* worklist,
    355                                   const DisallowHeapAllocation& no_allocation);
    356   void InitializeJSObjectAt(TranslatedFrame* frame, int* value_index,
    357                             TranslatedValue* slot, Handle<Map> map,
    358                             const DisallowHeapAllocation& no_allocation);
    359   void InitializeObjectWithTaggedFieldsAt(
    360       TranslatedFrame* frame, int* value_index, TranslatedValue* slot,
    361       Handle<Map> map, const DisallowHeapAllocation& no_allocation);
    362 
    363   void ReadUpdateFeedback(TranslationIterator* iterator,
    364                           FixedArray* literal_array, FILE* trace_file);
    365 
    366   TranslatedValue* ResolveCapturedObject(TranslatedValue* slot);
    367   TranslatedValue* GetValueByObjectIndex(int object_index);
    368   Handle<Object> GetValueAndAdvance(TranslatedFrame* frame, int* value_index);
    369 
    370   static uint32_t GetUInt32Slot(Address fp, int slot_index);
    371   static Float32 GetFloatSlot(Address fp, int slot_index);
    372   static Float64 GetDoubleSlot(Address fp, int slot_index);
    373 
    374   std::vector<TranslatedFrame> frames_;
    375   Isolate* isolate_ = nullptr;
    376   Address stack_frame_pointer_ = kNullAddress;
    377   int formal_parameter_count_;
    378 
    379   struct ObjectPosition {
    380     int frame_index_;
    381     int value_index_;
    382   };
    383   std::deque<ObjectPosition> object_positions_;
    384   Handle<FeedbackVector> feedback_vector_handle_;
    385   FeedbackVector* feedback_vector_ = nullptr;
    386   FeedbackSlot feedback_slot_;
    387 };
    388 
    389 
    390 class OptimizedFunctionVisitor BASE_EMBEDDED {
    391  public:
    392   virtual ~OptimizedFunctionVisitor() {}
    393   virtual void VisitFunction(JSFunction* function) = 0;
    394 };
    395 
    396 class Deoptimizer : public Malloced {
    397  public:
    398   struct DeoptInfo {
    399     DeoptInfo(SourcePosition position, DeoptimizeReason deopt_reason,
    400               int deopt_id)
    401         : position(position), deopt_reason(deopt_reason), deopt_id(deopt_id) {}
    402 
    403     SourcePosition position;
    404     DeoptimizeReason deopt_reason;
    405     int deopt_id;
    406 
    407     static const int kNoDeoptId = -1;
    408   };
    409 
    410   static DeoptInfo GetDeoptInfo(Code* code, Address from);
    411 
    412   static int ComputeSourcePositionFromBytecodeArray(SharedFunctionInfo* shared,
    413                                                     BailoutId node_id);
    414 
    415   struct JumpTableEntry : public ZoneObject {
    416     inline JumpTableEntry(Address entry, const DeoptInfo& deopt_info,
    417                           DeoptimizeKind kind, bool frame)
    418         : label(),
    419           address(entry),
    420           deopt_info(deopt_info),
    421           deopt_kind(kind),
    422           needs_frame(frame) {}
    423 
    424     bool IsEquivalentTo(const JumpTableEntry& other) const {
    425       return address == other.address && deopt_kind == other.deopt_kind &&
    426              needs_frame == other.needs_frame;
    427     }
    428 
    429     Label label;
    430     Address address;
    431     DeoptInfo deopt_info;
    432     DeoptimizeKind deopt_kind;
    433     bool needs_frame;
    434   };
    435 
    436   static const char* MessageFor(DeoptimizeKind kind);
    437 
    438   int output_count() const { return output_count_; }
    439 
    440   Handle<JSFunction> function() const;
    441   Handle<Code> compiled_code() const;
    442   DeoptimizeKind deopt_kind() const { return deopt_kind_; }
    443 
    444   // Number of created JS frames. Not all created frames are necessarily JS.
    445   int jsframe_count() const { return jsframe_count_; }
    446 
    447   static Deoptimizer* New(JSFunction* function, DeoptimizeKind kind,
    448                           unsigned bailout_id, Address from, int fp_to_sp_delta,
    449                           Isolate* isolate);
    450   static Deoptimizer* Grab(Isolate* isolate);
    451 
    452   // The returned object with information on the optimized frame needs to be
    453   // freed before another one can be generated.
    454   static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame,
    455                                                         int jsframe_index,
    456                                                         Isolate* isolate);
    457 
    458   // Deoptimize the function now. Its current optimized code will never be run
    459   // again and any activations of the optimized code will get deoptimized when
    460   // execution returns. If {code} is specified then the given code is targeted
    461   // instead of the function code (e.g. OSR code not installed on function).
    462   static void DeoptimizeFunction(JSFunction* function, Code* code = nullptr);
    463 
    464   // Deoptimize all code in the given isolate.
    465   static void DeoptimizeAll(Isolate* isolate);
    466 
    467   // Deoptimizes all optimized code that has been previously marked
    468   // (via code->set_marked_for_deoptimization) and unlinks all functions that
    469   // refer to that code.
    470   static void DeoptimizeMarkedCode(Isolate* isolate);
    471 
    472   ~Deoptimizer();
    473 
    474   void MaterializeHeapObjects();
    475 
    476   static void ComputeOutputFrames(Deoptimizer* deoptimizer);
    477 
    478   static Address GetDeoptimizationEntry(Isolate* isolate, int id,
    479                                         DeoptimizeKind kind);
    480   static int GetDeoptimizationId(Isolate* isolate, Address addr,
    481                                  DeoptimizeKind kind);
    482 
    483   // Returns true if {addr} is a deoptimization entry and stores its type in
    484   // {type}. Returns false if {addr} is not a deoptimization entry.
    485   static bool IsDeoptimizationEntry(Isolate* isolate, Address addr,
    486                                     DeoptimizeKind* type);
    487 
    488   // Code generation support.
    489   static int input_offset() { return OFFSET_OF(Deoptimizer, input_); }
    490   static int output_count_offset() {
    491     return OFFSET_OF(Deoptimizer, output_count_);
    492   }
    493   static int output_offset() { return OFFSET_OF(Deoptimizer, output_); }
    494 
    495   static int caller_frame_top_offset() {
    496     return OFFSET_OF(Deoptimizer, caller_frame_top_);
    497   }
    498 
    499   static int GetDeoptimizedCodeCount(Isolate* isolate);
    500 
    501   static const int kNotDeoptimizationEntry = -1;
    502 
    503   // Generators for the deoptimization entry code.
    504   class TableEntryGenerator BASE_EMBEDDED {
    505    public:
    506     TableEntryGenerator(MacroAssembler* masm, DeoptimizeKind kind, int count)
    507         : masm_(masm), deopt_kind_(kind), count_(count) {}
    508 
    509     void Generate();
    510 
    511    protected:
    512     MacroAssembler* masm() const { return masm_; }
    513     DeoptimizeKind deopt_kind() const { return deopt_kind_; }
    514     Isolate* isolate() const { return masm_->isolate(); }
    515 
    516     void GeneratePrologue();
    517 
    518    private:
    519     int count() const { return count_; }
    520 
    521     MacroAssembler* masm_;
    522     DeoptimizeKind deopt_kind_;
    523     int count_;
    524   };
    525 
    526   static void EnsureCodeForDeoptimizationEntry(Isolate* isolate,
    527                                                DeoptimizeKind kind);
    528   static void EnsureCodeForMaxDeoptimizationEntries(Isolate* isolate);
    529 
    530   Isolate* isolate() const { return isolate_; }
    531 
    532  private:
    533   friend class FrameWriter;
    534   void QueueValueForMaterialization(Address output_address, Object* obj,
    535                                     const TranslatedFrame::iterator& iterator);
    536 
    537   static const int kMinNumberOfEntries = 64;
    538   static const int kMaxNumberOfEntries = 16384;
    539 
    540   Deoptimizer(Isolate* isolate, JSFunction* function, DeoptimizeKind kind,
    541               unsigned bailout_id, Address from, int fp_to_sp_delta);
    542   Code* FindOptimizedCode();
    543   void PrintFunctionName();
    544   void DeleteFrameDescriptions();
    545 
    546   static bool IsInDeoptimizationTable(Isolate* isolate, Address addr,
    547                                       DeoptimizeKind type);
    548 
    549   void DoComputeOutputFrames();
    550   void DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
    551                                  int frame_index, bool goto_catch_handler);
    552   void DoComputeArgumentsAdaptorFrame(TranslatedFrame* translated_frame,
    553                                       int frame_index);
    554   void DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
    555                                    int frame_index);
    556 
    557   enum class BuiltinContinuationMode {
    558     STUB,
    559     JAVASCRIPT,
    560     JAVASCRIPT_WITH_CATCH,
    561     JAVASCRIPT_HANDLE_EXCEPTION
    562   };
    563   static bool BuiltinContinuationModeIsWithCatch(BuiltinContinuationMode mode);
    564   static bool BuiltinContinuationModeIsJavaScript(BuiltinContinuationMode mode);
    565   static StackFrame::Type BuiltinContinuationModeToFrameType(
    566       BuiltinContinuationMode mode);
    567   static Builtins::Name TrampolineForBuiltinContinuation(
    568       BuiltinContinuationMode mode, bool must_handle_result);
    569 
    570   void DoComputeBuiltinContinuation(TranslatedFrame* translated_frame,
    571                                     int frame_index,
    572                                     BuiltinContinuationMode mode);
    573 
    574   unsigned ComputeInputFrameAboveFpFixedSize() const;
    575   unsigned ComputeInputFrameSize() const;
    576   static unsigned ComputeInterpretedFixedSize(SharedFunctionInfo* shared);
    577 
    578   static unsigned ComputeIncomingArgumentSize(SharedFunctionInfo* shared);
    579   static unsigned ComputeOutgoingArgumentSize(Code* code, unsigned bailout_id);
    580 
    581   static void GenerateDeoptimizationEntries(MacroAssembler* masm, int count,
    582                                             DeoptimizeKind kind);
    583 
    584   // Marks all the code in the given context for deoptimization.
    585   static void MarkAllCodeForContext(Context* native_context);
    586 
    587   // Deoptimizes all code marked in the given context.
    588   static void DeoptimizeMarkedCodeForContext(Context* native_context);
    589 
    590   // Some architectures need to push padding together with the TOS register
    591   // in order to maintain stack alignment.
    592   static bool PadTopOfStackRegister();
    593 
    594   // Searches the list of known deoptimizing code for a Code object
    595   // containing the given address (which is supposedly faster than
    596   // searching all code objects).
    597   Code* FindDeoptimizingCode(Address addr);
    598 
    599   Isolate* isolate_;
    600   JSFunction* function_;
    601   Code* compiled_code_;
    602   unsigned bailout_id_;
    603   DeoptimizeKind deopt_kind_;
    604   Address from_;
    605   int fp_to_sp_delta_;
    606   bool deoptimizing_throw_;
    607   int catch_handler_data_;
    608   int catch_handler_pc_offset_;
    609 
    610   // Input frame description.
    611   FrameDescription* input_;
    612   // Number of output frames.
    613   int output_count_;
    614   // Number of output js frames.
    615   int jsframe_count_;
    616   // Array of output frame descriptions.
    617   FrameDescription** output_;
    618 
    619   // Caller frame details computed from input frame.
    620   intptr_t caller_frame_top_;
    621   intptr_t caller_fp_;
    622   intptr_t caller_pc_;
    623   intptr_t caller_constant_pool_;
    624   intptr_t input_frame_context_;
    625 
    626   // Key for lookup of previously materialized objects
    627   intptr_t stack_fp_;
    628 
    629   TranslatedState translated_state_;
    630   struct ValueToMaterialize {
    631     Address output_slot_address_;
    632     TranslatedFrame::iterator value_;
    633   };
    634   std::vector<ValueToMaterialize> values_to_materialize_;
    635 
    636 #ifdef DEBUG
    637   DisallowHeapAllocation* disallow_heap_allocation_;
    638 #endif  // DEBUG
    639 
    640   CodeTracer::Scope* trace_scope_;
    641 
    642   static const int table_entry_size_;
    643 
    644   friend class FrameDescription;
    645   friend class DeoptimizedFrameInfo;
    646 };
    647 
    648 
    649 class RegisterValues {
    650  public:
    651   intptr_t GetRegister(unsigned n) const {
    652 #if DEBUG
    653     // This convoluted DCHECK is needed to work around a gcc problem that
    654     // improperly detects an array bounds overflow in optimized debug builds
    655     // when using a plain DCHECK.
    656     if (n >= arraysize(registers_)) {
    657       DCHECK(false);
    658       return 0;
    659     }
    660 #endif
    661     return registers_[n];
    662   }
    663 
    664   Float32 GetFloatRegister(unsigned n) const {
    665     DCHECK(n < arraysize(float_registers_));
    666     return float_registers_[n];
    667   }
    668 
    669   Float64 GetDoubleRegister(unsigned n) const {
    670     DCHECK(n < arraysize(double_registers_));
    671     return double_registers_[n];
    672   }
    673 
    674   void SetRegister(unsigned n, intptr_t value) {
    675     DCHECK(n < arraysize(registers_));
    676     registers_[n] = value;
    677   }
    678 
    679   void SetFloatRegister(unsigned n, Float32 value) {
    680     DCHECK(n < arraysize(float_registers_));
    681     float_registers_[n] = value;
    682   }
    683 
    684   void SetDoubleRegister(unsigned n, Float64 value) {
    685     DCHECK(n < arraysize(double_registers_));
    686     double_registers_[n] = value;
    687   }
    688 
    689   // Generated code is writing directly into the below arrays, make sure their
    690   // element sizes fit what the machine instructions expect.
    691   static_assert(sizeof(Float32) == kFloatSize, "size mismatch");
    692   static_assert(sizeof(Float64) == kDoubleSize, "size mismatch");
    693 
    694   intptr_t registers_[Register::kNumRegisters];
    695   Float32 float_registers_[FloatRegister::kNumRegisters];
    696   Float64 double_registers_[DoubleRegister::kNumRegisters];
    697 };
    698 
    699 
    700 class FrameDescription {
    701  public:
    702   explicit FrameDescription(uint32_t frame_size, int parameter_count = 0);
    703 
    704   void* operator new(size_t size, uint32_t frame_size) {
    705     // Subtracts kPointerSize, as the member frame_content_ already supplies
    706     // the first element of the area to store the frame.
    707     return malloc(size + frame_size - kPointerSize);
    708   }
    709 
    710   void operator delete(void* pointer, uint32_t frame_size) {
    711     free(pointer);
    712   }
    713 
    714   void operator delete(void* description) {
    715     free(description);
    716   }
    717 
    718   uint32_t GetFrameSize() const {
    719     USE(frame_content_);
    720     DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_);
    721     return static_cast<uint32_t>(frame_size_);
    722   }
    723 
    724   intptr_t GetFrameSlot(unsigned offset) {
    725     return *GetFrameSlotPointer(offset);
    726   }
    727 
    728   unsigned GetLastArgumentSlotOffset() {
    729     int parameter_slots = parameter_count();
    730     if (kPadArguments) parameter_slots = RoundUp(parameter_slots, 2);
    731     return GetFrameSize() - parameter_slots * kPointerSize;
    732   }
    733 
    734   Address GetFramePointerAddress() {
    735     int fp_offset =
    736         GetLastArgumentSlotOffset() - StandardFrameConstants::kCallerSPOffset;
    737     return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset));
    738   }
    739 
    740   RegisterValues* GetRegisterValues() { return &register_values_; }
    741 
    742   void SetFrameSlot(unsigned offset, intptr_t value) {
    743     *GetFrameSlotPointer(offset) = value;
    744   }
    745 
    746   void SetCallerPc(unsigned offset, intptr_t value);
    747 
    748   void SetCallerFp(unsigned offset, intptr_t value);
    749 
    750   void SetCallerConstantPool(unsigned offset, intptr_t value);
    751 
    752   intptr_t GetRegister(unsigned n) const {
    753     return register_values_.GetRegister(n);
    754   }
    755 
    756   Float64 GetDoubleRegister(unsigned n) const {
    757     return register_values_.GetDoubleRegister(n);
    758   }
    759 
    760   void SetRegister(unsigned n, intptr_t value) {
    761     register_values_.SetRegister(n, value);
    762   }
    763 
    764   void SetDoubleRegister(unsigned n, Float64 value) {
    765     register_values_.SetDoubleRegister(n, value);
    766   }
    767 
    768   intptr_t GetTop() const { return top_; }
    769   void SetTop(intptr_t top) { top_ = top; }
    770 
    771   intptr_t GetPc() const { return pc_; }
    772   void SetPc(intptr_t pc) { pc_ = pc; }
    773 
    774   intptr_t GetFp() const { return fp_; }
    775   void SetFp(intptr_t fp) { fp_ = fp; }
    776 
    777   intptr_t GetContext() const { return context_; }
    778   void SetContext(intptr_t context) { context_ = context; }
    779 
    780   intptr_t GetConstantPool() const { return constant_pool_; }
    781   void SetConstantPool(intptr_t constant_pool) {
    782     constant_pool_ = constant_pool;
    783   }
    784 
    785   void SetContinuation(intptr_t pc) { continuation_ = pc; }
    786 
    787   // Argument count, including receiver.
    788   int parameter_count() { return parameter_count_; }
    789 
    790   static int registers_offset() {
    791     return OFFSET_OF(FrameDescription, register_values_.registers_);
    792   }
    793 
    794   static int double_registers_offset() {
    795     return OFFSET_OF(FrameDescription, register_values_.double_registers_);
    796   }
    797 
    798   static int float_registers_offset() {
    799     return OFFSET_OF(FrameDescription, register_values_.float_registers_);
    800   }
    801 
    802   static int frame_size_offset() {
    803     return offsetof(FrameDescription, frame_size_);
    804   }
    805 
    806   static int pc_offset() { return offsetof(FrameDescription, pc_); }
    807 
    808   static int continuation_offset() {
    809     return offsetof(FrameDescription, continuation_);
    810   }
    811 
    812   static int frame_content_offset() {
    813     return offsetof(FrameDescription, frame_content_);
    814   }
    815 
    816  private:
    817   static const uint32_t kZapUint32 = 0xbeeddead;
    818 
    819   // Frame_size_ must hold a uint32_t value.  It is only a uintptr_t to
    820   // keep the variable-size array frame_content_ of type intptr_t at
    821   // the end of the structure aligned.
    822   uintptr_t frame_size_;  // Number of bytes.
    823   int parameter_count_;
    824   RegisterValues register_values_;
    825   intptr_t top_;
    826   intptr_t pc_;
    827   intptr_t fp_;
    828   intptr_t context_;
    829   intptr_t constant_pool_;
    830 
    831   // Continuation is the PC where the execution continues after
    832   // deoptimizing.
    833   intptr_t continuation_;
    834 
    835   // This must be at the end of the object as the object is allocated larger
    836   // than it's definition indicate to extend this array.
    837   intptr_t frame_content_[1];
    838 
    839   intptr_t* GetFrameSlotPointer(unsigned offset) {
    840     DCHECK(offset < frame_size_);
    841     return reinterpret_cast<intptr_t*>(
    842         reinterpret_cast<Address>(this) + frame_content_offset() + offset);
    843   }
    844 };
    845 
    846 
    847 class DeoptimizerData {
    848  public:
    849   explicit DeoptimizerData(Heap* heap);
    850   ~DeoptimizerData();
    851 
    852  private:
    853   Heap* heap_;
    854   static const int kLastDeoptimizeKind =
    855       static_cast<int>(DeoptimizeKind::kLastDeoptimizeKind);
    856   Code* deopt_entry_code_[kLastDeoptimizeKind + 1];
    857   Code* deopt_entry_code(DeoptimizeKind kind);
    858   void set_deopt_entry_code(DeoptimizeKind kind, Code* code);
    859 
    860   Deoptimizer* current_;
    861 
    862   friend class Deoptimizer;
    863 
    864   DISALLOW_COPY_AND_ASSIGN(DeoptimizerData);
    865 };
    866 
    867 
    868 class TranslationBuffer BASE_EMBEDDED {
    869  public:
    870   explicit TranslationBuffer(Zone* zone) : contents_(zone) {}
    871 
    872   int CurrentIndex() const { return static_cast<int>(contents_.size()); }
    873   void Add(int32_t value);
    874 
    875   Handle<ByteArray> CreateByteArray(Factory* factory);
    876 
    877  private:
    878   ZoneChunkList<uint8_t> contents_;
    879 };
    880 
    881 
    882 class TranslationIterator BASE_EMBEDDED {
    883  public:
    884   TranslationIterator(ByteArray* buffer, int index);
    885 
    886   int32_t Next();
    887 
    888   bool HasNext() const;
    889 
    890   void Skip(int n) {
    891     for (int i = 0; i < n; i++) Next();
    892   }
    893 
    894  private:
    895   ByteArray* buffer_;
    896   int index_;
    897 };
    898 
    899 #define TRANSLATION_OPCODE_LIST(V)                     \
    900   V(BEGIN)                                             \
    901   V(INTERPRETED_FRAME)                                 \
    902   V(BUILTIN_CONTINUATION_FRAME)                        \
    903   V(JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME)            \
    904   V(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME) \
    905   V(CONSTRUCT_STUB_FRAME)                              \
    906   V(ARGUMENTS_ADAPTOR_FRAME)                           \
    907   V(DUPLICATED_OBJECT)                                 \
    908   V(ARGUMENTS_ELEMENTS)                                \
    909   V(ARGUMENTS_LENGTH)                                  \
    910   V(CAPTURED_OBJECT)                                   \
    911   V(REGISTER)                                          \
    912   V(INT32_REGISTER)                                    \
    913   V(UINT32_REGISTER)                                   \
    914   V(BOOL_REGISTER)                                     \
    915   V(FLOAT_REGISTER)                                    \
    916   V(DOUBLE_REGISTER)                                   \
    917   V(STACK_SLOT)                                        \
    918   V(INT32_STACK_SLOT)                                  \
    919   V(UINT32_STACK_SLOT)                                 \
    920   V(BOOL_STACK_SLOT)                                   \
    921   V(FLOAT_STACK_SLOT)                                  \
    922   V(DOUBLE_STACK_SLOT)                                 \
    923   V(LITERAL)                                           \
    924   V(UPDATE_FEEDBACK)
    925 
    926 class Translation BASE_EMBEDDED {
    927  public:
    928 #define DECLARE_TRANSLATION_OPCODE_ENUM(item) item,
    929   enum Opcode {
    930     TRANSLATION_OPCODE_LIST(DECLARE_TRANSLATION_OPCODE_ENUM)
    931     LAST = LITERAL
    932   };
    933 #undef DECLARE_TRANSLATION_OPCODE_ENUM
    934 
    935   Translation(TranslationBuffer* buffer, int frame_count, int jsframe_count,
    936               int update_feedback_count, Zone* zone)
    937       : buffer_(buffer), index_(buffer->CurrentIndex()), zone_(zone) {
    938     buffer_->Add(BEGIN);
    939     buffer_->Add(frame_count);
    940     buffer_->Add(jsframe_count);
    941     buffer_->Add(update_feedback_count);
    942   }
    943 
    944   int index() const { return index_; }
    945 
    946   // Commands.
    947   void BeginInterpretedFrame(BailoutId bytecode_offset, int literal_id,
    948                              unsigned height);
    949   void BeginArgumentsAdaptorFrame(int literal_id, unsigned height);
    950   void BeginConstructStubFrame(BailoutId bailout_id, int literal_id,
    951                                unsigned height);
    952   void BeginBuiltinContinuationFrame(BailoutId bailout_id, int literal_id,
    953                                      unsigned height);
    954   void BeginJavaScriptBuiltinContinuationFrame(BailoutId bailout_id,
    955                                                int literal_id, unsigned height);
    956   void BeginJavaScriptBuiltinContinuationWithCatchFrame(BailoutId bailout_id,
    957                                                         int literal_id,
    958                                                         unsigned height);
    959   void ArgumentsElements(CreateArgumentsType type);
    960   void ArgumentsLength(CreateArgumentsType type);
    961   void BeginCapturedObject(int length);
    962   void AddUpdateFeedback(int vector_literal, int slot);
    963   void DuplicateObject(int object_index);
    964   void StoreRegister(Register reg);
    965   void StoreInt32Register(Register reg);
    966   void StoreUint32Register(Register reg);
    967   void StoreBoolRegister(Register reg);
    968   void StoreFloatRegister(FloatRegister reg);
    969   void StoreDoubleRegister(DoubleRegister reg);
    970   void StoreStackSlot(int index);
    971   void StoreInt32StackSlot(int index);
    972   void StoreUint32StackSlot(int index);
    973   void StoreBoolStackSlot(int index);
    974   void StoreFloatStackSlot(int index);
    975   void StoreDoubleStackSlot(int index);
    976   void StoreLiteral(int literal_id);
    977   void StoreJSFrameFunction();
    978 
    979   Zone* zone() const { return zone_; }
    980 
    981   static int NumberOfOperandsFor(Opcode opcode);
    982 
    983 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
    984   static const char* StringFor(Opcode opcode);
    985 #endif
    986 
    987  private:
    988   TranslationBuffer* buffer_;
    989   int index_;
    990   Zone* zone_;
    991 };
    992 
    993 
    994 class MaterializedObjectStore {
    995  public:
    996   explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) {
    997   }
    998 
    999   Handle<FixedArray> Get(Address fp);
   1000   void Set(Address fp, Handle<FixedArray> materialized_objects);
   1001   bool Remove(Address fp);
   1002 
   1003  private:
   1004   Isolate* isolate() const { return isolate_; }
   1005   Handle<FixedArray> GetStackEntries();
   1006   Handle<FixedArray> EnsureStackEntries(int size);
   1007 
   1008   int StackIdToIndex(Address fp);
   1009 
   1010   Isolate* isolate_;
   1011   std::vector<Address> frame_fps_;
   1012 };
   1013 
   1014 
   1015 // Class used to represent an unoptimized frame when the debugger
   1016 // needs to inspect a frame that is part of an optimized frame. The
   1017 // internally used FrameDescription objects are not GC safe so for use
   1018 // by the debugger frame information is copied to an object of this type.
   1019 // Represents parameters in unadapted form so their number might mismatch
   1020 // formal parameter count.
   1021 class DeoptimizedFrameInfo : public Malloced {
   1022  public:
   1023   DeoptimizedFrameInfo(TranslatedState* state,
   1024                        TranslatedState::iterator frame_it, Isolate* isolate);
   1025 
   1026   // Return the number of incoming arguments.
   1027   int parameters_count() { return static_cast<int>(parameters_.size()); }
   1028 
   1029   // Return the height of the expression stack.
   1030   int expression_count() { return static_cast<int>(expression_stack_.size()); }
   1031 
   1032   // Get the frame function.
   1033   Handle<JSFunction> GetFunction() { return function_; }
   1034 
   1035   // Get the frame context.
   1036   Handle<Object> GetContext() { return context_; }
   1037 
   1038   // Get an incoming argument.
   1039   Handle<Object> GetParameter(int index) {
   1040     DCHECK(0 <= index && index < parameters_count());
   1041     return parameters_[index];
   1042   }
   1043 
   1044   // Get an expression from the expression stack.
   1045   Handle<Object> GetExpression(int index) {
   1046     DCHECK(0 <= index && index < expression_count());
   1047     return expression_stack_[index];
   1048   }
   1049 
   1050   int GetSourcePosition() {
   1051     return source_position_;
   1052   }
   1053 
   1054  private:
   1055   // Set an incoming argument.
   1056   void SetParameter(int index, Handle<Object> obj) {
   1057     DCHECK(0 <= index && index < parameters_count());
   1058     parameters_[index] = obj;
   1059   }
   1060 
   1061   // Set an expression on the expression stack.
   1062   void SetExpression(int index, Handle<Object> obj) {
   1063     DCHECK(0 <= index && index < expression_count());
   1064     expression_stack_[index] = obj;
   1065   }
   1066 
   1067   Handle<JSFunction> function_;
   1068   Handle<Object> context_;
   1069   std::vector<Handle<Object> > parameters_;
   1070   std::vector<Handle<Object> > expression_stack_;
   1071   int source_position_;
   1072 
   1073   friend class Deoptimizer;
   1074 };
   1075 
   1076 }  // namespace internal
   1077 }  // namespace v8
   1078 
   1079 #endif  // V8_DEOPTIMIZER_H_
   1080