LCOV - code coverage report
Current view: top level - src - deoptimizer.h (source / functions) Hit Total Coverage
Test: app.info Lines: 52 53 98.1 %
Date: 2019-04-18 Functions: 4 4 100.0 %

          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    21448322 :       : 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       56402 :   void set_storage(Handle<HeapObject> storage) { storage_ = storage; }
     105             :   void set_initialized_storage(Handle<Object> storage);
     106       56402 :   void mark_finished() { materialization_state_ = kFinished; }
     107       56402 :   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     7923624 : 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             :   SharedFunctionInfo raw_shared_info() const {
     180       63553 :     CHECK(!raw_shared_info_.is_null());
     181             :     return raw_shared_info_;
     182             :   }
     183             : 
     184      254117 :   class iterator {
     185             :    public:
     186             :     iterator& operator++() {
     187      579066 :       ++input_index_;
     188      579066 :       AdvanceIterator(&position_);
     189             :       return *this;
     190             :     }
     191             : 
     192             :     iterator operator++(int) {
     193     3689524 :       iterator original(position_, input_index_);
     194     3690357 :       ++input_index_;
     195     3690357 :       AdvanceIterator(&position_);
     196             :       return original;
     197             :     }
     198             : 
     199             :     bool operator==(const iterator& other) const {
     200             :       // Ignore {input_index_} for equality.
     201             :       return position_ == other.position_;
     202             :     }
     203             :     bool operator!=(const iterator& other) const { return !(*this == other); }
     204             : 
     205             :     TranslatedValue& operator*() { return (*position_); }
     206             :     TranslatedValue* operator->() { return &(*position_); }
     207             :     const TranslatedValue& operator*() const { return (*position_); }
     208             :     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     1818481 :         : 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     3961812 :         return_value_count_(return_value_count) {}
     269             : 
     270    21448322 :   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     1398056 : class TranslatedState {
     304             :  public:
     305      162717 :   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             :   static const char* MessageFor(DeoptimizeKind kind);
     433             : 
     434             :   int output_count() const { return output_count_; }
     435             : 
     436             :   Handle<JSFunction> function() const;
     437             :   Handle<Code> compiled_code() const;
     438             :   DeoptimizeKind deopt_kind() const { return deopt_kind_; }
     439             : 
     440             :   // Number of created JS frames. Not all created frames are necessarily JS.
     441             :   int jsframe_count() const { return jsframe_count_; }
     442             : 
     443             :   static Deoptimizer* New(Address raw_function, DeoptimizeKind kind,
     444             :                           unsigned bailout_id, Address from, int fp_to_sp_delta,
     445             :                           Isolate* isolate);
     446             :   static Deoptimizer* Grab(Isolate* isolate);
     447             : 
     448             :   // The returned object with information on the optimized frame needs to be
     449             :   // freed before another one can be generated.
     450             :   static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame,
     451             :                                                         int jsframe_index,
     452             :                                                         Isolate* isolate);
     453             : 
     454             :   // Deoptimize the function now. Its current optimized code will never be run
     455             :   // again and any activations of the optimized code will get deoptimized when
     456             :   // execution returns. If {code} is specified then the given code is targeted
     457             :   // instead of the function code (e.g. OSR code not installed on function).
     458             :   static void DeoptimizeFunction(JSFunction function, Code code = Code());
     459             : 
     460             :   // Deoptimize all code in the given isolate.
     461             :   V8_EXPORT_PRIVATE static void DeoptimizeAll(Isolate* isolate);
     462             : 
     463             :   // Deoptimizes all optimized code that has been previously marked
     464             :   // (via code->set_marked_for_deoptimization) and unlinks all functions that
     465             :   // refer to that code.
     466             :   static void DeoptimizeMarkedCode(Isolate* isolate);
     467             : 
     468             :   ~Deoptimizer();
     469             : 
     470             :   void MaterializeHeapObjects();
     471             : 
     472             :   static void ComputeOutputFrames(Deoptimizer* deoptimizer);
     473             : 
     474             :   static Address GetDeoptimizationEntry(Isolate* isolate, DeoptimizeKind kind);
     475             : 
     476             :   // Returns true if {addr} is a deoptimization entry and stores its type in
     477             :   // {type}. Returns false if {addr} is not a deoptimization entry.
     478             :   static bool IsDeoptimizationEntry(Isolate* isolate, Address addr,
     479             :                                     DeoptimizeKind* type);
     480             : 
     481             :   // Code generation support.
     482             :   static int input_offset() { return OFFSET_OF(Deoptimizer, input_); }
     483             :   static int output_count_offset() {
     484             :     return OFFSET_OF(Deoptimizer, output_count_);
     485             :   }
     486             :   static int output_offset() { return OFFSET_OF(Deoptimizer, output_); }
     487             : 
     488             :   static int caller_frame_top_offset() {
     489             :     return OFFSET_OF(Deoptimizer, caller_frame_top_);
     490             :   }
     491             : 
     492             :   V8_EXPORT_PRIVATE static int GetDeoptimizedCodeCount(Isolate* isolate);
     493             : 
     494             :   static const int kNotDeoptimizationEntry = -1;
     495             : 
     496             :   static void EnsureCodeForDeoptimizationEntry(Isolate* isolate,
     497             :                                                DeoptimizeKind kind);
     498             :   static void EnsureCodeForDeoptimizationEntries(Isolate* isolate);
     499             : 
     500             :   Isolate* isolate() const { return isolate_; }
     501             : 
     502             :   static const int kMaxNumberOfEntries = 16384;
     503             : 
     504             :  private:
     505             :   friend class FrameWriter;
     506             :   void QueueValueForMaterialization(Address output_address, Object obj,
     507             :                                     const TranslatedFrame::iterator& iterator);
     508             : 
     509             : 
     510             :   Deoptimizer(Isolate* isolate, JSFunction function, DeoptimizeKind kind,
     511             :               unsigned bailout_id, Address from, int fp_to_sp_delta);
     512             :   Code FindOptimizedCode();
     513             :   void PrintFunctionName();
     514             :   void DeleteFrameDescriptions();
     515             : 
     516             :   static bool IsDeoptimizationEntry(Isolate* isolate, Address addr,
     517             :                                     DeoptimizeKind type);
     518             : 
     519             :   void DoComputeOutputFrames();
     520             :   void DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
     521             :                                  int frame_index, bool goto_catch_handler);
     522             :   void DoComputeArgumentsAdaptorFrame(TranslatedFrame* translated_frame,
     523             :                                       int frame_index);
     524             :   void DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
     525             :                                    int frame_index);
     526             : 
     527             :   enum class BuiltinContinuationMode {
     528             :     STUB,
     529             :     JAVASCRIPT,
     530             :     JAVASCRIPT_WITH_CATCH,
     531             :     JAVASCRIPT_HANDLE_EXCEPTION
     532             :   };
     533             :   static bool BuiltinContinuationModeIsWithCatch(BuiltinContinuationMode mode);
     534             :   static bool BuiltinContinuationModeIsJavaScript(BuiltinContinuationMode mode);
     535             :   static StackFrame::Type BuiltinContinuationModeToFrameType(
     536             :       BuiltinContinuationMode mode);
     537             :   static Builtins::Name TrampolineForBuiltinContinuation(
     538             :       BuiltinContinuationMode mode, bool must_handle_result);
     539             : 
     540             :   void DoComputeBuiltinContinuation(TranslatedFrame* translated_frame,
     541             :                                     int frame_index,
     542             :                                     BuiltinContinuationMode mode);
     543             : 
     544             :   unsigned ComputeInputFrameAboveFpFixedSize() const;
     545             :   unsigned ComputeInputFrameSize() const;
     546             :   static unsigned ComputeInterpretedFixedSize(SharedFunctionInfo shared);
     547             : 
     548             :   static unsigned ComputeIncomingArgumentSize(SharedFunctionInfo shared);
     549             :   static unsigned ComputeOutgoingArgumentSize(Code code, unsigned bailout_id);
     550             : 
     551             :   static void GenerateDeoptimizationEntries(MacroAssembler* masm,
     552             :                                             Isolate* isolate,
     553             :                                             DeoptimizeKind kind);
     554             : 
     555             :   // Marks all the code in the given context for deoptimization.
     556             :   static void MarkAllCodeForContext(Context native_context);
     557             : 
     558             :   // Deoptimizes all code marked in the given context.
     559             :   static void DeoptimizeMarkedCodeForContext(Context native_context);
     560             : 
     561             :   // Some architectures need to push padding together with the TOS register
     562             :   // in order to maintain stack alignment.
     563             :   static bool PadTopOfStackRegister();
     564             : 
     565             :   // Searches the list of known deoptimizing code for a Code object
     566             :   // containing the given address (which is supposedly faster than
     567             :   // searching all code objects).
     568             :   Code FindDeoptimizingCode(Address addr);
     569             : 
     570             :   Isolate* isolate_;
     571             :   JSFunction function_;
     572             :   Code compiled_code_;
     573             :   unsigned bailout_id_;
     574             :   DeoptimizeKind deopt_kind_;
     575             :   Address from_;
     576             :   int fp_to_sp_delta_;
     577             :   bool deoptimizing_throw_;
     578             :   int catch_handler_data_;
     579             :   int catch_handler_pc_offset_;
     580             : 
     581             :   // Input frame description.
     582             :   FrameDescription* input_;
     583             :   // Number of output frames.
     584             :   int output_count_;
     585             :   // Number of output js frames.
     586             :   int jsframe_count_;
     587             :   // Array of output frame descriptions.
     588             :   FrameDescription** output_;
     589             : 
     590             :   // Caller frame details computed from input frame.
     591             :   intptr_t caller_frame_top_;
     592             :   intptr_t caller_fp_;
     593             :   intptr_t caller_pc_;
     594             :   intptr_t caller_constant_pool_;
     595             :   intptr_t input_frame_context_;
     596             : 
     597             :   // Key for lookup of previously materialized objects
     598             :   intptr_t stack_fp_;
     599             : 
     600             :   TranslatedState translated_state_;
     601       32505 :   struct ValueToMaterialize {
     602             :     Address output_slot_address_;
     603             :     TranslatedFrame::iterator value_;
     604             :   };
     605             :   std::vector<ValueToMaterialize> values_to_materialize_;
     606             : 
     607             : #ifdef DEBUG
     608             :   DisallowHeapAllocation* disallow_heap_allocation_;
     609             : #endif  // DEBUG
     610             : 
     611             :   CodeTracer::Scope* trace_scope_;
     612             : 
     613             :   static const int table_entry_size_;
     614             : 
     615             :   friend class FrameDescription;
     616             :   friend class DeoptimizedFrameInfo;
     617             : };
     618             : 
     619             : 
     620      113650 : class RegisterValues {
     621             :  public:
     622             :   intptr_t GetRegister(unsigned n) const {
     623             : #if DEBUG
     624             :     // This convoluted DCHECK is needed to work around a gcc problem that
     625             :     // improperly detects an array bounds overflow in optimized debug builds
     626             :     // when using a plain DCHECK.
     627             :     if (n >= arraysize(registers_)) {
     628             :       DCHECK(false);
     629             :       return 0;
     630             :     }
     631             : #endif
     632      110638 :     return registers_[n];
     633             :   }
     634             : 
     635             :   Float32 GetFloatRegister(unsigned n) const {
     636             :     DCHECK(n < arraysize(float_registers_));
     637          91 :     return float_registers_[n];
     638             :   }
     639             : 
     640             :   Float64 GetDoubleRegister(unsigned n) const {
     641             :     DCHECK(n < arraysize(double_registers_));
     642         427 :     return double_registers_[n];
     643             :   }
     644             : 
     645             :   void SetRegister(unsigned n, intptr_t value) {
     646             :     DCHECK(n < arraysize(registers_));
     647     1982136 :     registers_[n] = value;
     648             :   }
     649             : 
     650             :   void SetFloatRegister(unsigned n, Float32 value) {
     651             :     DCHECK(n < arraysize(float_registers_));
     652             :     float_registers_[n] = value;
     653             :   }
     654             : 
     655             :   void SetDoubleRegister(unsigned n, Float64 value) {
     656             :     DCHECK(n < arraysize(double_registers_));
     657             :     double_registers_[n] = value;
     658             :   }
     659             : 
     660             :   // Generated code is writing directly into the below arrays, make sure their
     661             :   // element sizes fit what the machine instructions expect.
     662             :   static_assert(sizeof(Float32) == kFloatSize, "size mismatch");
     663             :   static_assert(sizeof(Float64) == kDoubleSize, "size mismatch");
     664             : 
     665             :   intptr_t registers_[Register::kNumRegisters];
     666             :   Float32 float_registers_[FloatRegister::kNumRegisters];
     667             :   Float64 double_registers_[DoubleRegister::kNumRegisters];
     668             : };
     669             : 
     670             : 
     671             : class FrameDescription {
     672             :  public:
     673             :   explicit FrameDescription(uint32_t frame_size, int parameter_count = 0);
     674             : 
     675             :   void* operator new(size_t size, uint32_t frame_size) {
     676             :     // Subtracts kSystemPointerSize, as the member frame_content_ already
     677             :     // supplies the first element of the area to store the frame.
     678      113650 :     return malloc(size + frame_size - kSystemPointerSize);
     679             :   }
     680             : 
     681             :   void operator delete(void* pointer, uint32_t frame_size) {
     682             :     free(pointer);
     683             :   }
     684             : 
     685             :   void operator delete(void* description) {
     686      113650 :     free(description);
     687             :   }
     688             : 
     689             :   uint32_t GetFrameSize() const {
     690             :     USE(frame_content_);
     691             :     DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_);
     692      167889 :     return static_cast<uint32_t>(frame_size_);
     693             :   }
     694             : 
     695             :   intptr_t GetFrameSlot(unsigned offset) {
     696             :     return *GetFrameSlotPointer(offset);
     697             :   }
     698             : 
     699             :   unsigned GetLastArgumentSlotOffset() {
     700             :     int parameter_slots = parameter_count();
     701             :     if (kPadArguments) parameter_slots = RoundUp(parameter_slots, 2);
     702      108478 :     return GetFrameSize() - parameter_slots * kSystemPointerSize;
     703             :   }
     704             : 
     705             :   Address GetFramePointerAddress() {
     706             :     int fp_offset =
     707      108478 :         GetLastArgumentSlotOffset() - StandardFrameConstants::kCallerSPOffset;
     708             :     return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset));
     709             :   }
     710             : 
     711       54239 :   RegisterValues* GetRegisterValues() { return &register_values_; }
     712             : 
     713             :   void SetFrameSlot(unsigned offset, intptr_t value) {
     714     2383585 :     *GetFrameSlotPointer(offset) = value;
     715             :   }
     716             : 
     717             :   void SetCallerPc(unsigned offset, intptr_t value);
     718             : 
     719             :   void SetCallerFp(unsigned offset, intptr_t value);
     720             : 
     721             :   void SetCallerConstantPool(unsigned offset, intptr_t value);
     722             : 
     723             :   intptr_t GetRegister(unsigned n) const {
     724             :     return register_values_.GetRegister(n);
     725             :   }
     726             : 
     727             :   Float64 GetDoubleRegister(unsigned n) const {
     728             :     return register_values_.GetDoubleRegister(n);
     729             :   }
     730             : 
     731             :   void SetRegister(unsigned n, intptr_t value) {
     732             :     register_values_.SetRegister(n, value);
     733             :   }
     734             : 
     735             :   void SetDoubleRegister(unsigned n, Float64 value) {
     736             :     register_values_.SetDoubleRegister(n, value);
     737             :   }
     738             : 
     739             :   intptr_t GetTop() const { return top_; }
     740       59411 :   void SetTop(intptr_t top) { top_ = top; }
     741             : 
     742             :   intptr_t GetPc() const { return pc_; }
     743       59411 :   void SetPc(intptr_t pc) { pc_ = pc; }
     744             : 
     745             :   intptr_t GetFp() const { return fp_; }
     746       59411 :   void SetFp(intptr_t fp) { fp_ = fp; }
     747             : 
     748             :   intptr_t GetContext() const { return context_; }
     749       58042 :   void SetContext(intptr_t context) { context_ = context; }
     750             : 
     751             :   intptr_t GetConstantPool() const { return constant_pool_; }
     752             :   void SetConstantPool(intptr_t constant_pool) {
     753             :     constant_pool_ = constant_pool;
     754             :   }
     755             : 
     756       54633 :   void SetContinuation(intptr_t pc) { continuation_ = pc; }
     757             : 
     758             :   // Argument count, including receiver.
     759             :   int parameter_count() { return parameter_count_; }
     760             : 
     761             :   static int registers_offset() {
     762             :     return OFFSET_OF(FrameDescription, register_values_.registers_);
     763             :   }
     764             : 
     765             :   static int double_registers_offset() {
     766             :     return OFFSET_OF(FrameDescription, register_values_.double_registers_);
     767             :   }
     768             : 
     769             :   static int float_registers_offset() {
     770             :     return OFFSET_OF(FrameDescription, register_values_.float_registers_);
     771             :   }
     772             : 
     773             :   static int frame_size_offset() {
     774             :     return offsetof(FrameDescription, frame_size_);
     775             :   }
     776             : 
     777             :   static int pc_offset() { return offsetof(FrameDescription, pc_); }
     778             : 
     779             :   static int continuation_offset() {
     780             :     return offsetof(FrameDescription, continuation_);
     781             :   }
     782             : 
     783             :   static int frame_content_offset() {
     784             :     return offsetof(FrameDescription, frame_content_);
     785             :   }
     786             : 
     787             :  private:
     788             :   static const uint32_t kZapUint32 = 0xbeeddead;
     789             : 
     790             :   // Frame_size_ must hold a uint32_t value.  It is only a uintptr_t to
     791             :   // keep the variable-size array frame_content_ of type intptr_t at
     792             :   // the end of the structure aligned.
     793             :   uintptr_t frame_size_;  // Number of bytes.
     794             :   int parameter_count_;
     795             :   RegisterValues register_values_;
     796             :   intptr_t top_;
     797             :   intptr_t pc_;
     798             :   intptr_t fp_;
     799             :   intptr_t context_;
     800             :   intptr_t constant_pool_;
     801             : 
     802             :   // Continuation is the PC where the execution continues after
     803             :   // deoptimizing.
     804             :   intptr_t continuation_;
     805             : 
     806             :   // This must be at the end of the object as the object is allocated larger
     807             :   // than it's definition indicate to extend this array.
     808             :   intptr_t frame_content_[1];
     809             : 
     810             :   intptr_t* GetFrameSlotPointer(unsigned offset) {
     811             :     DCHECK(offset < frame_size_);
     812             :     return reinterpret_cast<intptr_t*>(
     813     2492063 :         reinterpret_cast<Address>(this) + frame_content_offset() + offset);
     814             :   }
     815             : };
     816             : 
     817             : 
     818             : class DeoptimizerData {
     819             :  public:
     820             :   explicit DeoptimizerData(Heap* heap);
     821             :   ~DeoptimizerData();
     822             : 
     823             : #ifdef DEBUG
     824             :   bool IsDeoptEntryCode(Code code) const {
     825             :     for (int i = 0; i < kLastDeoptimizeKind + 1; i++) {
     826             :       if (code == deopt_entry_code_[i]) return true;
     827             :     }
     828             :     return false;
     829             :   }
     830             : #endif  // DEBUG
     831             : 
     832             :  private:
     833             :   Heap* heap_;
     834             :   static const int kLastDeoptimizeKind =
     835             :       static_cast<int>(DeoptimizeKind::kLastDeoptimizeKind);
     836             :   Code deopt_entry_code_[kLastDeoptimizeKind + 1];
     837             :   Code deopt_entry_code(DeoptimizeKind kind);
     838             :   void set_deopt_entry_code(DeoptimizeKind kind, Code code);
     839             : 
     840             :   Deoptimizer* current_;
     841             : 
     842             :   friend class Deoptimizer;
     843             : 
     844             :   DISALLOW_COPY_AND_ASSIGN(DeoptimizerData);
     845             : };
     846             : 
     847             : class TranslationBuffer {
     848             :  public:
     849             :   explicit TranslationBuffer(Zone* zone) : contents_(zone) {}
     850             : 
     851     3793718 :   int CurrentIndex() const { return static_cast<int>(contents_.size()); }
     852             :   void Add(int32_t value);
     853             : 
     854             :   Handle<ByteArray> CreateByteArray(Factory* factory);
     855             : 
     856             :  private:
     857             :   ZoneChunkList<uint8_t> contents_;
     858             : };
     859             : 
     860             : class TranslationIterator {
     861             :  public:
     862             :   TranslationIterator(ByteArray buffer, int index);
     863             : 
     864             :   int32_t Next();
     865             : 
     866             :   bool HasNext() const;
     867             : 
     868             :   void Skip(int n) {
     869      578990 :     for (int i = 0; i < n; i++) Next();
     870             :   }
     871             : 
     872             :  private:
     873             :   ByteArray buffer_;
     874             :   int index_;
     875             : };
     876             : 
     877             : #define TRANSLATION_OPCODE_LIST(V)                     \
     878             :   V(BEGIN)                                             \
     879             :   V(INTERPRETED_FRAME)                                 \
     880             :   V(BUILTIN_CONTINUATION_FRAME)                        \
     881             :   V(JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME)            \
     882             :   V(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME) \
     883             :   V(CONSTRUCT_STUB_FRAME)                              \
     884             :   V(ARGUMENTS_ADAPTOR_FRAME)                           \
     885             :   V(DUPLICATED_OBJECT)                                 \
     886             :   V(ARGUMENTS_ELEMENTS)                                \
     887             :   V(ARGUMENTS_LENGTH)                                  \
     888             :   V(CAPTURED_OBJECT)                                   \
     889             :   V(REGISTER)                                          \
     890             :   V(INT32_REGISTER)                                    \
     891             :   V(INT64_REGISTER)                                    \
     892             :   V(UINT32_REGISTER)                                   \
     893             :   V(BOOL_REGISTER)                                     \
     894             :   V(FLOAT_REGISTER)                                    \
     895             :   V(DOUBLE_REGISTER)                                   \
     896             :   V(STACK_SLOT)                                        \
     897             :   V(INT32_STACK_SLOT)                                  \
     898             :   V(INT64_STACK_SLOT)                                  \
     899             :   V(UINT32_STACK_SLOT)                                 \
     900             :   V(BOOL_STACK_SLOT)                                   \
     901             :   V(FLOAT_STACK_SLOT)                                  \
     902             :   V(DOUBLE_STACK_SLOT)                                 \
     903             :   V(LITERAL)                                           \
     904             :   V(UPDATE_FEEDBACK)
     905             : 
     906             : class Translation {
     907             :  public:
     908             : #define DECLARE_TRANSLATION_OPCODE_ENUM(item) item,
     909             :   enum Opcode {
     910             :     TRANSLATION_OPCODE_LIST(DECLARE_TRANSLATION_OPCODE_ENUM)
     911             :     LAST = LITERAL
     912             :   };
     913             : #undef DECLARE_TRANSLATION_OPCODE_ENUM
     914             : 
     915     3329972 :   Translation(TranslationBuffer* buffer, int frame_count, int jsframe_count,
     916             :               int update_feedback_count, Zone* zone)
     917     6659944 :       : buffer_(buffer), index_(buffer->CurrentIndex()), zone_(zone) {
     918     3329972 :     buffer_->Add(BEGIN);
     919     3329973 :     buffer_->Add(frame_count);
     920     3329981 :     buffer_->Add(jsframe_count);
     921     3329977 :     buffer_->Add(update_feedback_count);
     922     3329979 :   }
     923             : 
     924             :   int index() const { return index_; }
     925             : 
     926             :   // Commands.
     927             :   void BeginInterpretedFrame(BailoutId bytecode_offset, int literal_id,
     928             :                              unsigned height, int return_value_offset,
     929             :                              int return_value_count);
     930             :   void BeginArgumentsAdaptorFrame(int literal_id, unsigned height);
     931             :   void BeginConstructStubFrame(BailoutId bailout_id, int literal_id,
     932             :                                unsigned height);
     933             :   void BeginBuiltinContinuationFrame(BailoutId bailout_id, int literal_id,
     934             :                                      unsigned height);
     935             :   void BeginJavaScriptBuiltinContinuationFrame(BailoutId bailout_id,
     936             :                                                int literal_id, unsigned height);
     937             :   void BeginJavaScriptBuiltinContinuationWithCatchFrame(BailoutId bailout_id,
     938             :                                                         int literal_id,
     939             :                                                         unsigned height);
     940             :   void ArgumentsElements(CreateArgumentsType type);
     941             :   void ArgumentsLength(CreateArgumentsType type);
     942             :   void BeginCapturedObject(int length);
     943             :   void AddUpdateFeedback(int vector_literal, int slot);
     944             :   void DuplicateObject(int object_index);
     945             :   void StoreRegister(Register reg);
     946             :   void StoreInt32Register(Register reg);
     947             :   void StoreInt64Register(Register reg);
     948             :   void StoreUint32Register(Register reg);
     949             :   void StoreBoolRegister(Register reg);
     950             :   void StoreFloatRegister(FloatRegister reg);
     951             :   void StoreDoubleRegister(DoubleRegister reg);
     952             :   void StoreStackSlot(int index);
     953             :   void StoreInt32StackSlot(int index);
     954             :   void StoreInt64StackSlot(int index);
     955             :   void StoreUint32StackSlot(int index);
     956             :   void StoreBoolStackSlot(int index);
     957             :   void StoreFloatStackSlot(int index);
     958             :   void StoreDoubleStackSlot(int index);
     959             :   void StoreLiteral(int literal_id);
     960             :   void StoreJSFrameFunction();
     961             : 
     962             :   Zone* zone() const { return zone_; }
     963             : 
     964             :   static int NumberOfOperandsFor(Opcode opcode);
     965             : 
     966             : #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
     967             :   static const char* StringFor(Opcode opcode);
     968             : #endif
     969             : 
     970             :  private:
     971             :   TranslationBuffer* buffer_;
     972             :   int index_;
     973             :   Zone* zone_;
     974             : };
     975             : 
     976             : 
     977       62427 : class MaterializedObjectStore {
     978             :  public:
     979       62442 :   explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) {
     980             :   }
     981             : 
     982             :   Handle<FixedArray> Get(Address fp);
     983             :   void Set(Address fp, Handle<FixedArray> materialized_objects);
     984             :   bool Remove(Address fp);
     985             : 
     986             :  private:
     987             :   Isolate* isolate() const { return isolate_; }
     988             :   Handle<FixedArray> GetStackEntries();
     989             :   Handle<FixedArray> EnsureStackEntries(int size);
     990             : 
     991             :   int StackIdToIndex(Address fp);
     992             : 
     993             :   Isolate* isolate_;
     994             :   std::vector<Address> frame_fps_;
     995             : };
     996             : 
     997             : 
     998             : // Class used to represent an unoptimized frame when the debugger
     999             : // needs to inspect a frame that is part of an optimized frame. The
    1000             : // internally used FrameDescription objects are not GC safe so for use
    1001             : // by the debugger frame information is copied to an object of this type.
    1002             : // Represents parameters in unadapted form so their number might mismatch
    1003             : // formal parameter count.
    1004       49910 : class DeoptimizedFrameInfo : public Malloced {
    1005             :  public:
    1006             :   DeoptimizedFrameInfo(TranslatedState* state,
    1007             :                        TranslatedState::iterator frame_it, Isolate* isolate);
    1008             : 
    1009             :   // Return the number of incoming arguments.
    1010           0 :   int parameters_count() { return static_cast<int>(parameters_.size()); }
    1011             : 
    1012             :   // Return the height of the expression stack.
    1013             :   int expression_count() { return static_cast<int>(expression_stack_.size()); }
    1014             : 
    1015             :   // Get the frame function.
    1016             :   Handle<JSFunction> GetFunction() { return function_; }
    1017             : 
    1018             :   // Get the frame context.
    1019             :   Handle<Object> GetContext() { return context_; }
    1020             : 
    1021             :   // Get an incoming argument.
    1022             :   Handle<Object> GetParameter(int index) {
    1023             :     DCHECK(0 <= index && index < parameters_count());
    1024       24524 :     return parameters_[index];
    1025             :   }
    1026             : 
    1027             :   // Get an expression from the expression stack.
    1028             :   Handle<Object> GetExpression(int index) {
    1029             :     DCHECK(0 <= index && index < expression_count());
    1030       18604 :     return expression_stack_[index];
    1031             :   }
    1032             : 
    1033             :   int GetSourcePosition() {
    1034             :     return source_position_;
    1035             :   }
    1036             : 
    1037             :  private:
    1038             :   // Set an incoming argument.
    1039             :   void SetParameter(int index, Handle<Object> obj) {
    1040             :     DCHECK(0 <= index && index < parameters_count());
    1041       82530 :     parameters_[index] = obj;
    1042             :   }
    1043             : 
    1044             :   // Set an expression on the expression stack.
    1045             :   void SetExpression(int index, Handle<Object> obj) {
    1046             :     DCHECK(0 <= index && index < expression_count());
    1047      230516 :     expression_stack_[index] = obj;
    1048             :   }
    1049             : 
    1050             :   Handle<JSFunction> function_;
    1051             :   Handle<Object> context_;
    1052             :   std::vector<Handle<Object> > parameters_;
    1053             :   std::vector<Handle<Object> > expression_stack_;
    1054             :   int source_position_;
    1055             : 
    1056             :   friend class Deoptimizer;
    1057             : };
    1058             : 
    1059             : }  // namespace internal
    1060             : }  // namespace v8
    1061             : 
    1062             : #endif  // V8_DEOPTIMIZER_H_

Generated by: LCOV version 1.10