LCOV - code coverage report
Current view: top level - src - deoptimizer.h (source / functions) Hit Total Coverage
Test: app.info Lines: 60 61 98.4 %
Date: 2019-02-19 Functions: 9 11 81.8 %

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

Generated by: LCOV version 1.10