LCOV - code coverage report
Current view: top level - src - deoptimizer.h (source / functions) Hit Total Coverage
Test: app.info Lines: 58 62 93.5 %
Date: 2017-04-26 Functions: 5 9 55.6 %

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

Generated by: LCOV version 1.10