LCOV - code coverage report
Current view: top level - src - deoptimizer.h (source / functions) Hit Total Coverage
Test: app.info Lines: 48 49 98.0 %
Date: 2017-10-20 Functions: 5 8 62.5 %

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

Generated by: LCOV version 1.10