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