V8 Project
v8::internal::Deoptimizer Class Reference

#include <deoptimizer.h>

+ Inheritance diagram for v8::internal::Deoptimizer:
+ Collaboration diagram for v8::internal::Deoptimizer:

Classes

class  BASE_EMBEDDED
 
struct  JumpTableEntry
 
struct  Reason
 
class  TableEntryGenerator
 

Public Types

enum  BailoutType { EAGER , LAZY , SOFT , DEBUGGER }
 
enum  GetEntryMode { CALCULATE_ENTRY_ADDRESS , ENSURE_ENTRY_CODE }
 

Public Member Functions

int output_count () const
 
Handle< JSFunctionfunction () const
 
Handle< Codecompiled_code () const
 
BailoutType bailout_type () const
 
int jsframe_count () const
 
 ~Deoptimizer ()
 
void MaterializeHeapObjects (JavaScriptFrameIterator *it)
 
void MaterializeHeapNumbersForDebuggerInspectableFrame (Address parameters_top, uint32_t parameters_size, Address expressions_top, uint32_t expressions_size, DeoptimizedFrameInfo *info)
 
int ConvertJSFrameIndexToFrameIndex (int jsframe_index)
 
Isolateisolate () const
 
- Public Member Functions inherited from v8::internal::Malloced
void * operator new (size_t size)
 
void operator delete (void *p)
 

Static Public Member Functions

static bool TraceEnabledFor (BailoutType deopt_type, StackFrame::Type frame_type)
 
static const char * MessageFor (BailoutType type)
 
static DeoptimizerNew (JSFunction *function, BailoutType type, unsigned bailout_id, Address from, int fp_to_sp_delta, Isolate *isolate)
 
static DeoptimizerGrab (Isolate *isolate)
 
static DeoptimizedFrameInfoDebuggerInspectableFrame (JavaScriptFrame *frame, int jsframe_index, Isolate *isolate)
 
static void DeleteDebuggerInspectableFrame (DeoptimizedFrameInfo *info, Isolate *isolate)
 
static void EnsureRelocSpaceForLazyDeoptimization (Handle< Code > code)
 
static void DeoptimizeFunction (JSFunction *function)
 
static void DeoptimizeAll (Isolate *isolate)
 
static void DeoptimizeGlobalObject (JSObject *object)
 
static void DeoptimizeMarkedCode (Isolate *isolate)
 
static void VisitAllOptimizedFunctions (Isolate *isolate, OptimizedFunctionVisitor *visitor)
 
static int patch_size ()
 
static void ComputeOutputFrames (Deoptimizer *deoptimizer)
 
static Address GetDeoptimizationEntry (Isolate *isolate, int id, BailoutType type, GetEntryMode mode=ENSURE_ENTRY_CODE)
 
static int GetDeoptimizationId (Isolate *isolate, Address addr, BailoutType type)
 
static int GetOutputInfo (DeoptimizationOutputData *data, BailoutId node_id, SharedFunctionInfo *shared)
 
static int input_offset ()
 
static int output_count_offset ()
 
static int output_offset ()
 
static int has_alignment_padding_offset ()
 
static int GetDeoptimizedCodeCount (Isolate *isolate)
 
static size_t GetMaxDeoptTableSize ()
 
static void EnsureCodeForDeoptimizationEntry (Isolate *isolate, BailoutType type, int max_entry_id)
 
- Static Public Member Functions inherited from v8::internal::Malloced
static void FatalProcessOutOfMemory ()
 
static void * New (size_t size)
 
static void Delete (void *p)
 

Static Public Attributes

static const int kBailoutTypesWithCodeEntry = SOFT + 1
 
static const int kNotDeoptimizationEntry = -1
 

Private Member Functions

 Deoptimizer (Isolate *isolate, JSFunction *function, BailoutType type, unsigned bailout_id, Address from, int fp_to_sp_delta, Code *optimized_code)
 
CodeFindOptimizedCode (JSFunction *function, Code *optimized_code)
 
void PrintFunctionName ()
 
void DeleteFrameDescriptions ()
 
void DoComputeOutputFrames ()
 
void DoComputeJSFrame (TranslationIterator *iterator, int frame_index)
 
void DoComputeArgumentsAdaptorFrame (TranslationIterator *iterator, int frame_index)
 
void DoComputeConstructStubFrame (TranslationIterator *iterator, int frame_index)
 
void DoComputeAccessorStubFrame (TranslationIterator *iterator, int frame_index, bool is_setter_stub_frame)
 
void DoComputeCompiledStubFrame (TranslationIterator *iterator, int frame_index)
 
void DoTranslateObject (TranslationIterator *iterator, int object_index, int field_index)
 
void DoTranslateCommand (TranslationIterator *iterator, int frame_index, unsigned output_offset)
 
void DoTranslateObjectAndSkip (TranslationIterator *iterator)
 
unsigned ComputeInputFrameSize () const
 
unsigned ComputeFixedSize (JSFunction *function) const
 
unsigned ComputeIncomingArgumentSize (JSFunction *function) const
 
unsigned ComputeOutgoingArgumentSize () const
 
ObjectComputeLiteral (int index) const
 
void AddObjectStart (intptr_t slot_address, int argc, bool is_arguments)
 
void AddObjectDuplication (intptr_t slot, int object_index)
 
void AddObjectTaggedValue (intptr_t value)
 
void AddObjectDoubleValue (double value)
 
void AddDoubleValue (intptr_t slot_address, double value)
 
bool ArgumentsObjectIsAdapted (int object_index)
 
Handle< JSFunctionArgumentsObjectFunction (int object_index)
 
Handle< ObjectMaterializeNextHeapObject ()
 
Handle< ObjectMaterializeNextValue ()
 
CodeFindDeoptimizingCode (Address addr)
 
void FillInputFrame (Address tos, JavaScriptFrame *frame)
 
void SetPlatformCompiledStubRegisters (FrameDescription *output_frame, CodeStubDescriptor *desc)
 
void CopyDoubleRegisters (FrameDescription *output_frame)
 
bool HasAlignmentPadding (JSFunction *function)
 

Static Private Member Functions

static void GenerateDeoptimizationEntries (MacroAssembler *masm, int count, BailoutType type)
 
static void MarkAllCodeForContext (Context *native_context)
 
static void VisitAllOptimizedFunctionsForContext (Context *context, OptimizedFunctionVisitor *visitor)
 
static void DeoptimizeMarkedCodeForContext (Context *native_context)
 
static void PatchCodeForDeoptimization (Isolate *isolate, Code *code)
 

Private Attributes

Isolateisolate_
 
JSFunctionfunction_
 
Codecompiled_code_
 
unsigned bailout_id_
 
BailoutType bailout_type_
 
Address from_
 
int fp_to_sp_delta_
 
int has_alignment_padding_
 
FrameDescriptioninput_
 
int output_count_
 
int jsframe_count_
 
FrameDescription ** output_
 
List< Object * > deferred_objects_tagged_values_
 
List< HeapNumberMaterializationDescriptor< int > > deferred_objects_double_values_
 
List< ObjectMaterializationDescriptor > deferred_objects_
 
List< HeapNumberMaterializationDescriptor< Address > > deferred_heap_numbers_
 
Address stack_fp_
 
Handle< FixedArraypreviously_materialized_objects_
 
int prev_materialized_count_
 
List< Handle< JSFunction > > jsframe_functions_
 
List< booljsframe_has_adapted_arguments_
 
List< Handle< Object > > * materialized_values_
 
List< Handle< Object > > * materialized_objects_
 
int materialization_value_index_
 
int materialization_object_index_
 
CodeTracer::Scope * trace_scope_
 

Static Private Attributes

static const int kMinNumberOfEntries = 64
 
static const int kMaxNumberOfEntries = 16384
 
static const int table_entry_size_ = 8
 

Friends

class FrameDescription
 
class DeoptimizedFrameInfo
 

Detailed Description

Definition at line 91 of file deoptimizer.h.

Member Enumeration Documentation

◆ BailoutType

Enumerator
EAGER 
LAZY 
SOFT 
DEBUGGER 

Definition at line 93 of file deoptimizer.h.

93  {
94  EAGER,
95  LAZY,
96  SOFT,
97  // This last bailout type is not really a bailout, but used by the
98  // debugger to deoptimize stack frames to allow inspection.
99  DEBUGGER
100  };

◆ GetEntryMode

Enumerator
CALCULATE_ENTRY_ADDRESS 
ENSURE_ENTRY_CODE 

Definition at line 216 of file deoptimizer.h.

Constructor & Destructor Documentation

◆ ~Deoptimizer()

v8::internal::Deoptimizer::~Deoptimizer ( )

Definition at line 648 of file deoptimizer.cc.

648  {
649  DCHECK(input_ == NULL && output_ == NULL);
650  DCHECK(disallow_heap_allocation_ == NULL);
651  delete trace_scope_;
652 }
FrameDescription ** output_
Definition: deoptimizer.h:421
FrameDescription * input_
Definition: deoptimizer.h:415
CodeTracer::Scope * trace_scope_
Definition: deoptimizer.h:449
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK(condition)
Definition: logging.h:205

References DCHECK, input_, NULL, output_, and trace_scope_.

◆ Deoptimizer()

v8::internal::Deoptimizer::Deoptimizer ( Isolate isolate,
JSFunction function,
BailoutType  type,
unsigned  bailout_id,
Address  from,
int  fp_to_sp_delta,
Code optimized_code 
)
private

Definition at line 548 of file deoptimizer.cc.

555  : isolate_(isolate),
556  function_(function),
557  bailout_id_(bailout_id),
558  bailout_type_(type),
559  from_(from),
560  fp_to_sp_delta_(fp_to_sp_delta),
562  input_(NULL),
563  output_count_(0),
564  jsframe_count_(0),
565  output_(NULL),
576  trace_scope_(NULL) {
577  // For COMPILED_STUBs called from builtins, the function pointer is a SMI
578  // indicating an internal frame.
579  if (function->IsSmi()) {
580  function = NULL;
581  }
582  DCHECK(from != NULL);
583  if (function != NULL && function->IsOptimized()) {
584  function->shared()->increment_deopt_count();
586  isolate->counters()->soft_deopts_executed()->Increment();
587  // Soft deopts shouldn't count against the overall re-optimization count
588  // that can eventually lead to disabling optimization for a function.
589  int opt_count = function->shared()->opt_count();
590  if (opt_count > 0) opt_count--;
591  function->shared()->set_opt_count(opt_count);
592  }
593  }
594  compiled_code_ = FindOptimizedCode(function, optimized_code);
595 
596 #if DEBUG
598  if (type == EAGER || type == SOFT || type == LAZY) {
599  DCHECK(compiled_code_->kind() != Code::FUNCTION);
600  }
601 #endif
602 
603  StackFrame::Type frame_type = function == NULL
605  : StackFrame::JAVA_SCRIPT;
606  trace_scope_ = TraceEnabledFor(type, frame_type) ?
607  new CodeTracer::Scope(isolate->GetCodeTracer()) : NULL;
608 #ifdef DEBUG
609  CHECK(AllowHeapAllocation::IsAllowed());
610  disallow_heap_allocation_ = new DisallowHeapAllocation();
611 #endif // DEBUG
612  unsigned size = ComputeInputFrameSize();
613  input_ = new(size) FrameDescription(size, function);
614  input_->SetFrameType(frame_type);
615 }
unsigned ComputeInputFrameSize() const
List< Handle< Object > > * materialized_objects_
Definition: deoptimizer.h:441
Code * FindOptimizedCode(JSFunction *function, Code *optimized_code)
Definition: deoptimizer.cc:618
friend class FrameDescription
Definition: deoptimizer.h:453
List< Handle< Object > > * materialized_values_
Definition: deoptimizer.h:440
Handle< JSFunction > function() const
Definition: deoptimizer.h:149
List< ObjectMaterializationDescriptor > deferred_objects_
Definition: deoptimizer.h:427
List< Handle< JSFunction > > jsframe_functions_
Definition: deoptimizer.h:436
List< bool > jsframe_has_adapted_arguments_
Definition: deoptimizer.h:437
static bool TraceEnabledFor(BailoutType deopt_type, StackFrame::Type frame_type)
Definition: deoptimizer.cc:520
List< HeapNumberMaterializationDescriptor< int > > deferred_objects_double_values_
Definition: deoptimizer.h:426
List< Object * > deferred_objects_tagged_values_
Definition: deoptimizer.h:424
Isolate * isolate() const
Definition: deoptimizer.h:292
List< HeapNumberMaterializationDescriptor< Address > > deferred_heap_numbers_
Definition: deoptimizer.h:428
void SetFrameType(StackFrame::Type type)
Definition: deoptimizer.h:556
Counters * counters()
Definition: isolate.h:857
CodeTracer * GetCodeTracer()
Definition: isolate.cc:2154
enable harmony numeric enable harmony object literal extensions Optimize object size
#define CHECK(condition)
Definition: logging.h:36
PerThreadAssertScopeDebugOnly< HEAP_ALLOCATION_ASSERT, false > DisallowHeapAllocation
Definition: assert-scope.h:110
TypeImpl< ZoneTypeConfig > Type

References bailout_type_, CHECK, compiled_code_, ComputeInputFrameSize(), v8::internal::Isolate::counters(), DCHECK, EAGER, FindOptimizedCode(), FrameDescription, function(), v8::internal::Isolate::GetCodeTracer(), input_, isolate(), v8::internal::Code::kind(), LAZY, NULL, v8::internal::FrameDescription::SetFrameType(), size, SOFT, v8::internal::STUB, trace_scope_, and TraceEnabledFor().

Referenced by DebuggerInspectableFrame(), and New().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Function Documentation

◆ AddDoubleValue()

void v8::internal::Deoptimizer::AddDoubleValue ( intptr_t  slot_address,
double  value 
)
private

Definition at line 2783 of file deoptimizer.cc.

2783  {
2784  HeapNumberMaterializationDescriptor<Address> value_desc(
2785  reinterpret_cast<Address>(slot_address), value);
2786  deferred_heap_numbers_.Add(value_desc);
2787 }
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:17
byte * Address
Definition: globals.h:101

References v8::internal::List< T, AllocationPolicy >::Add(), and deferred_heap_numbers_.

Referenced by DoTranslateCommand().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ AddObjectDoubleValue()

void v8::internal::Deoptimizer::AddObjectDoubleValue ( double  value)
private

Definition at line 2775 of file deoptimizer.cc.

2775  {
2776  deferred_objects_tagged_values_.Add(isolate()->heap()->the_hole_value());
2777  HeapNumberMaterializationDescriptor<int> value_desc(
2778  deferred_objects_tagged_values_.length() - 1, value);
2780 }

References v8::internal::List< T, AllocationPolicy >::Add(), deferred_objects_double_values_, deferred_objects_tagged_values_, and isolate().

Referenced by DoTranslateObject().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ AddObjectDuplication()

void v8::internal::Deoptimizer::AddObjectDuplication ( intptr_t  slot,
int  object_index 
)
private

Definition at line 2763 of file deoptimizer.cc.

2763  {
2764  ObjectMaterializationDescriptor object_desc(
2765  reinterpret_cast<Address>(slot), jsframe_count_, -1, object_index, false);
2766  deferred_objects_.Add(object_desc);
2767 }

References v8::internal::List< T, AllocationPolicy >::Add(), deferred_objects_, and jsframe_count_.

Referenced by DoTranslateCommand(), DoTranslateObject(), and DoTranslateObjectAndSkip().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ AddObjectStart()

void v8::internal::Deoptimizer::AddObjectStart ( intptr_t  slot_address,
int  argc,
bool  is_arguments 
)
private

Definition at line 2756 of file deoptimizer.cc.

2756  {
2757  ObjectMaterializationDescriptor object_desc(
2758  reinterpret_cast<Address>(slot), jsframe_count_, length, -1, is_args);
2759  deferred_objects_.Add(object_desc);
2760 }

References v8::internal::List< T, AllocationPolicy >::Add(), deferred_objects_, and jsframe_count_.

Referenced by DoTranslateCommand(), DoTranslateObject(), and DoTranslateObjectAndSkip().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ AddObjectTaggedValue()

void v8::internal::Deoptimizer::AddObjectTaggedValue ( intptr_t  value)
private

Definition at line 2770 of file deoptimizer.cc.

2770  {
2771  deferred_objects_tagged_values_.Add(reinterpret_cast<Object*>(value));
2772 }
kSerializedDataOffset Object
Definition: objects-inl.h:5322

References deferred_objects_tagged_values_.

Referenced by DoTranslateObject().

+ Here is the caller graph for this function:

◆ ArgumentsObjectFunction()

Handle<JSFunction> v8::internal::Deoptimizer::ArgumentsObjectFunction ( int  object_index)
inlineprivate

Definition at line 356 of file deoptimizer.h.

356  {
357  ObjectMaterializationDescriptor desc = deferred_objects_.at(object_index);
358  int reverse_jsframe_index = jsframe_count_ - desc.jsframe_index() - 1;
359  return jsframe_functions_[reverse_jsframe_index];
360  }
T & at(int i) const
Definition: list.h:69

References v8::internal::List< T, AllocationPolicy >::at(), deferred_objects_, jsframe_count_, and jsframe_functions_.

Referenced by MaterializeNextHeapObject().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ArgumentsObjectIsAdapted()

bool v8::internal::Deoptimizer::ArgumentsObjectIsAdapted ( int  object_index)
inlineprivate

Definition at line 350 of file deoptimizer.h.

350  {
351  ObjectMaterializationDescriptor desc = deferred_objects_.at(object_index);
352  int reverse_jsframe_index = jsframe_count_ - desc.jsframe_index() - 1;
353  return jsframe_has_adapted_arguments_[reverse_jsframe_index];
354  }

References v8::internal::List< T, AllocationPolicy >::at(), deferred_objects_, jsframe_count_, and jsframe_has_adapted_arguments_.

Referenced by MaterializeHeapObjects(), and MaterializeNextHeapObject().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ bailout_type()

BailoutType v8::internal::Deoptimizer::bailout_type ( ) const
inline

Definition at line 151 of file deoptimizer.h.

151 { return bailout_type_; }

References bailout_type_.

Referenced by v8::internal::RUNTIME_FUNCTION().

+ Here is the caller graph for this function:

◆ compiled_code()

Handle<Code> v8::internal::Deoptimizer::compiled_code ( ) const
inline

Definition at line 150 of file deoptimizer.h.

150 { return Handle<Code>(compiled_code_); }

References compiled_code_.

Referenced by FindOptimizedCode(), and v8::internal::RUNTIME_FUNCTION().

+ Here is the caller graph for this function:

◆ ComputeFixedSize()

unsigned v8::internal::Deoptimizer::ComputeFixedSize ( JSFunction function) const
private

Definition at line 2720 of file deoptimizer.cc.

2720  {
2721  // The fixed part of the frame consists of the return address, frame
2722  // pointer, function, context, and all the incoming arguments.
2723  return ComputeIncomingArgumentSize(function) +
2725 }
unsigned ComputeIncomingArgumentSize(JSFunction *function) const
static const int kFixedFrameSize
Definition: frames.h:158

References ComputeIncomingArgumentSize(), and v8::internal::StandardFrameConstants::kFixedFrameSize.

Referenced by ComputeInputFrameSize(), and DoComputeJSFrame().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ComputeIncomingArgumentSize()

unsigned v8::internal::Deoptimizer::ComputeIncomingArgumentSize ( JSFunction function) const
private

Definition at line 2728 of file deoptimizer.cc.

2728  {
2729  // The incoming arguments is the values for formal parameters and
2730  // the receiver. Every slot contains a pointer.
2731  if (function->IsSmi()) {
2732  CHECK_EQ(Smi::cast(function), Smi::FromInt(StackFrame::STUB));
2733  return 0;
2734  }
2735  unsigned arguments = function->shared()->formal_parameter_count() + 1;
2736  return arguments * kPointerSize;
2737 }
static Smi * FromInt(int value)
Definition: objects-inl.h:1321
#define CHECK_EQ(expected, value)
Definition: logging.h:169
const int kPointerSize
Definition: globals.h:129

References CHECK_EQ, v8::internal::Smi::FromInt(), function(), v8::internal::kPointerSize, and v8::internal::STUB.

Referenced by ComputeFixedSize().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ComputeInputFrameSize()

unsigned v8::internal::Deoptimizer::ComputeInputFrameSize ( ) const
private

Definition at line 2705 of file deoptimizer.cc.

2705  {
2706  unsigned fixed_size = ComputeFixedSize(function_);
2707  // The fp-to-sp delta already takes the context, constant pool pointer and the
2708  // function into account so we have to avoid double counting them.
2709  unsigned result = fixed_size + fp_to_sp_delta_ -
2711  if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
2712  unsigned stack_slots = compiled_code_->stack_slots();
2713  unsigned outgoing_size = ComputeOutgoingArgumentSize();
2714  CHECK(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size);
2715  }
2716  return result;
2717 }
unsigned stack_slots()
Definition: objects-inl.h:4801
unsigned ComputeFixedSize(JSFunction *function) const
unsigned ComputeOutgoingArgumentSize() const
static const int kFixedFrameSizeFromFp
Definition: frames.h:157

References CHECK, compiled_code_, ComputeFixedSize(), ComputeOutgoingArgumentSize(), fp_to_sp_delta_, function_, v8::internal::StandardFrameConstants::kFixedFrameSizeFromFp, v8::internal::Code::kind(), v8::internal::kPointerSize, and v8::internal::Code::stack_slots().

Referenced by Deoptimizer().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ComputeLiteral()

Object * v8::internal::Deoptimizer::ComputeLiteral ( int  index) const
private

Definition at line 2748 of file deoptimizer.cc.

2748  {
2749  DeoptimizationInputData* data = DeoptimizationInputData::cast(
2750  compiled_code_->deoptimization_data());
2751  FixedArray* literals = data->LiteralArray();
2752  return literals->get(index);
2753 }
enable harmony numeric literals(0o77, 0b11)") DEFINE_BOOL(harmony_object_literals

References compiled_code_, and literals().

Referenced by DoComputeAccessorStubFrame(), DoComputeArgumentsAdaptorFrame(), DoComputeConstructStubFrame(), DoComputeJSFrame(), DoTranslateCommand(), and DoTranslateObject().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ComputeOutgoingArgumentSize()

unsigned v8::internal::Deoptimizer::ComputeOutgoingArgumentSize ( ) const
private

Definition at line 2740 of file deoptimizer.cc.

2740  {
2741  DeoptimizationInputData* data = DeoptimizationInputData::cast(
2742  compiled_code_->deoptimization_data());
2743  unsigned height = data->ArgumentsStackHeight(bailout_id_)->value();
2744  return height * kPointerSize;
2745 }

References bailout_id_, compiled_code_, and v8::internal::kPointerSize.

Referenced by ComputeInputFrameSize().

+ Here is the caller graph for this function:

◆ ComputeOutputFrames()

void v8::internal::Deoptimizer::ComputeOutputFrames ( Deoptimizer deoptimizer)
static

Definition at line 515 of file deoptimizer.cc.

515  {
516  deoptimizer->DoComputeOutputFrames();
517 }

References DoComputeOutputFrames().

Referenced by DebuggerInspectableFrame().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ConvertJSFrameIndexToFrameIndex()

int v8::internal::Deoptimizer::ConvertJSFrameIndexToFrameIndex ( int  jsframe_index)

Definition at line 120 of file deoptimizer.cc.

120  {
121  if (jsframe_index == 0) return 0;
122 
123  int frame_index = 0;
124  while (jsframe_index >= 0) {
125  FrameDescription* frame = output_[frame_index];
126  if (frame->GetFrameType() == StackFrame::JAVA_SCRIPT) {
127  jsframe_index--;
128  }
129  frame_index++;
130  }
131 
132  return frame_index - 1;
133 }

References v8::internal::FrameDescription::GetFrameType(), and output_.

Referenced by DebuggerInspectableFrame().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ CopyDoubleRegisters()

void v8::internal::Deoptimizer::CopyDoubleRegisters ( FrameDescription output_frame)
private

Definition at line 114 of file deoptimizer-arm.cc.

114  {
115  for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; ++i) {
116  double double_value = input_->GetDoubleRegister(i);
117  output_frame->SetDoubleRegister(i, double_value);
118  }
119 }
double GetDoubleRegister(unsigned n) const
Definition: deoptimizer.h:518
static const int kMaxNumRegisters

References v8::internal::FrameDescription::GetDoubleRegister(), input_, v8::internal::DwVfpRegister::kMaxNumRegisters, and v8::internal::FrameDescription::SetDoubleRegister().

Referenced by DoComputeCompiledStubFrame().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DebuggerInspectableFrame()

DeoptimizedFrameInfo * v8::internal::Deoptimizer::DebuggerInspectableFrame ( JavaScriptFrame frame,
int  jsframe_index,
Isolate isolate 
)
static

Definition at line 136 of file deoptimizer.cc.

139  {
140  CHECK(frame->is_optimized());
142 
143  // Get the function and code from the frame.
144  JSFunction* function = frame->function();
145  Code* code = frame->LookupCode();
146 
147  // Locate the deoptimization point in the code. As we are at a call the
148  // return address must be at a place in the code with deoptimization support.
149  SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc());
150  int deoptimization_index = safepoint_entry.deoptimization_index();
151  CHECK_NE(deoptimization_index, Safepoint::kNoDeoptimizationIndex);
152 
153  // Always use the actual stack slots when calculating the fp to sp
154  // delta adding two for the function and context.
155  unsigned stack_slots = code->stack_slots();
156  unsigned fp_to_sp_delta = (stack_slots * kPointerSize) +
158 
159  Deoptimizer* deoptimizer = new Deoptimizer(isolate,
160  function,
162  deoptimization_index,
163  frame->pc(),
164  fp_to_sp_delta,
165  code);
166  Address tos = frame->fp() - fp_to_sp_delta;
167  deoptimizer->FillInputFrame(tos, frame);
168 
169  // Calculate the output frames.
171 
172  // Create the GC safe output frame information and register it for GC
173  // handling.
174  CHECK_LT(jsframe_index, deoptimizer->jsframe_count());
175 
176  // Convert JS frame index into frame index.
177  int frame_index = deoptimizer->ConvertJSFrameIndexToFrameIndex(jsframe_index);
178 
179  bool has_arguments_adaptor =
180  frame_index > 0 &&
181  deoptimizer->output_[frame_index - 1]->GetFrameType() ==
183 
184  int construct_offset = has_arguments_adaptor ? 2 : 1;
185  bool has_construct_stub =
186  frame_index >= construct_offset &&
187  deoptimizer->output_[frame_index - construct_offset]->GetFrameType() ==
188  StackFrame::CONSTRUCT;
189 
190  DeoptimizedFrameInfo* info = new DeoptimizedFrameInfo(deoptimizer,
191  frame_index,
192  has_arguments_adaptor,
193  has_construct_stub);
195 
196  // Get the "simulated" top and size for the requested frame.
197  FrameDescription* parameters_frame =
198  deoptimizer->output_[
199  has_arguments_adaptor ? (frame_index - 1) : frame_index];
200 
201  uint32_t parameters_size = (info->parameters_count() + 1) * kPointerSize;
202  Address parameters_top = reinterpret_cast<Address>(
203  parameters_frame->GetTop() + (parameters_frame->GetFrameSize() -
204  parameters_size));
205 
206  uint32_t expressions_size = info->expression_count() * kPointerSize;
207  Address expressions_top = reinterpret_cast<Address>(
208  deoptimizer->output_[frame_index]->GetTop());
209 
210  // Done with the GC-unsafe frame descriptions. This re-enables allocation.
211  deoptimizer->DeleteFrameDescriptions();
212 
213  // Allocate a heap number for the doubles belonging to this frame.
214  deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame(
215  parameters_top, parameters_size, expressions_top, expressions_size, info);
216 
217  // Finished using the deoptimizer instance.
218  delete deoptimizer;
219 
220  return info;
221 }
DeoptimizedFrameInfo * deoptimized_frame_info_
Definition: deoptimizer.h:646
static void ComputeOutputFrames(Deoptimizer *deoptimizer)
Definition: deoptimizer.cc:515
Deoptimizer(Isolate *isolate, JSFunction *function, BailoutType type, unsigned bailout_id, Address from, int fp_to_sp_delta, Code *optimized_code)
Definition: deoptimizer.cc:548
friend class DeoptimizedFrameInfo
Definition: deoptimizer.h:454
DeoptimizerData * deoptimizer_data()
Definition: isolate.h:877
#define CHECK_LT(a, b)
Definition: logging.h:179
#define CHECK_NE(unexpected, value)
Definition: logging.h:173

References v8::internal::compiler::ARGUMENTS_ADAPTOR, CHECK, CHECK_LT, CHECK_NE, ComputeOutputFrames(), ConvertJSFrameIndexToFrameIndex(), DEBUGGER, DeleteFrameDescriptions(), v8::internal::DeoptimizerData::deoptimized_frame_info_, DeoptimizedFrameInfo, Deoptimizer(), v8::internal::Isolate::deoptimizer_data(), v8::internal::DeoptimizedFrameInfo::expression_count(), FillInputFrame(), v8::internal::JavaScriptFrame::function(), v8::internal::FrameDescription::GetFrameSize(), v8::internal::FrameDescription::GetFrameType(), v8::internal::Code::GetSafepointEntry(), v8::internal::FrameDescription::GetTop(), isolate(), jsframe_count(), v8::internal::StandardFrameConstants::kFixedFrameSizeFromFp, v8::internal::kPointerSize, MaterializeHeapNumbersForDebuggerInspectableFrame(), NULL, output_, v8::internal::DeoptimizedFrameInfo::parameters_count(), and v8::internal::Code::stack_slots().

Referenced by v8::internal::FrameInspector::FrameInspector().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DeleteDebuggerInspectableFrame()

void v8::internal::Deoptimizer::DeleteDebuggerInspectableFrame ( DeoptimizedFrameInfo info,
Isolate isolate 
)
static

Definition at line 224 of file deoptimizer.cc.

225  {
227  delete info;
229 }

References CHECK_EQ, v8::internal::DeoptimizerData::deoptimized_frame_info_, v8::internal::Isolate::deoptimizer_data(), isolate(), and NULL.

Referenced by v8::internal::FrameInspector::~FrameInspector().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DeleteFrameDescriptions()

void v8::internal::Deoptimizer::DeleteFrameDescriptions ( )
private

Definition at line 655 of file deoptimizer.cc.

655  {
656  delete input_;
657  for (int i = 0; i < output_count_; ++i) {
658  if (output_[i] != input_) delete output_[i];
659  }
660  delete[] output_;
661  input_ = NULL;
662  output_ = NULL;
663 #ifdef DEBUG
664  CHECK(!AllowHeapAllocation::IsAllowed());
665  CHECK(disallow_heap_allocation_ != NULL);
666  delete disallow_heap_allocation_;
667  disallow_heap_allocation_ = NULL;
668 #endif // DEBUG
669 }

References CHECK, input_, NULL, output_, and output_count_.

Referenced by DebuggerInspectableFrame(), and Grab().

+ Here is the caller graph for this function:

◆ DeoptimizeAll()

void v8::internal::Deoptimizer::DeoptimizeAll ( Isolate isolate)
static

Definition at line 437 of file deoptimizer.cc.

437  {
438  if (FLAG_trace_deopt) {
439  CodeTracer::Scope scope(isolate->GetCodeTracer());
440  PrintF(scope.file(), "[deoptimize all code in all contexts]\n");
441  }
442  DisallowHeapAllocation no_allocation;
443  // For all contexts, mark all code, then deoptimize.
444  Object* context = isolate->heap()->native_contexts_list();
445  while (!context->IsUndefined()) {
446  Context* native_context = Context::cast(context);
447  MarkAllCodeForContext(native_context);
448  DeoptimizeMarkedCodeForContext(native_context);
449  context = native_context->get(Context::NEXT_CONTEXT_LINK);
450  }
451 }
static Context * cast(Object *context)
Definition: contexts.h:255
static void MarkAllCodeForContext(Context *native_context)
Definition: deoptimizer.cc:492
static void DeoptimizeMarkedCodeForContext(Context *native_context)
Definition: deoptimizer.cc:301
Object * native_contexts_list() const
Definition: heap.h:793
void PrintF(const char *format,...)
Definition: utils.cc:80

References v8::internal::Context::cast(), DeoptimizeMarkedCodeForContext(), v8::internal::FixedArray::get(), v8::internal::Isolate::GetCodeTracer(), v8::internal::Isolate::heap(), isolate(), MarkAllCodeForContext(), v8::internal::Heap::native_contexts_list(), v8::internal::Context::NEXT_CONTEXT_LINK, and v8::internal::PrintF().

Referenced by v8::Testing::DeoptimizeAll(), v8::Object::ForceDelete(), v8::internal::Heap::GarbageCollectionEpilogue(), and v8::internal::Debug::PrepareForBreakPoints().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DeoptimizeFunction()

void v8::internal::Deoptimizer::DeoptimizeFunction ( JSFunction function)
static

Definition at line 503 of file deoptimizer.cc.

503  {
504  Code* code = function->code();
505  if (code->kind() == Code::OPTIMIZED_FUNCTION) {
506  // Mark the code for deoptimization and unlink any functions that also
507  // refer to that code. The code cannot be shared across native contexts,
508  // so we only need to search one.
509  code->set_marked_for_deoptimization(true);
510  DeoptimizeMarkedCodeForContext(function->context()->native_context());
511  }
512 }

References DeoptimizeMarkedCodeForContext(), function(), v8::internal::Code::kind(), and v8::internal::Code::set_marked_for_deoptimization().

Referenced by v8::internal::RUNTIME_FUNCTION().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DeoptimizeGlobalObject()

void v8::internal::Deoptimizer::DeoptimizeGlobalObject ( JSObject object)
static

Definition at line 470 of file deoptimizer.cc.

470  {
471  if (FLAG_trace_deopt) {
472  CodeTracer::Scope scope(object->GetHeap()->isolate()->GetCodeTracer());
473  PrintF(scope.file(), "[deoptimize global object @ 0x%08" V8PRIxPTR "]\n",
474  reinterpret_cast<intptr_t>(object));
475  }
476  if (object->IsJSGlobalProxy()) {
477  PrototypeIterator iter(object->GetIsolate(), object);
478  // TODO(verwaest): This CHECK will be hit if the global proxy is detached.
479  CHECK(iter.GetCurrent()->IsJSGlobalObject());
480  Context* native_context =
481  GlobalObject::cast(iter.GetCurrent())->native_context();
482  MarkAllCodeForContext(native_context);
483  DeoptimizeMarkedCodeForContext(native_context);
484  } else if (object->IsGlobalObject()) {
485  Context* native_context = GlobalObject::cast(object)->native_context();
486  MarkAllCodeForContext(native_context);
487  DeoptimizeMarkedCodeForContext(native_context);
488  }
489 }
#define V8PRIxPTR
Definition: macros.h:363

References CHECK, DeoptimizeMarkedCodeForContext(), v8::internal::Isolate::GetCodeTracer(), v8::internal::PrototypeIterator::GetCurrent(), v8::internal::HeapObject::GetHeap(), v8::internal::HeapObject::GetIsolate(), v8::internal::Heap::isolate(), MarkAllCodeForContext(), v8::internal::Context::native_context(), v8::internal::PrintF(), and V8PRIxPTR.

Referenced by v8::internal::JSObject::SetPropertyCallback(), and v8::Object::TurnOnAccessCheck().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DeoptimizeMarkedCode()

void v8::internal::Deoptimizer::DeoptimizeMarkedCode ( Isolate isolate)
static

Definition at line 454 of file deoptimizer.cc.

454  {
455  if (FLAG_trace_deopt) {
456  CodeTracer::Scope scope(isolate->GetCodeTracer());
457  PrintF(scope.file(), "[deoptimize marked code in all contexts]\n");
458  }
459  DisallowHeapAllocation no_allocation;
460  // For all contexts, deoptimize code already marked.
461  Object* context = isolate->heap()->native_contexts_list();
462  while (!context->IsUndefined()) {
463  Context* native_context = Context::cast(context);
464  DeoptimizeMarkedCodeForContext(native_context);
465  context = native_context->get(Context::NEXT_CONTEXT_LINK);
466  }
467 }

References v8::internal::Context::cast(), DeoptimizeMarkedCodeForContext(), v8::internal::FixedArray::get(), v8::internal::Isolate::GetCodeTracer(), v8::internal::Isolate::heap(), isolate(), v8::internal::Heap::native_contexts_list(), v8::internal::Context::NEXT_CONTEXT_LINK, and v8::internal::PrintF().

Referenced by v8::internal::DependentCode::DeoptimizeDependentCodeGroup(), v8::internal::DeoptimizeDependentFunctions(), v8::internal::Heap::DeoptMarkedAllocationSites(), and v8::internal::MarkCompactCollector::Finish().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DeoptimizeMarkedCodeForContext()

void v8::internal::Deoptimizer::DeoptimizeMarkedCodeForContext ( Context native_context)
staticprivate

Definition at line 301 of file deoptimizer.cc.

301  {
302  DisallowHeapAllocation no_allocation;
303 
304  // A "closure" that unlinks optimized code that is going to be
305  // deoptimized from the functions that refer to it.
306  class SelectedCodeUnlinker: public OptimizedFunctionVisitor {
307  public:
308  virtual void EnterContext(Context* context) { } // Don't care.
309  virtual void LeaveContext(Context* context) { } // Don't care.
310  virtual void VisitFunction(JSFunction* function) {
311  Code* code = function->code();
312  if (!code->marked_for_deoptimization()) return;
313 
314  // Unlink this function and evict from optimized code map.
315  SharedFunctionInfo* shared = function->shared();
316  function->set_code(shared->code());
317 
318  if (FLAG_trace_deopt) {
319  CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
320  PrintF(scope.file(), "[deoptimizer unlinked: ");
321  function->PrintName(scope.file());
322  PrintF(scope.file(),
323  " / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function));
324  }
325  }
326  };
327 
328  // Unlink all functions that refer to marked code.
329  SelectedCodeUnlinker unlinker;
330  VisitAllOptimizedFunctionsForContext(context, &unlinker);
331 
332  Isolate* isolate = context->GetHeap()->isolate();
333 #ifdef DEBUG
334  Code* topmost_optimized_code = NULL;
335  bool safe_to_deopt_topmost_optimized_code = false;
336  // Make sure all activations of optimized code can deopt at their current PC.
337  // The topmost optimized code has special handling because it cannot be
338  // deoptimized due to weak object dependency.
339  for (StackFrameIterator it(isolate, isolate->thread_local_top());
340  !it.done(); it.Advance()) {
341  StackFrame::Type type = it.frame()->type();
342  if (type == StackFrame::OPTIMIZED) {
343  Code* code = it.frame()->LookupCode();
344  if (FLAG_trace_deopt) {
345  JSFunction* function =
346  static_cast<OptimizedFrame*>(it.frame())->function();
347  CodeTracer::Scope scope(isolate->GetCodeTracer());
348  PrintF(scope.file(), "[deoptimizer found activation of function: ");
349  function->PrintName(scope.file());
350  PrintF(scope.file(),
351  " / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function));
352  }
353  SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc());
354  int deopt_index = safepoint.deoptimization_index();
355  // Turbofan deopt is checked when we are patching addresses on stack.
356  bool turbofanned = code->is_turbofanned() && !FLAG_turbo_deoptimization;
357  bool safe_to_deopt =
358  deopt_index != Safepoint::kNoDeoptimizationIndex || turbofanned;
359  CHECK(topmost_optimized_code == NULL || safe_to_deopt || turbofanned);
360  if (topmost_optimized_code == NULL) {
361  topmost_optimized_code = code;
362  safe_to_deopt_topmost_optimized_code = safe_to_deopt;
363  }
364  }
365  }
366 #endif
367 
368  // Move marked code from the optimized code list to the deoptimized
369  // code list, collecting them into a ZoneList.
370  Zone zone(isolate);
371  ZoneList<Code*> codes(10, &zone);
372 
373  // Walk over all optimized code objects in this native context.
374  Code* prev = NULL;
375  Object* element = context->OptimizedCodeListHead();
376  while (!element->IsUndefined()) {
377  Code* code = Code::cast(element);
378  CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
379  Object* next = code->next_code_link();
380 
381  if (code->marked_for_deoptimization() &&
382  (!code->is_turbofanned() || FLAG_turbo_deoptimization)) {
383  // Put the code into the list for later patching.
384  codes.Add(code, &zone);
385 
386  if (prev != NULL) {
387  // Skip this code in the optimized code list.
388  prev->set_next_code_link(next);
389  } else {
390  // There was no previous node, the next node is the new head.
391  context->SetOptimizedCodeListHead(next);
392  }
393 
394  // Move the code to the _deoptimized_ code list.
395  code->set_next_code_link(context->DeoptimizedCodeListHead());
396  context->SetDeoptimizedCodeListHead(code);
397  } else {
398  // Not marked; preserve this element.
399  prev = code;
400  }
401  element = next;
402  }
403 
404  // TODO(titzer): we need a handle scope only because of the macro assembler,
405  // which is only used in EnsureCodeForDeoptimizationEntry.
406  HandleScope scope(isolate);
407 
408  // Now patch all the codes for deoptimization.
409  for (int i = 0; i < codes.length(); i++) {
410 #ifdef DEBUG
411  if (codes[i] == topmost_optimized_code) {
412  DCHECK(safe_to_deopt_topmost_optimized_code);
413  }
414 #endif
415  // It is finally time to die, code object.
416 
417  // Remove the code from optimized code map.
418  DeoptimizationInputData* deopt_data =
419  DeoptimizationInputData::cast(codes[i]->deoptimization_data());
420  SharedFunctionInfo* shared =
421  SharedFunctionInfo::cast(deopt_data->SharedFunctionInfo());
422  shared->EvictFromOptimizedCodeMap(codes[i], "deoptimized code");
423 
424  // Do platform-specific patching to force any activations to lazy deopt.
425  if (!codes[i]->is_turbofanned() || FLAG_turbo_deoptimization) {
427 
428  // We might be in the middle of incremental marking with compaction.
429  // Tell collector to treat this code object in a special way and
430  // ignore all slots that might have been recorded on it.
432  }
433  }
434 }
static void PatchCodeForDeoptimization(Isolate *isolate, Code *code)
static void VisitAllOptimizedFunctionsForContext(Context *context, OptimizedFunctionVisitor *visitor)
Definition: deoptimizer.cc:240
MarkCompactCollector * mark_compact_collector()
Definition: heap.h:1197
ThreadLocalTop * thread_local_top()
Definition: isolate.h:878

References v8::internal::List< T, AllocationPolicy >::Add(), v8::internal::StackFrameIterator::Advance(), CHECK, CHECK_EQ, DCHECK, v8::internal::Context::DeoptimizedCodeListHead(), v8::internal::SharedFunctionInfo::EvictFromOptimizedCodeMap(), v8::internal::Isolate::GetCodeTracer(), v8::internal::HeapObject::GetHeap(), v8::internal::Code::GetSafepointEntry(), v8::internal::Isolate::heap(), v8::internal::MarkCompactCollector::InvalidateCode(), v8::internal::Code::is_turbofanned(), v8::internal::Heap::isolate(), isolate(), v8::internal::Code::kind(), v8::internal::Heap::mark_compact_collector(), v8::internal::Code::marked_for_deoptimization(), NULL, v8::internal::Context::OptimizedCodeListHead(), PatchCodeForDeoptimization(), v8::internal::PrintF(), v8::internal::Context::SetDeoptimizedCodeListHead(), v8::internal::Context::SetOptimizedCodeListHead(), v8::internal::Isolate::thread_local_top(), V8PRIxPTR, and VisitAllOptimizedFunctionsForContext().

Referenced by DeoptimizeAll(), DeoptimizeFunction(), DeoptimizeGlobalObject(), and DeoptimizeMarkedCode().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DoComputeAccessorStubFrame()

void v8::internal::Deoptimizer::DoComputeAccessorStubFrame ( TranslationIterator *  iterator,
int  frame_index,
bool  is_setter_stub_frame 
)
private

Definition at line 1405 of file deoptimizer.cc.

1407  {
1408  JSFunction* accessor = JSFunction::cast(ComputeLiteral(iterator->Next()));
1409  // The receiver (and the implicit return value, if any) are expected in
1410  // registers by the LoadIC/StoreIC, so they don't belong to the output stack
1411  // frame. This means that we have to use a height of 0.
1412  unsigned height = 0;
1413  unsigned height_in_bytes = height * kPointerSize;
1414  const char* kind = is_setter_stub_frame ? "setter" : "getter";
1415  if (trace_scope_ != NULL) {
1416  PrintF(trace_scope_->file(),
1417  " translating %s stub => height=%u\n", kind, height_in_bytes);
1418  }
1419 
1420  // We need 1 stack entry for the return address and enough entries for the
1421  // StackFrame::INTERNAL (FP, context, frame type, code object and constant
1422  // pool (if FLAG_enable_ool_constant_pool)- see MacroAssembler::EnterFrame).
1423  // For a setter stub frame we need one additional entry for the implicit
1424  // return value, see StoreStubCompiler::CompileStoreViaSetter.
1425  unsigned fixed_frame_entries =
1427  (is_setter_stub_frame ? 1 : 0);
1428  unsigned fixed_frame_size = fixed_frame_entries * kPointerSize;
1429  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1430 
1431  // Allocate and store the output frame description.
1432  FrameDescription* output_frame =
1433  new(output_frame_size) FrameDescription(output_frame_size, accessor);
1434  output_frame->SetFrameType(StackFrame::INTERNAL);
1435 
1436  // A frame for an accessor stub can not be the topmost or bottommost one.
1437  CHECK(frame_index > 0 && frame_index < output_count_ - 1);
1438  CHECK_EQ(output_[frame_index], NULL);
1439  output_[frame_index] = output_frame;
1440 
1441  // The top address of the frame is computed from the previous frame's top and
1442  // this frame's size.
1443  intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1444  output_frame->SetTop(top_address);
1445 
1446  unsigned output_offset = output_frame_size;
1447 
1448  // Read caller's PC from the previous frame.
1450  intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1451  output_frame->SetCallerPc(output_offset, callers_pc);
1452  if (trace_scope_ != NULL) {
1453  PrintF(trace_scope_->file(),
1454  " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
1455  " ; caller's pc\n",
1456  top_address + output_offset, output_offset, callers_pc);
1457  }
1458 
1459  // Read caller's FP from the previous frame, and set this frame's FP.
1461  intptr_t value = output_[frame_index - 1]->GetFp();
1462  output_frame->SetCallerFp(output_offset, value);
1463  intptr_t fp_value = top_address + output_offset;
1464  output_frame->SetFp(fp_value);
1465  if (trace_scope_ != NULL) {
1466  PrintF(trace_scope_->file(),
1467  " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
1468  " ; caller's fp\n",
1469  fp_value, output_offset, value);
1470  }
1471 
1472  if (FLAG_enable_ool_constant_pool) {
1473  // Read the caller's constant pool from the previous frame.
1475  value = output_[frame_index - 1]->GetConstantPool();
1476  output_frame->SetCallerConstantPool(output_offset, value);
1477  if (trace_scope_) {
1478  PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1479  V8PRIxPTR " ; caller's constant pool\n",
1480  top_address + output_offset, output_offset, value);
1481  }
1482  }
1483 
1484  // The context can be gotten from the previous frame.
1486  value = output_[frame_index - 1]->GetContext();
1487  output_frame->SetFrameSlot(output_offset, value);
1488  if (trace_scope_ != NULL) {
1489  PrintF(trace_scope_->file(),
1490  " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
1491  " ; context\n",
1492  top_address + output_offset, output_offset, value);
1493  }
1494 
1495  // A marker value is used in place of the function.
1497  value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::INTERNAL));
1498  output_frame->SetFrameSlot(output_offset, value);
1499  if (trace_scope_ != NULL) {
1500  PrintF(trace_scope_->file(),
1501  " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
1502  " ; function (%s sentinel)\n",
1503  top_address + output_offset, output_offset, value, kind);
1504  }
1505 
1506  // Get Code object from accessor stub.
1508  Builtins::Name name = is_setter_stub_frame ?
1509  Builtins::kStoreIC_Setter_ForDeopt :
1510  Builtins::kLoadIC_Getter_ForDeopt;
1511  Code* accessor_stub = isolate_->builtins()->builtin(name);
1512  value = reinterpret_cast<intptr_t>(accessor_stub);
1513  output_frame->SetFrameSlot(output_offset, value);
1514  if (trace_scope_ != NULL) {
1515  PrintF(trace_scope_->file(),
1516  " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
1517  " ; code object\n",
1518  top_address + output_offset, output_offset, value);
1519  }
1520 
1521  // Skip receiver.
1522  DoTranslateObjectAndSkip(iterator);
1523 
1524  if (is_setter_stub_frame) {
1525  // The implicit return value was part of the artificial setter stub
1526  // environment.
1528  DoTranslateCommand(iterator, frame_index, output_offset);
1529  }
1530 
1531  CHECK_EQ(output_offset, 0);
1532 
1533  Smi* offset = is_setter_stub_frame ?
1534  isolate_->heap()->setter_stub_deopt_pc_offset() :
1535  isolate_->heap()->getter_stub_deopt_pc_offset();
1536  intptr_t pc = reinterpret_cast<intptr_t>(
1537  accessor_stub->instruction_start() + offset->value());
1538  output_frame->SetPc(pc);
1539  if (FLAG_enable_ool_constant_pool) {
1540  intptr_t constant_pool_value =
1541  reinterpret_cast<intptr_t>(accessor_stub->constant_pool());
1542  output_frame->SetConstantPool(constant_pool_value);
1543  }
1544 }
Code * builtin(Name name)
Definition: builtins.h:254
static int output_offset()
Definition: deoptimizer.h:239
Object * ComputeLiteral(int index) const
void DoTranslateCommand(TranslationIterator *iterator, int frame_index, unsigned output_offset)
void DoTranslateObjectAndSkip(TranslationIterator *iterator)
intptr_t GetConstantPool() const
Definition: deoptimizer.h:545
Builtins * builtins()
Definition: isolate.h:947
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
const int kPCOnStackSize
Definition: globals.h:135
const Register pc
const int kFPOnStackSize
Definition: globals.h:136

References v8::internal::Builtins::builtin(), v8::internal::Isolate::builtins(), CHECK, CHECK_EQ, ComputeLiteral(), v8::internal::Code::constant_pool(), DoTranslateCommand(), DoTranslateObjectAndSkip(), FrameDescription, v8::internal::Smi::FromInt(), v8::internal::FrameDescription::GetConstantPool(), v8::internal::FrameDescription::GetContext(), v8::internal::FrameDescription::GetFp(), v8::internal::FrameDescription::GetPc(), v8::internal::FrameDescription::GetTop(), v8::internal::Isolate::heap(), v8::internal::Code::instruction_start(), v8::internal::INTERNAL, isolate_, v8::internal::StandardFrameConstants::kFixedFrameSize, v8::internal::kFPOnStackSize, v8::internal::kPCOnStackSize, v8::internal::kPointerSize, name, NULL, output_, output_count_, output_offset(), v8::internal::pc, v8::internal::PrintF(), v8::internal::FrameDescription::SetCallerConstantPool(), v8::internal::FrameDescription::SetCallerFp(), v8::internal::FrameDescription::SetCallerPc(), v8::internal::FrameDescription::SetConstantPool(), v8::internal::FrameDescription::SetFp(), v8::internal::FrameDescription::SetFrameSlot(), v8::internal::FrameDescription::SetFrameType(), v8::internal::FrameDescription::SetPc(), v8::internal::FrameDescription::SetTop(), trace_scope_, V8PRIxPTR, and v8::internal::Smi::value().

Referenced by DoComputeOutputFrames().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DoComputeArgumentsAdaptorFrame()

void v8::internal::Deoptimizer::DoComputeArgumentsAdaptorFrame ( TranslationIterator *  iterator,
int  frame_index 
)
private

Definition at line 1114 of file deoptimizer.cc.

1115  {
1116  JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
1117  unsigned height = iterator->Next();
1118  unsigned height_in_bytes = height * kPointerSize;
1119  if (trace_scope_ != NULL) {
1120  PrintF(trace_scope_->file(),
1121  " translating arguments adaptor => height=%d\n", height_in_bytes);
1122  }
1123 
1124  unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
1125  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1126 
1127  // Allocate and store the output frame description.
1128  FrameDescription* output_frame =
1129  new(output_frame_size) FrameDescription(output_frame_size, function);
1130  output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR);
1131 
1132  // Arguments adaptor can not be topmost or bottommost.
1133  CHECK(frame_index > 0 && frame_index < output_count_ - 1);
1134  CHECK(output_[frame_index] == NULL);
1135  output_[frame_index] = output_frame;
1136 
1137  // The top address of the frame is computed from the previous
1138  // frame's top and this frame's size.
1139  intptr_t top_address;
1140  top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1141  output_frame->SetTop(top_address);
1142 
1143  // Compute the incoming parameter translation.
1144  int parameter_count = height;
1145  unsigned output_offset = output_frame_size;
1146  for (int i = 0; i < parameter_count; ++i) {
1148  DoTranslateCommand(iterator, frame_index, output_offset);
1149  }
1150 
1151  // Read caller's PC from the previous frame.
1153  intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1154  output_frame->SetCallerPc(output_offset, callers_pc);
1155  if (trace_scope_ != NULL) {
1156  PrintF(trace_scope_->file(),
1157  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1158  V8PRIxPTR " ; caller's pc\n",
1159  top_address + output_offset, output_offset, callers_pc);
1160  }
1161 
1162  // Read caller's FP from the previous frame, and set this frame's FP.
1164  intptr_t value = output_[frame_index - 1]->GetFp();
1165  output_frame->SetCallerFp(output_offset, value);
1166  intptr_t fp_value = top_address + output_offset;
1167  output_frame->SetFp(fp_value);
1168  if (trace_scope_ != NULL) {
1169  PrintF(trace_scope_->file(),
1170  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1171  V8PRIxPTR " ; caller's fp\n",
1172  fp_value, output_offset, value);
1173  }
1174 
1175  if (FLAG_enable_ool_constant_pool) {
1176  // Read the caller's constant pool from the previous frame.
1178  value = output_[frame_index - 1]->GetConstantPool();
1179  output_frame->SetCallerConstantPool(output_offset, value);
1180  if (trace_scope_) {
1181  PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1182  V8PRIxPTR "; caller's constant_pool\n",
1183  top_address + output_offset, output_offset, value);
1184  }
1185  }
1186 
1187  // A marker value is used in place of the context.
1189  intptr_t context = reinterpret_cast<intptr_t>(
1191  output_frame->SetFrameSlot(output_offset, context);
1192  if (trace_scope_ != NULL) {
1193  PrintF(trace_scope_->file(),
1194  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1195  V8PRIxPTR " ; context (adaptor sentinel)\n",
1196  top_address + output_offset, output_offset, context);
1197  }
1198 
1199  // The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
1201  value = reinterpret_cast<intptr_t>(function);
1202  output_frame->SetFrameSlot(output_offset, value);
1203  if (trace_scope_ != NULL) {
1204  PrintF(trace_scope_->file(),
1205  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1206  V8PRIxPTR " ; function\n",
1207  top_address + output_offset, output_offset, value);
1208  }
1209 
1210  // Number of incoming arguments.
1212  value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
1213  output_frame->SetFrameSlot(output_offset, value);
1214  if (trace_scope_ != NULL) {
1215  PrintF(trace_scope_->file(),
1216  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1217  V8PRIxPTR " ; argc (%d)\n",
1218  top_address + output_offset, output_offset, value, height - 1);
1219  }
1220 
1221  DCHECK(0 == output_offset);
1222 
1223  Builtins* builtins = isolate_->builtins();
1224  Code* adaptor_trampoline =
1225  builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
1226  intptr_t pc_value = reinterpret_cast<intptr_t>(
1227  adaptor_trampoline->instruction_start() +
1228  isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
1229  output_frame->SetPc(pc_value);
1230  if (FLAG_enable_ool_constant_pool) {
1231  intptr_t constant_pool_value =
1232  reinterpret_cast<intptr_t>(adaptor_trampoline->constant_pool());
1233  output_frame->SetConstantPool(constant_pool_value);
1234  }
1235 }

References v8::internal::compiler::ARGUMENTS_ADAPTOR, v8::internal::Builtins::builtin(), v8::internal::Isolate::builtins(), CHECK, ComputeLiteral(), v8::internal::Code::constant_pool(), DCHECK, DoTranslateCommand(), FrameDescription, v8::internal::Smi::FromInt(), v8::internal::FrameDescription::GetConstantPool(), v8::internal::FrameDescription::GetFp(), v8::internal::FrameDescription::GetPc(), v8::internal::FrameDescription::GetTop(), v8::internal::Isolate::heap(), v8::internal::Code::instruction_start(), isolate_, v8::internal::kFPOnStackSize, v8::internal::ArgumentsAdaptorFrameConstants::kFrameSize, v8::internal::kPCOnStackSize, v8::internal::kPointerSize, NULL, output_, output_count_, output_offset(), v8::internal::PrintF(), v8::internal::FrameDescription::SetCallerConstantPool(), v8::internal::FrameDescription::SetCallerFp(), v8::internal::FrameDescription::SetCallerPc(), v8::internal::FrameDescription::SetConstantPool(), v8::internal::FrameDescription::SetFp(), v8::internal::FrameDescription::SetFrameSlot(), v8::internal::FrameDescription::SetFrameType(), v8::internal::FrameDescription::SetPc(), v8::internal::FrameDescription::SetTop(), trace_scope_, and V8PRIxPTR.

Referenced by DoComputeOutputFrames().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DoComputeCompiledStubFrame()

void v8::internal::Deoptimizer::DoComputeCompiledStubFrame ( TranslationIterator *  iterator,
int  frame_index 
)
private

Definition at line 1547 of file deoptimizer.cc.

1548  {
1549  //
1550  // FROM TO
1551  // | .... | | .... |
1552  // +-------------------------+ +-------------------------+
1553  // | JSFunction continuation | | JSFunction continuation |
1554  // +-------------------------+ +-------------------------+
1555  // | | saved frame (FP) | | saved frame (FP) |
1556  // | +=========================+<-fpreg +=========================+<-fpreg
1557  // | |constant pool (if ool_cp)| |constant pool (if ool_cp)|
1558  // | +-------------------------+ +-------------------------|
1559  // | | JSFunction context | | JSFunction context |
1560  // v +-------------------------+ +-------------------------|
1561  // | COMPILED_STUB marker | | STUB_FAILURE marker |
1562  // +-------------------------+ +-------------------------+
1563  // | | | caller args.arguments_ |
1564  // | ... | +-------------------------+
1565  // | | | caller args.length_ |
1566  // |-------------------------|<-spreg +-------------------------+
1567  // | caller args pointer |
1568  // +-------------------------+
1569  // | caller stack param 1 |
1570  // parameters in registers +-------------------------+
1571  // and spilled to stack | .... |
1572  // +-------------------------+
1573  // | caller stack param n |
1574  // +-------------------------+<-spreg
1575  // reg = number of parameters
1576  // reg = failure handler address
1577  // reg = saved frame
1578  // reg = JSFunction context
1579  //
1580 
1582  int major_key = CodeStub::GetMajorKey(compiled_code_);
1583  CodeStubDescriptor descriptor(isolate_, compiled_code_->stub_key());
1584 
1585  // The output frame must have room for all pushed register parameters
1586  // and the standard stack frame slots. Include space for an argument
1587  // object to the callee and optionally the space to pass the argument
1588  // object to the stub failure handler.
1589  int param_count = descriptor.GetEnvironmentParameterCount();
1590  CHECK_GE(param_count, 0);
1591 
1592  int height_in_bytes = kPointerSize * param_count + sizeof(Arguments) +
1593  kPointerSize;
1594  int fixed_frame_size = StandardFrameConstants::kFixedFrameSize;
1595  int input_frame_size = input_->GetFrameSize();
1596  int output_frame_size = height_in_bytes + fixed_frame_size;
1597  if (trace_scope_ != NULL) {
1598  PrintF(trace_scope_->file(),
1599  " translating %s => StubFailureTrampolineStub, height=%d\n",
1600  CodeStub::MajorName(static_cast<CodeStub::Major>(major_key), false),
1601  height_in_bytes);
1602  }
1603 
1604  // The stub failure trampoline is a single frame.
1605  FrameDescription* output_frame =
1606  new(output_frame_size) FrameDescription(output_frame_size, NULL);
1607  output_frame->SetFrameType(StackFrame::STUB_FAILURE_TRAMPOLINE);
1608  CHECK_EQ(frame_index, 0);
1609  output_[frame_index] = output_frame;
1610 
1611  // The top address for the output frame can be computed from the input
1612  // frame pointer and the output frame's height. Subtract space for the
1613  // context and function slots.
1614  Register fp_reg = StubFailureTrampolineFrame::fp_register();
1615  intptr_t top_address = input_->GetRegister(fp_reg.code()) -
1617  output_frame->SetTop(top_address);
1618 
1619  // Read caller's PC (JSFunction continuation) from the input frame.
1620  unsigned input_frame_offset = input_frame_size - kPCOnStackSize;
1621  unsigned output_frame_offset = output_frame_size - kFPOnStackSize;
1622  intptr_t value = input_->GetFrameSlot(input_frame_offset);
1623  output_frame->SetCallerPc(output_frame_offset, value);
1624  if (trace_scope_ != NULL) {
1625  PrintF(trace_scope_->file(),
1626  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1627  V8PRIxPTR " ; caller's pc\n",
1628  top_address + output_frame_offset, output_frame_offset, value);
1629  }
1630 
1631  // Read caller's FP from the input frame, and set this frame's FP.
1632  input_frame_offset -= kFPOnStackSize;
1633  value = input_->GetFrameSlot(input_frame_offset);
1634  output_frame_offset -= kFPOnStackSize;
1635  output_frame->SetCallerFp(output_frame_offset, value);
1636  intptr_t frame_ptr = input_->GetRegister(fp_reg.code());
1637  output_frame->SetRegister(fp_reg.code(), frame_ptr);
1638  output_frame->SetFp(frame_ptr);
1639  if (trace_scope_ != NULL) {
1640  PrintF(trace_scope_->file(),
1641  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1642  V8PRIxPTR " ; caller's fp\n",
1643  top_address + output_frame_offset, output_frame_offset, value);
1644  }
1645 
1646  if (FLAG_enable_ool_constant_pool) {
1647  // Read the caller's constant pool from the input frame.
1648  input_frame_offset -= kPointerSize;
1649  value = input_->GetFrameSlot(input_frame_offset);
1650  output_frame_offset -= kPointerSize;
1651  output_frame->SetCallerConstantPool(output_frame_offset, value);
1652  if (trace_scope_) {
1653  PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1654  V8PRIxPTR " ; caller's constant_pool\n",
1655  top_address + output_frame_offset, output_frame_offset, value);
1656  }
1657  }
1658 
1659  // The context can be gotten from the input frame.
1660  Register context_reg = StubFailureTrampolineFrame::context_register();
1661  input_frame_offset -= kPointerSize;
1662  value = input_->GetFrameSlot(input_frame_offset);
1663  output_frame->SetRegister(context_reg.code(), value);
1664  output_frame_offset -= kPointerSize;
1665  output_frame->SetFrameSlot(output_frame_offset, value);
1666  CHECK(reinterpret_cast<Object*>(value)->IsContext());
1667  if (trace_scope_ != NULL) {
1668  PrintF(trace_scope_->file(),
1669  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1670  V8PRIxPTR " ; context\n",
1671  top_address + output_frame_offset, output_frame_offset, value);
1672  }
1673 
1674  // A marker value is used in place of the function.
1675  output_frame_offset -= kPointerSize;
1676  value = reinterpret_cast<intptr_t>(
1677  Smi::FromInt(StackFrame::STUB_FAILURE_TRAMPOLINE));
1678  output_frame->SetFrameSlot(output_frame_offset, value);
1679  if (trace_scope_ != NULL) {
1680  PrintF(trace_scope_->file(),
1681  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1682  V8PRIxPTR " ; function (stub failure sentinel)\n",
1683  top_address + output_frame_offset, output_frame_offset, value);
1684  }
1685 
1686  intptr_t caller_arg_count = 0;
1687  bool arg_count_known = !descriptor.stack_parameter_count().is_valid();
1688 
1689  // Build the Arguments object for the caller's parameters and a pointer to it.
1690  output_frame_offset -= kPointerSize;
1691  int args_arguments_offset = output_frame_offset;
1692  intptr_t the_hole = reinterpret_cast<intptr_t>(
1693  isolate_->heap()->the_hole_value());
1694  if (arg_count_known) {
1695  value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
1696  (caller_arg_count - 1) * kPointerSize;
1697  } else {
1698  value = the_hole;
1699  }
1700 
1701  output_frame->SetFrameSlot(args_arguments_offset, value);
1702  if (trace_scope_ != NULL) {
1703  PrintF(trace_scope_->file(),
1704  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1705  V8PRIxPTR " ; args.arguments %s\n",
1706  top_address + args_arguments_offset, args_arguments_offset, value,
1707  arg_count_known ? "" : "(the hole)");
1708  }
1709 
1710  output_frame_offset -= kPointerSize;
1711  int length_frame_offset = output_frame_offset;
1712  value = arg_count_known ? caller_arg_count : the_hole;
1713  output_frame->SetFrameSlot(length_frame_offset, value);
1714  if (trace_scope_ != NULL) {
1715  PrintF(trace_scope_->file(),
1716  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1717  V8PRIxPTR " ; args.length %s\n",
1718  top_address + length_frame_offset, length_frame_offset, value,
1719  arg_count_known ? "" : "(the hole)");
1720  }
1721 
1722  output_frame_offset -= kPointerSize;
1723  value = frame_ptr + StandardFrameConstants::kCallerSPOffset -
1724  (output_frame_size - output_frame_offset) + kPointerSize;
1725  output_frame->SetFrameSlot(output_frame_offset, value);
1726  if (trace_scope_ != NULL) {
1727  PrintF(trace_scope_->file(),
1728  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1729  V8PRIxPTR " ; args*\n",
1730  top_address + output_frame_offset, output_frame_offset, value);
1731  }
1732 
1733  // Copy the register parameters to the failure frame.
1734  int arguments_length_offset = -1;
1735  for (int i = 0; i < param_count; ++i) {
1736  output_frame_offset -= kPointerSize;
1737  DoTranslateCommand(iterator, 0, output_frame_offset);
1738 
1739  if (!arg_count_known && descriptor.IsEnvironmentParameterCountRegister(i)) {
1740  arguments_length_offset = output_frame_offset;
1741  }
1742  }
1743 
1744  CHECK_EQ(output_frame_offset, 0);
1745 
1746  if (!arg_count_known) {
1747  CHECK_GE(arguments_length_offset, 0);
1748  // We know it's a smi because 1) the code stub guarantees the stack
1749  // parameter count is in smi range, and 2) the DoTranslateCommand in the
1750  // parameter loop above translated that to a tagged value.
1751  Smi* smi_caller_arg_count = reinterpret_cast<Smi*>(
1752  output_frame->GetFrameSlot(arguments_length_offset));
1753  caller_arg_count = smi_caller_arg_count->value();
1754  output_frame->SetFrameSlot(length_frame_offset, caller_arg_count);
1755  if (trace_scope_ != NULL) {
1756  PrintF(trace_scope_->file(),
1757  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1758  V8PRIxPTR " ; args.length\n",
1759  top_address + length_frame_offset, length_frame_offset,
1760  caller_arg_count);
1761  }
1762  value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
1763  (caller_arg_count - 1) * kPointerSize;
1764  output_frame->SetFrameSlot(args_arguments_offset, value);
1765  if (trace_scope_ != NULL) {
1766  PrintF(trace_scope_->file(),
1767  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1768  V8PRIxPTR " ; args.arguments\n",
1769  top_address + args_arguments_offset, args_arguments_offset,
1770  value);
1771  }
1772  }
1773 
1774  // Copy the double registers from the input into the output frame.
1775  CopyDoubleRegisters(output_frame);
1776 
1777  // Fill registers containing handler and number of parameters.
1778  SetPlatformCompiledStubRegisters(output_frame, &descriptor);
1779 
1780  // Compute this frame's PC, state, and continuation.
1781  Code* trampoline = NULL;
1782  StubFunctionMode function_mode = descriptor.function_mode();
1783  StubFailureTrampolineStub(isolate_,
1784  function_mode).FindCodeInCache(&trampoline);
1785  DCHECK(trampoline != NULL);
1786  output_frame->SetPc(reinterpret_cast<intptr_t>(
1787  trampoline->instruction_start()));
1788  if (FLAG_enable_ool_constant_pool) {
1789  Register constant_pool_reg =
1791  intptr_t constant_pool_value =
1792  reinterpret_cast<intptr_t>(trampoline->constant_pool());
1793  output_frame->SetConstantPool(constant_pool_value);
1794  output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
1795  }
1796  output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS));
1797  Code* notify_failure =
1798  isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles);
1799  output_frame->SetContinuation(
1800  reinterpret_cast<intptr_t>(notify_failure->entry()));
1801 }
uint32_t stub_key()
Definition: objects-inl.h:6159
void CopyDoubleRegisters(FrameDescription *output_frame)
void SetPlatformCompiledStubRegisters(FrameDescription *output_frame, CodeStubDescriptor *desc)
uint32_t GetFrameSize() const
Definition: deoptimizer.h:477
intptr_t GetFrameSlot(unsigned offset)
Definition: deoptimizer.h:486
intptr_t GetRegister(unsigned n) const
Definition: deoptimizer.h:505
static const int kCallerSPOffset
Definition: frames.h:167
static Register constant_pool_pointer_register()
#define CHECK_GE(a, b)
Definition: logging.h:178

References v8::internal::Builtins::builtin(), v8::internal::Isolate::builtins(), CHECK, CHECK_EQ, CHECK_GE, v8::internal::Register::code(), compiled_code_, v8::internal::Code::constant_pool(), v8::internal::StubFailureTrampolineFrame::constant_pool_pointer_register(), v8::internal::StubFailureTrampolineFrame::context_register(), CopyDoubleRegisters(), DCHECK, DoTranslateCommand(), v8::internal::Code::entry(), v8::internal::StubFailureTrampolineFrame::fp_register(), FrameDescription, v8::internal::Smi::FromInt(), v8::internal::CodeStubDescriptor::function_mode(), v8::internal::CodeStubDescriptor::GetEnvironmentParameterCount(), v8::internal::FrameDescription::GetFrameSize(), v8::internal::FrameDescription::GetFrameSlot(), v8::internal::FrameDescription::GetRegister(), v8::internal::Isolate::heap(), input_, v8::internal::Code::instruction_start(), v8::internal::Code::is_hydrogen_stub(), v8::internal::Register::is_valid(), v8::internal::CodeStubDescriptor::IsEnvironmentParameterCountRegister(), isolate_, v8::internal::StandardFrameConstants::kCallerSPOffset, v8::internal::StandardFrameConstants::kFixedFrameSize, v8::internal::StandardFrameConstants::kFixedFrameSizeFromFp, v8::internal::kFPOnStackSize, v8::internal::kPCOnStackSize, v8::internal::kPointerSize, v8::internal::FullCodeGenerator::NO_REGISTERS, NULL, output_, v8::internal::PrintF(), v8::internal::FrameDescription::SetCallerConstantPool(), v8::internal::FrameDescription::SetCallerFp(), v8::internal::FrameDescription::SetCallerPc(), v8::internal::FrameDescription::SetConstantPool(), v8::internal::FrameDescription::SetContinuation(), v8::internal::FrameDescription::SetFp(), v8::internal::FrameDescription::SetFrameSlot(), v8::internal::FrameDescription::SetFrameType(), v8::internal::FrameDescription::SetPc(), SetPlatformCompiledStubRegisters(), v8::internal::FrameDescription::SetRegister(), v8::internal::FrameDescription::SetState(), v8::internal::FrameDescription::SetTop(), v8::internal::CodeStubDescriptor::stack_parameter_count(), v8::internal::Code::stub_key(), trace_scope_, V8PRIxPTR, and v8::internal::Smi::value().

Referenced by DoComputeOutputFrames().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DoComputeConstructStubFrame()

void v8::internal::Deoptimizer::DoComputeConstructStubFrame ( TranslationIterator *  iterator,
int  frame_index 
)
private

Definition at line 1238 of file deoptimizer.cc.

1239  {
1240  Builtins* builtins = isolate_->builtins();
1241  Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
1242  JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
1243  unsigned height = iterator->Next();
1244  unsigned height_in_bytes = height * kPointerSize;
1245  if (trace_scope_ != NULL) {
1246  PrintF(trace_scope_->file(),
1247  " translating construct stub => height=%d\n", height_in_bytes);
1248  }
1249 
1250  unsigned fixed_frame_size = ConstructFrameConstants::kFrameSize;
1251  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1252 
1253  // Allocate and store the output frame description.
1254  FrameDescription* output_frame =
1255  new(output_frame_size) FrameDescription(output_frame_size, function);
1256  output_frame->SetFrameType(StackFrame::CONSTRUCT);
1257 
1258  // Construct stub can not be topmost or bottommost.
1259  DCHECK(frame_index > 0 && frame_index < output_count_ - 1);
1260  DCHECK(output_[frame_index] == NULL);
1261  output_[frame_index] = output_frame;
1262 
1263  // The top address of the frame is computed from the previous
1264  // frame's top and this frame's size.
1265  intptr_t top_address;
1266  top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1267  output_frame->SetTop(top_address);
1268 
1269  // Compute the incoming parameter translation.
1270  int parameter_count = height;
1271  unsigned output_offset = output_frame_size;
1272  for (int i = 0; i < parameter_count; ++i) {
1274  int deferred_object_index = deferred_objects_.length();
1275  DoTranslateCommand(iterator, frame_index, output_offset);
1276  // The allocated receiver of a construct stub frame is passed as the
1277  // receiver parameter through the translation. It might be encoding
1278  // a captured object, patch the slot address for a captured object.
1279  if (i == 0 && deferred_objects_.length() > deferred_object_index) {
1280  CHECK(!deferred_objects_[deferred_object_index].is_arguments());
1281  deferred_objects_[deferred_object_index].patch_slot_address(top_address);
1282  }
1283  }
1284 
1285  // Read caller's PC from the previous frame.
1287  intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1288  output_frame->SetCallerPc(output_offset, callers_pc);
1289  if (trace_scope_ != NULL) {
1290  PrintF(trace_scope_->file(),
1291  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1292  V8PRIxPTR " ; caller's pc\n",
1293  top_address + output_offset, output_offset, callers_pc);
1294  }
1295 
1296  // Read caller's FP from the previous frame, and set this frame's FP.
1298  intptr_t value = output_[frame_index - 1]->GetFp();
1299  output_frame->SetCallerFp(output_offset, value);
1300  intptr_t fp_value = top_address + output_offset;
1301  output_frame->SetFp(fp_value);
1302  if (trace_scope_ != NULL) {
1303  PrintF(trace_scope_->file(),
1304  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1305  V8PRIxPTR " ; caller's fp\n",
1306  fp_value, output_offset, value);
1307  }
1308 
1309  if (FLAG_enable_ool_constant_pool) {
1310  // Read the caller's constant pool from the previous frame.
1312  value = output_[frame_index - 1]->GetConstantPool();
1313  output_frame->SetCallerConstantPool(output_offset, value);
1314  if (trace_scope_) {
1315  PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1316  V8PRIxPTR " ; caller's constant pool\n",
1317  top_address + output_offset, output_offset, value);
1318  }
1319  }
1320 
1321  // The context can be gotten from the previous frame.
1323  value = output_[frame_index - 1]->GetContext();
1324  output_frame->SetFrameSlot(output_offset, value);
1325  if (trace_scope_ != NULL) {
1326  PrintF(trace_scope_->file(),
1327  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1328  V8PRIxPTR " ; context\n",
1329  top_address + output_offset, output_offset, value);
1330  }
1331 
1332  // A marker value is used in place of the function.
1334  value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT));
1335  output_frame->SetFrameSlot(output_offset, value);
1336  if (trace_scope_ != NULL) {
1337  PrintF(trace_scope_->file(),
1338  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1339  V8PRIxPTR " ; function (construct sentinel)\n",
1340  top_address + output_offset, output_offset, value);
1341  }
1342 
1343  // The output frame reflects a JSConstructStubGeneric frame.
1345  value = reinterpret_cast<intptr_t>(construct_stub);
1346  output_frame->SetFrameSlot(output_offset, value);
1347  if (trace_scope_ != NULL) {
1348  PrintF(trace_scope_->file(),
1349  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1350  V8PRIxPTR " ; code object\n",
1351  top_address + output_offset, output_offset, value);
1352  }
1353 
1354  // Number of incoming arguments.
1356  value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
1357  output_frame->SetFrameSlot(output_offset, value);
1358  if (trace_scope_ != NULL) {
1359  PrintF(trace_scope_->file(),
1360  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1361  V8PRIxPTR " ; argc (%d)\n",
1362  top_address + output_offset, output_offset, value, height - 1);
1363  }
1364 
1365  // Constructor function being invoked by the stub (only present on some
1366  // architectures, indicated by kConstructorOffset).
1369  value = reinterpret_cast<intptr_t>(function);
1370  output_frame->SetFrameSlot(output_offset, value);
1371  if (trace_scope_ != NULL) {
1372  PrintF(trace_scope_->file(),
1373  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1374  V8PRIxPTR " ; constructor function\n",
1375  top_address + output_offset, output_offset, value);
1376  }
1377  }
1378 
1379  // The newly allocated object was passed as receiver in the artificial
1380  // constructor stub environment created by HEnvironment::CopyForInlining().
1382  value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
1383  output_frame->SetFrameSlot(output_offset, value);
1384  if (trace_scope_ != NULL) {
1385  PrintF(trace_scope_->file(),
1386  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1387  V8PRIxPTR " ; allocated receiver\n",
1388  top_address + output_offset, output_offset, value);
1389  }
1390 
1391  CHECK_EQ(0, output_offset);
1392 
1393  intptr_t pc = reinterpret_cast<intptr_t>(
1394  construct_stub->instruction_start() +
1395  isolate_->heap()->construct_stub_deopt_pc_offset()->value());
1396  output_frame->SetPc(pc);
1397  if (FLAG_enable_ool_constant_pool) {
1398  intptr_t constant_pool_value =
1399  reinterpret_cast<intptr_t>(construct_stub->constant_pool());
1400  output_frame->SetConstantPool(constant_pool_value);
1401  }
1402 }
const int kMinInt
Definition: globals.h:110

References v8::internal::Builtins::builtin(), v8::internal::Isolate::builtins(), CHECK, CHECK_EQ, ComputeLiteral(), v8::internal::Code::constant_pool(), DCHECK, deferred_objects_, DoTranslateCommand(), FrameDescription, v8::internal::Smi::FromInt(), v8::internal::FrameDescription::GetConstantPool(), v8::internal::FrameDescription::GetContext(), v8::internal::FrameDescription::GetFp(), v8::internal::FrameDescription::GetFrameSlot(), v8::internal::FrameDescription::GetPc(), v8::internal::FrameDescription::GetTop(), v8::internal::Isolate::heap(), v8::internal::Code::instruction_start(), isolate_, v8::internal::ConstructFrameConstants::kConstructorOffset, v8::internal::kFPOnStackSize, v8::internal::ConstructFrameConstants::kFrameSize, v8::internal::kMinInt, v8::internal::kPCOnStackSize, v8::internal::kPointerSize, NULL, output_, output_count_, output_offset(), v8::internal::pc, v8::internal::PrintF(), v8::internal::FrameDescription::SetCallerConstantPool(), v8::internal::FrameDescription::SetCallerFp(), v8::internal::FrameDescription::SetCallerPc(), v8::internal::FrameDescription::SetConstantPool(), v8::internal::FrameDescription::SetFp(), v8::internal::FrameDescription::SetFrameSlot(), v8::internal::FrameDescription::SetFrameType(), v8::internal::FrameDescription::SetPc(), v8::internal::FrameDescription::SetTop(), trace_scope_, and V8PRIxPTR.

Referenced by DoComputeOutputFrames().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DoComputeJSFrame()

void v8::internal::Deoptimizer::DoComputeJSFrame ( TranslationIterator *  iterator,
int  frame_index 
)
private

Definition at line 875 of file deoptimizer.cc.

876  {
877  BailoutId node_id = BailoutId(iterator->Next());
878  JSFunction* function;
879  if (frame_index != 0) {
880  function = JSFunction::cast(ComputeLiteral(iterator->Next()));
881  } else {
882  int closure_id = iterator->Next();
883  USE(closure_id);
884  CHECK_EQ(Translation::kSelfLiteralId, closure_id);
885  function = function_;
886  }
887  unsigned height = iterator->Next() - 1; // Do not count the context.
888  unsigned height_in_bytes = height * kPointerSize;
889  if (trace_scope_ != NULL) {
890  PrintF(trace_scope_->file(), " translating ");
891  function->PrintName(trace_scope_->file());
892  PrintF(trace_scope_->file(),
893  " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes);
894  }
895 
896  // The 'fixed' part of the frame consists of the incoming parameters and
897  // the part described by JavaScriptFrameConstants.
898  unsigned fixed_frame_size = ComputeFixedSize(function);
899  unsigned input_frame_size = input_->GetFrameSize();
900  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
901 
902  // Allocate and store the output frame description.
903  FrameDescription* output_frame =
904  new(output_frame_size) FrameDescription(output_frame_size, function);
905  output_frame->SetFrameType(StackFrame::JAVA_SCRIPT);
906 
907  bool is_bottommost = (0 == frame_index);
908  bool is_topmost = (output_count_ - 1 == frame_index);
909  CHECK(frame_index >= 0 && frame_index < output_count_);
910  CHECK_EQ(output_[frame_index], NULL);
911  output_[frame_index] = output_frame;
912 
913  // The top address for the bottommost output frame can be computed from
914  // the input frame pointer and the output frame's height. For all
915  // subsequent output frames, it can be computed from the previous one's
916  // top address and the current frame's size.
917  Register fp_reg = JavaScriptFrame::fp_register();
918  intptr_t top_address;
919  if (is_bottommost) {
920  // Determine whether the input frame contains alignment padding.
923  ? 1
924  : 0;
925  // 2 = context and function in the frame.
926  // If the optimized frame had alignment padding, adjust the frame pointer
927  // to point to the new position of the old frame pointer after padding
928  // is removed. Subtract 2 * kPointerSize for the context and function slots.
929  top_address = input_->GetRegister(fp_reg.code()) -
931  height_in_bytes + has_alignment_padding_ * kPointerSize;
932  } else {
933  top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
934  }
935  output_frame->SetTop(top_address);
936 
937  // Compute the incoming parameter translation.
938  int parameter_count = function->shared()->formal_parameter_count() + 1;
939  unsigned output_offset = output_frame_size;
940  unsigned input_offset = input_frame_size;
941  for (int i = 0; i < parameter_count; ++i) {
943  DoTranslateCommand(iterator, frame_index, output_offset);
944  }
945  input_offset -= (parameter_count * kPointerSize);
946 
947  // There are no translation commands for the caller's pc and fp, the
948  // context, and the function. Synthesize their values and set them up
949  // explicitly.
950  //
951  // The caller's pc for the bottommost output frame is the same as in the
952  // input frame. For all subsequent output frames, it can be read from the
953  // previous one. This frame's pc can be computed from the non-optimized
954  // function code and AST id of the bailout.
957  intptr_t value;
958  if (is_bottommost) {
959  value = input_->GetFrameSlot(input_offset);
960  } else {
961  value = output_[frame_index - 1]->GetPc();
962  }
963  output_frame->SetCallerPc(output_offset, value);
964  if (trace_scope_ != NULL) {
965  PrintF(trace_scope_->file(),
966  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
967  V8PRIxPTR " ; caller's pc\n",
968  top_address + output_offset, output_offset, value);
969  }
970 
971  // The caller's frame pointer for the bottommost output frame is the same
972  // as in the input frame. For all subsequent output frames, it can be
973  // read from the previous one. Also compute and set this frame's frame
974  // pointer.
977  if (is_bottommost) {
978  value = input_->GetFrameSlot(input_offset);
979  } else {
980  value = output_[frame_index - 1]->GetFp();
981  }
982  output_frame->SetCallerFp(output_offset, value);
983  intptr_t fp_value = top_address + output_offset;
984  DCHECK(!is_bottommost || (input_->GetRegister(fp_reg.code()) +
985  has_alignment_padding_ * kPointerSize) == fp_value);
986  output_frame->SetFp(fp_value);
987  if (is_topmost) output_frame->SetRegister(fp_reg.code(), fp_value);
988  if (trace_scope_ != NULL) {
989  PrintF(trace_scope_->file(),
990  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
991  V8PRIxPTR " ; caller's fp\n",
992  fp_value, output_offset, value);
993  }
994  DCHECK(!is_bottommost || !has_alignment_padding_ ||
995  (fp_value & kPointerSize) != 0);
996 
997  if (FLAG_enable_ool_constant_pool) {
998  // For the bottommost output frame the constant pool pointer can be gotten
999  // from the input frame. For subsequent output frames, it can be read from
1000  // the previous frame.
1003  if (is_bottommost) {
1004  value = input_->GetFrameSlot(input_offset);
1005  } else {
1006  value = output_[frame_index - 1]->GetConstantPool();
1007  }
1008  output_frame->SetCallerConstantPool(output_offset, value);
1009  if (trace_scope_) {
1010  PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1011  V8PRIxPTR "; caller's constant_pool\n",
1012  top_address + output_offset, output_offset, value);
1013  }
1014  }
1015 
1016  // For the bottommost output frame the context can be gotten from the input
1017  // frame. For all subsequent output frames it can be gotten from the function
1018  // so long as we don't inline functions that need local contexts.
1019  Register context_reg = JavaScriptFrame::context_register();
1022  // Read the context from the translations.
1023  DoTranslateCommand(iterator, frame_index, output_offset);
1024  value = output_frame->GetFrameSlot(output_offset);
1025  // The context should not be a placeholder for a materialized object.
1026  CHECK(value !=
1027  reinterpret_cast<intptr_t>(isolate_->heap()->arguments_marker()));
1028  if (value ==
1029  reinterpret_cast<intptr_t>(isolate_->heap()->undefined_value())) {
1030  // If the context was optimized away, just use the context from
1031  // the activation. This should only apply to Crankshaft code.
1033  if (is_bottommost) {
1034  value = input_->GetFrameSlot(input_offset);
1035  } else {
1036  value = reinterpret_cast<intptr_t>(function->context());
1037  }
1038  output_frame->SetFrameSlot(output_offset, value);
1039  }
1040  output_frame->SetContext(value);
1041  if (is_topmost) output_frame->SetRegister(context_reg.code(), value);
1042  if (trace_scope_ != NULL) {
1043  PrintF(trace_scope_->file(),
1044  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1045  V8PRIxPTR "; context\n",
1046  top_address + output_offset, output_offset, value);
1047  }
1048 
1049  // The function was mentioned explicitly in the BEGIN_FRAME.
1052  value = reinterpret_cast<intptr_t>(function);
1053  // The function for the bottommost output frame should also agree with the
1054  // input frame.
1055  DCHECK(!is_bottommost || input_->GetFrameSlot(input_offset) == value);
1056  output_frame->SetFrameSlot(output_offset, value);
1057  if (trace_scope_ != NULL) {
1058  PrintF(trace_scope_->file(),
1059  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1060  V8PRIxPTR "; function\n",
1061  top_address + output_offset, output_offset, value);
1062  }
1063 
1064  // Translate the rest of the frame.
1065  for (unsigned i = 0; i < height; ++i) {
1067  DoTranslateCommand(iterator, frame_index, output_offset);
1068  }
1069  CHECK_EQ(0, output_offset);
1070 
1071  // Compute this frame's PC, state, and continuation.
1072  Code* non_optimized_code = function->shared()->code();
1073  FixedArray* raw_data = non_optimized_code->deoptimization_data();
1074  DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
1075  Address start = non_optimized_code->instruction_start();
1076  unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared());
1077  unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
1078  intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset);
1079  output_frame->SetPc(pc_value);
1080 
1081  // Update constant pool.
1082  if (FLAG_enable_ool_constant_pool) {
1083  intptr_t constant_pool_value =
1084  reinterpret_cast<intptr_t>(non_optimized_code->constant_pool());
1085  output_frame->SetConstantPool(constant_pool_value);
1086  if (is_topmost) {
1087  Register constant_pool_reg =
1089  output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
1090  }
1091  }
1092 
1093  FullCodeGenerator::State state =
1095  output_frame->SetState(Smi::FromInt(state));
1096 
1097  // Set the continuation for the topmost frame.
1098  if (is_topmost && bailout_type_ != DEBUGGER) {
1099  Builtins* builtins = isolate_->builtins();
1100  Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
1101  if (bailout_type_ == LAZY) {
1102  continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
1103  } else if (bailout_type_ == SOFT) {
1104  continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized);
1105  } else {
1107  }
1108  output_frame->SetContinuation(
1109  reinterpret_cast<intptr_t>(continuation->entry()));
1110  }
1111 }
static T decode(U value)
Definition: utils.h:228
static int GetOutputInfo(DeoptimizationOutputData *data, BailoutId node_id, SharedFunctionInfo *shared)
Definition: deoptimizer.cc:707
bool HasAlignmentPadding(JSFunction *function)
static Register context_register()
static Register fp_register()
static Register constant_pool_pointer_register()
void USE(T)
Definition: macros.h:322

References bailout_type_, v8::internal::Builtins::builtin(), v8::internal::Isolate::builtins(), CHECK, CHECK_EQ, v8::internal::Register::code(), compiled_code_, ComputeFixedSize(), ComputeLiteral(), v8::internal::Code::constant_pool(), v8::internal::JavaScriptFrame::constant_pool_pointer_register(), v8::internal::JavaScriptFrame::context_register(), DCHECK, DEBUGGER, v8::internal::BitFieldBase< T, shift, size, U >::decode(), DoTranslateCommand(), EAGER, v8::internal::Code::entry(), v8::internal::JavaScriptFrame::fp_register(), FrameDescription, v8::internal::Smi::FromInt(), function(), function_, v8::internal::FrameDescription::GetConstantPool(), v8::internal::FrameDescription::GetFp(), v8::internal::FrameDescription::GetFrameSize(), v8::internal::FrameDescription::GetFrameSlot(), GetOutputInfo(), v8::internal::FrameDescription::GetPc(), v8::internal::FrameDescription::GetRegister(), v8::internal::FrameDescription::GetTop(), has_alignment_padding_, HasAlignmentPadding(), v8::internal::Isolate::heap(), input_, input_offset(), v8::internal::Code::instruction_start(), v8::internal::Code::is_turbofanned(), isolate_, v8::internal::StandardFrameConstants::kFixedFrameSizeFromFp, v8::internal::kFPOnStackSize, v8::internal::kPCOnStackSize, v8::internal::kPointerSize, LAZY, NULL, output_, output_count_, output_offset(), v8::internal::PrintF(), v8::internal::FrameDescription::SetCallerConstantPool(), v8::internal::FrameDescription::SetCallerFp(), v8::internal::FrameDescription::SetCallerPc(), v8::internal::FrameDescription::SetConstantPool(), v8::internal::FrameDescription::SetContext(), v8::internal::FrameDescription::SetContinuation(), v8::internal::FrameDescription::SetFp(), v8::internal::FrameDescription::SetFrameSlot(), v8::internal::FrameDescription::SetFrameType(), v8::internal::FrameDescription::SetPc(), v8::internal::FrameDescription::SetRegister(), v8::internal::FrameDescription::SetState(), v8::internal::FrameDescription::SetTop(), SOFT, v8::internal::BailoutId::ToInt(), trace_scope_, USE(), and V8PRIxPTR.

Referenced by DoComputeOutputFrames().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DoComputeOutputFrames()

void v8::internal::Deoptimizer::DoComputeOutputFrames ( )
private

Definition at line 750 of file deoptimizer.cc.

750  {
751  // Print some helpful diagnostic information.
752  if (FLAG_log_timer_events &&
753  compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
754  LOG(isolate(), CodeDeoptEvent(compiled_code_));
755  }
756  base::ElapsedTimer timer;
757 
758  // Determine basic deoptimization information. The optimized frame is
759  // described by the input data.
760  DeoptimizationInputData* input_data =
761  DeoptimizationInputData::cast(compiled_code_->deoptimization_data());
762 
763  if (trace_scope_ != NULL) {
764  timer.Start();
765  PrintF(trace_scope_->file(),
766  "[deoptimizing (DEOPT %s): begin 0x%08" V8PRIxPTR " ",
768  reinterpret_cast<intptr_t>(function_));
770  PrintF(trace_scope_->file(),
771  " (opt #%d) @%d, FP to SP delta: %d]\n",
772  input_data->OptimizationId()->value(),
773  bailout_id_,
775  if (bailout_type_ == EAGER || bailout_type_ == SOFT ||
778  }
779  }
780 
781  BailoutId node_id = input_data->AstId(bailout_id_);
782  ByteArray* translations = input_data->TranslationByteArray();
783  unsigned translation_index =
784  input_data->TranslationIndex(bailout_id_)->value();
785 
786  // Do the input frame to output frame(s) translation.
787  TranslationIterator iterator(translations, translation_index);
788  Translation::Opcode opcode =
789  static_cast<Translation::Opcode>(iterator.Next());
790  DCHECK(Translation::BEGIN == opcode);
791  USE(opcode);
792  // Read the number of output frames and allocate an array for their
793  // descriptions.
794  int count = iterator.Next();
795  iterator.Next(); // Drop JS frames count.
796  DCHECK(output_ == NULL);
797  output_ = new FrameDescription*[count];
798  for (int i = 0; i < count; ++i) {
799  output_[i] = NULL;
800  }
801  output_count_ = count;
802 
803  Register fp_reg = JavaScriptFrame::fp_register();
804  stack_fp_ = reinterpret_cast<Address>(
805  input_->GetRegister(fp_reg.code()) +
807 
808  // Translate each output frame.
809  for (int i = 0; i < count; ++i) {
810  // Read the ast node id, function, and frame height for this output frame.
811  Translation::Opcode opcode =
812  static_cast<Translation::Opcode>(iterator.Next());
813  switch (opcode) {
815  DoComputeJSFrame(&iterator, i);
816  jsframe_count_++;
817  break;
818  case Translation::ARGUMENTS_ADAPTOR_FRAME:
819  DoComputeArgumentsAdaptorFrame(&iterator, i);
820  break;
821  case Translation::CONSTRUCT_STUB_FRAME:
822  DoComputeConstructStubFrame(&iterator, i);
823  break;
824  case Translation::GETTER_STUB_FRAME:
825  DoComputeAccessorStubFrame(&iterator, i, false);
826  break;
827  case Translation::SETTER_STUB_FRAME:
828  DoComputeAccessorStubFrame(&iterator, i, true);
829  break;
830  case Translation::COMPILED_STUB_FRAME:
831  DoComputeCompiledStubFrame(&iterator, i);
832  break;
833  case Translation::BEGIN:
835  case Translation::INT32_REGISTER:
836  case Translation::UINT32_REGISTER:
837  case Translation::DOUBLE_REGISTER:
838  case Translation::STACK_SLOT:
839  case Translation::INT32_STACK_SLOT:
840  case Translation::UINT32_STACK_SLOT:
841  case Translation::DOUBLE_STACK_SLOT:
842  case Translation::LITERAL:
843  case Translation::ARGUMENTS_OBJECT:
844  default:
845  FATAL("Unsupported translation");
846  break;
847  }
848  }
849 
850  // Print some helpful diagnostic information.
851  if (trace_scope_ != NULL) {
852  double ms = timer.Elapsed().InMillisecondsF();
853  int index = output_count_ - 1; // Index of the topmost frame.
854  JSFunction* function = output_[index]->GetFunction();
855  PrintF(trace_scope_->file(),
856  "[deoptimizing (%s): end 0x%08" V8PRIxPTR " ",
858  reinterpret_cast<intptr_t>(function));
860  PrintF(trace_scope_->file(),
861  " @%d => node=%d, pc=0x%08" V8PRIxPTR ", state=%s, alignment=%s,"
862  " took %0.3f ms]\n",
863  bailout_id_,
864  node_id.ToInt(),
865  output_[index]->GetPc(),
867  static_cast<FullCodeGenerator::State>(
868  output_[index]->GetState()->value())),
869  has_alignment_padding_ ? "with padding" : "no padding",
870  ms);
871  }
872 }
#define REGISTER(N, C)
void PrintDeoptLocation(FILE *out, int bailout_id)
Definition: objects.cc:10589
void DoComputeAccessorStubFrame(TranslationIterator *iterator, int frame_index, bool is_setter_stub_frame)
static const char * MessageFor(BailoutType type)
Definition: deoptimizer.cc:536
void DoComputeCompiledStubFrame(TranslationIterator *iterator, int frame_index)
void DoComputeConstructStubFrame(TranslationIterator *iterator, int frame_index)
void DoComputeJSFrame(TranslationIterator *iterator, int frame_index)
Definition: deoptimizer.cc:875
void DoComputeArgumentsAdaptorFrame(TranslationIterator *iterator, int frame_index)
JSFunction * GetFunction() const
Definition: deoptimizer.h:482
static const char * State2String(State state)
Definition: full-codegen.h:90
int value() const
Definition: objects-inl.h:1316
#define LOG(isolate, Call)
Definition: log.h:69
#define FATAL(msg)
Definition: logging.h:26

References v8::internal::DeoptimizationInputData::AstId(), bailout_id_, bailout_type_, v8::internal::Register::code(), compiled_code_, DCHECK, DoComputeAccessorStubFrame(), DoComputeArgumentsAdaptorFrame(), DoComputeCompiledStubFrame(), DoComputeConstructStubFrame(), DoComputeJSFrame(), EAGER, FATAL, v8::internal::JavaScriptFrame::fp_register(), fp_to_sp_delta_, function_, v8::internal::FrameDescription::GetFunction(), v8::internal::FrameDescription::GetPc(), v8::internal::FrameDescription::GetRegister(), v8::internal::FrameDescription::GetState(), has_alignment_padding_, input_, v8::internal::Code::is_hydrogen_stub(), isolate(), v8::internal::compiler::JS_FRAME, jsframe_count_, v8::internal::Code::kind(), v8::internal::kPointerSize, LOG, MessageFor(), NULL, output_, output_count_, v8::internal::Code::PrintDeoptLocation(), v8::internal::PrintF(), PrintFunctionName(), REGISTER, SOFT, stack_fp_, v8::internal::FullCodeGenerator::State2String(), v8::internal::BailoutId::ToInt(), trace_scope_, USE(), V8PRIxPTR, and v8::internal::Smi::value().

Referenced by ComputeOutputFrames().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DoTranslateCommand()

void v8::internal::Deoptimizer::DoTranslateCommand ( TranslationIterator *  iterator,
int  frame_index,
unsigned  output_offset 
)
private

Definition at line 2421 of file deoptimizer.cc.

2423  {
2424  disasm::NameConverter converter;
2425  // A GC-safe temporary placeholder that we can put in the output frame.
2426  const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0));
2427 
2428  Translation::Opcode opcode =
2429  static_cast<Translation::Opcode>(iterator->Next());
2430 
2431  switch (opcode) {
2432  case Translation::BEGIN:
2433  case Translation::JS_FRAME:
2434  case Translation::ARGUMENTS_ADAPTOR_FRAME:
2435  case Translation::CONSTRUCT_STUB_FRAME:
2436  case Translation::GETTER_STUB_FRAME:
2437  case Translation::SETTER_STUB_FRAME:
2438  case Translation::COMPILED_STUB_FRAME:
2439  FATAL("Unexpected translation opcode");
2440  return;
2441 
2442  case Translation::REGISTER: {
2443  int input_reg = iterator->Next();
2444  intptr_t input_value = input_->GetRegister(input_reg);
2445  if (trace_scope_ != NULL) {
2446  PrintF(
2447  trace_scope_->file(),
2448  " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s ",
2449  output_[frame_index]->GetTop() + output_offset,
2450  output_offset,
2451  input_value,
2452  converter.NameOfCPURegister(input_reg));
2453  reinterpret_cast<Object*>(input_value)->ShortPrint(
2454  trace_scope_->file());
2455  PrintF(trace_scope_->file(), "\n");
2456  }
2457  output_[frame_index]->SetFrameSlot(output_offset, input_value);
2458  return;
2459  }
2460 
2461  case Translation::INT32_REGISTER: {
2462  int input_reg = iterator->Next();
2463  intptr_t value = input_->GetRegister(input_reg);
2464  bool is_smi = Smi::IsValid(value);
2465  if (trace_scope_ != NULL) {
2466  PrintF(
2467  trace_scope_->file(),
2468  " 0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIdPTR " ; %s (%s)\n",
2469  output_[frame_index]->GetTop() + output_offset,
2470  output_offset,
2471  value,
2472  converter.NameOfCPURegister(input_reg),
2473  TraceValueType(is_smi));
2474  }
2475  if (is_smi) {
2476  intptr_t tagged_value =
2477  reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2478  output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
2479  } else {
2480  // We save the untagged value on the side and store a GC-safe
2481  // temporary placeholder in the frame.
2482  AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
2483  static_cast<double>(static_cast<int32_t>(value)));
2484  output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
2485  }
2486  return;
2487  }
2488 
2489  case Translation::UINT32_REGISTER: {
2490  int input_reg = iterator->Next();
2491  uintptr_t value = static_cast<uintptr_t>(input_->GetRegister(input_reg));
2492  bool is_smi = value <= static_cast<uintptr_t>(Smi::kMaxValue);
2493  if (trace_scope_ != NULL) {
2494  PrintF(
2495  trace_scope_->file(),
2496  " 0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIuPTR
2497  " ; uint %s (%s)\n",
2498  output_[frame_index]->GetTop() + output_offset,
2499  output_offset,
2500  value,
2501  converter.NameOfCPURegister(input_reg),
2502  TraceValueType(is_smi));
2503  }
2504  if (is_smi) {
2505  intptr_t tagged_value =
2506  reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2507  output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
2508  } else {
2509  // We save the untagged value on the side and store a GC-safe
2510  // temporary placeholder in the frame.
2511  AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
2512  static_cast<double>(static_cast<uint32_t>(value)));
2513  output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
2514  }
2515  return;
2516  }
2517 
2518  case Translation::DOUBLE_REGISTER: {
2519  int input_reg = iterator->Next();
2520  double value = input_->GetDoubleRegister(input_reg);
2521  if (trace_scope_ != NULL) {
2522  PrintF(trace_scope_->file(),
2523  " 0x%08" V8PRIxPTR ": [top + %d] <- %e ; %s\n",
2524  output_[frame_index]->GetTop() + output_offset,
2525  output_offset,
2526  value,
2528  }
2529  // We save the untagged value on the side and store a GC-safe
2530  // temporary placeholder in the frame.
2531  AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value);
2532  output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
2533  return;
2534  }
2535 
2536  case Translation::STACK_SLOT: {
2537  int input_slot_index = iterator->Next();
2538  unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2539  intptr_t input_value = input_->GetFrameSlot(input_offset);
2540  if (trace_scope_ != NULL) {
2541  PrintF(trace_scope_->file(),
2542  " 0x%08" V8PRIxPTR ": ",
2543  output_[frame_index]->GetTop() + output_offset);
2544  PrintF(trace_scope_->file(),
2545  "[top + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d] ",
2546  output_offset,
2547  input_value,
2548  input_offset);
2549  reinterpret_cast<Object*>(input_value)->ShortPrint(
2550  trace_scope_->file());
2551  PrintF(trace_scope_->file(), "\n");
2552  }
2553  output_[frame_index]->SetFrameSlot(output_offset, input_value);
2554  return;
2555  }
2556 
2557  case Translation::INT32_STACK_SLOT: {
2558  int input_slot_index = iterator->Next();
2559  unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2560  intptr_t value = input_->GetFrameSlot(input_offset);
2561  bool is_smi = Smi::IsValid(value);
2562  if (trace_scope_ != NULL) {
2563  PrintF(trace_scope_->file(),
2564  " 0x%08" V8PRIxPTR ": ",
2565  output_[frame_index]->GetTop() + output_offset);
2566  PrintF(trace_scope_->file(),
2567  "[top + %d] <- %" V8PRIdPTR " ; [sp + %d] (%s)\n",
2568  output_offset,
2569  value,
2570  input_offset,
2571  TraceValueType(is_smi));
2572  }
2573  if (is_smi) {
2574  intptr_t tagged_value =
2575  reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2576  output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
2577  } else {
2578  // We save the untagged value on the side and store a GC-safe
2579  // temporary placeholder in the frame.
2580  AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
2581  static_cast<double>(static_cast<int32_t>(value)));
2582  output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
2583  }
2584  return;
2585  }
2586 
2587  case Translation::UINT32_STACK_SLOT: {
2588  int input_slot_index = iterator->Next();
2589  unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2590  uintptr_t value =
2591  static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
2592  bool is_smi = value <= static_cast<uintptr_t>(Smi::kMaxValue);
2593  if (trace_scope_ != NULL) {
2594  PrintF(trace_scope_->file(),
2595  " 0x%08" V8PRIxPTR ": ",
2596  output_[frame_index]->GetTop() + output_offset);
2597  PrintF(trace_scope_->file(),
2598  "[top + %d] <- %" V8PRIuPTR " ; [sp + %d] (uint32 %s)\n",
2599  output_offset,
2600  value,
2601  input_offset,
2602  TraceValueType(is_smi));
2603  }
2604  if (is_smi) {
2605  intptr_t tagged_value =
2606  reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2607  output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
2608  } else {
2609  // We save the untagged value on the side and store a GC-safe
2610  // temporary placeholder in the frame.
2611  AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
2612  static_cast<double>(static_cast<uint32_t>(value)));
2613  output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
2614  }
2615  return;
2616  }
2617 
2618  case Translation::DOUBLE_STACK_SLOT: {
2619  int input_slot_index = iterator->Next();
2620  unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2621  double value = input_->GetDoubleFrameSlot(input_offset);
2622  if (trace_scope_ != NULL) {
2623  PrintF(trace_scope_->file(),
2624  " 0x%08" V8PRIxPTR ": [top + %d] <- %e ; [sp + %d]\n",
2625  output_[frame_index]->GetTop() + output_offset,
2626  output_offset,
2627  value,
2628  input_offset);
2629  }
2630  // We save the untagged value on the side and store a GC-safe
2631  // temporary placeholder in the frame.
2632  AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value);
2633  output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
2634  return;
2635  }
2636 
2637  case Translation::LITERAL: {
2638  Object* literal = ComputeLiteral(iterator->Next());
2639  if (trace_scope_ != NULL) {
2640  PrintF(trace_scope_->file(),
2641  " 0x%08" V8PRIxPTR ": [top + %d] <- ",
2642  output_[frame_index]->GetTop() + output_offset,
2643  output_offset);
2644  literal->ShortPrint(trace_scope_->file());
2645  PrintF(trace_scope_->file(), " ; literal\n");
2646  }
2647  intptr_t value = reinterpret_cast<intptr_t>(literal);
2648  output_[frame_index]->SetFrameSlot(output_offset, value);
2649  return;
2650  }
2651 
2652  case Translation::DUPLICATED_OBJECT: {
2653  int object_index = iterator->Next();
2654  if (trace_scope_ != NULL) {
2655  PrintF(trace_scope_->file(),
2656  " 0x%08" V8PRIxPTR ": [top + %d] <- ",
2657  output_[frame_index]->GetTop() + output_offset,
2658  output_offset);
2659  isolate_->heap()->arguments_marker()->ShortPrint(trace_scope_->file());
2660  PrintF(trace_scope_->file(),
2661  " ; duplicate of object #%d\n", object_index);
2662  }
2663  // Use the materialization marker value as a sentinel and fill in
2664  // the object after the deoptimized frame is built.
2665  intptr_t value = reinterpret_cast<intptr_t>(
2666  isolate_->heap()->arguments_marker());
2667  AddObjectDuplication(output_[frame_index]->GetTop() + output_offset,
2668  object_index);
2669  output_[frame_index]->SetFrameSlot(output_offset, value);
2670  return;
2671  }
2672 
2673  case Translation::ARGUMENTS_OBJECT:
2674  case Translation::CAPTURED_OBJECT: {
2675  int length = iterator->Next();
2676  bool is_args = opcode == Translation::ARGUMENTS_OBJECT;
2677  if (trace_scope_ != NULL) {
2678  PrintF(trace_scope_->file(),
2679  " 0x%08" V8PRIxPTR ": [top + %d] <- ",
2680  output_[frame_index]->GetTop() + output_offset,
2681  output_offset);
2682  isolate_->heap()->arguments_marker()->ShortPrint(trace_scope_->file());
2683  PrintF(trace_scope_->file(),
2684  " ; object (length = %d, is_args = %d)\n", length, is_args);
2685  }
2686  // Use the materialization marker value as a sentinel and fill in
2687  // the object after the deoptimized frame is built.
2688  intptr_t value = reinterpret_cast<intptr_t>(
2689  isolate_->heap()->arguments_marker());
2690  AddObjectStart(output_[frame_index]->GetTop() + output_offset,
2691  length, is_args);
2692  output_[frame_index]->SetFrameSlot(output_offset, value);
2693  // We save the object values on the side and materialize the actual
2694  // object after the deoptimized frame is built.
2695  int object_index = deferred_objects_.length() - 1;
2696  for (int i = 0; i < length; i++) {
2697  DoTranslateObject(iterator, object_index, i);
2698  }
2699  return;
2700  }
2701  }
2702 }
virtual const char * NameOfCPURegister(int reg) const
void AddObjectStart(intptr_t slot_address, int argc, bool is_arguments)
void AddDoubleValue(intptr_t slot_address, double value)
void DoTranslateObject(TranslationIterator *iterator, int object_index, int field_index)
void AddObjectDuplication(intptr_t slot, int object_index)
unsigned GetOffsetFromSlotIndex(int slot_index)
double GetDoubleFrameSlot(unsigned offset)
Definition: deoptimizer.h:490
void SetFrameSlot(unsigned offset, intptr_t value)
Definition: deoptimizer.h:495
static const int kMaxValue
Definition: objects.h:1272
static bool IsValid(intptr_t value)
Definition: objects-inl.h:1334
#define V8PRIuPTR
Definition: macros.h:365
#define V8PRIdPTR
Definition: macros.h:364
int int32_t
Definition: unicode.cc:24
static const char * TraceValueType(bool is_smi)
static const char * AllocationIndexToString(int index)

References AddDoubleValue(), AddObjectDuplication(), AddObjectStart(), v8::internal::DwVfpRegister::AllocationIndexToString(), ComputeLiteral(), deferred_objects_, DoTranslateObject(), FATAL, v8::internal::Smi::FromInt(), v8::internal::FrameDescription::GetDoubleFrameSlot(), v8::internal::FrameDescription::GetDoubleRegister(), v8::internal::FrameDescription::GetFrameSlot(), v8::internal::FrameDescription::GetOffsetFromSlotIndex(), v8::internal::FrameDescription::GetRegister(), v8::internal::FrameDescription::GetTop(), v8::internal::Isolate::heap(), input_, input_offset(), isolate_, v8::internal::Smi::IsValid(), v8::internal::compiler::JS_FRAME, v8::internal::Smi::kMaxValue, disasm::NameConverter::NameOfCPURegister(), NULL, output_, output_offset(), v8::internal::PrintF(), REGISTER, v8::internal::FrameDescription::SetFrameSlot(), v8::internal::Object::ShortPrint(), trace_scope_, v8::internal::TraceValueType(), V8PRIdPTR, V8PRIuPTR, and V8PRIxPTR.

Referenced by DoComputeAccessorStubFrame(), DoComputeArgumentsAdaptorFrame(), DoComputeCompiledStubFrame(), DoComputeConstructStubFrame(), and DoComputeJSFrame().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DoTranslateObject()

void v8::internal::Deoptimizer::DoTranslateObject ( TranslationIterator *  iterator,
int  object_index,
int  field_index 
)
private

Definition at line 2159 of file deoptimizer.cc.

2161  {
2162  disasm::NameConverter converter;
2163  Address object_slot = deferred_objects_[object_index].slot_address();
2164 
2165  Translation::Opcode opcode =
2166  static_cast<Translation::Opcode>(iterator->Next());
2167 
2168  switch (opcode) {
2169  case Translation::BEGIN:
2170  case Translation::JS_FRAME:
2171  case Translation::ARGUMENTS_ADAPTOR_FRAME:
2172  case Translation::CONSTRUCT_STUB_FRAME:
2173  case Translation::GETTER_STUB_FRAME:
2174  case Translation::SETTER_STUB_FRAME:
2175  case Translation::COMPILED_STUB_FRAME:
2176  FATAL("Unexpected frame start translation opcode");
2177  return;
2178 
2179  case Translation::REGISTER: {
2180  int input_reg = iterator->Next();
2181  intptr_t input_value = input_->GetRegister(input_reg);
2182  if (trace_scope_ != NULL) {
2183  PrintF(trace_scope_->file(),
2184  " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2185  reinterpret_cast<intptr_t>(object_slot),
2186  field_index);
2187  PrintF(trace_scope_->file(),
2188  "0x%08" V8PRIxPTR " ; %s ", input_value,
2189  converter.NameOfCPURegister(input_reg));
2190  reinterpret_cast<Object*>(input_value)->ShortPrint(
2191  trace_scope_->file());
2192  PrintF(trace_scope_->file(),
2193  "\n");
2194  }
2195  AddObjectTaggedValue(input_value);
2196  return;
2197  }
2198 
2199  case Translation::INT32_REGISTER: {
2200  int input_reg = iterator->Next();
2201  intptr_t value = input_->GetRegister(input_reg);
2202  bool is_smi = Smi::IsValid(value);
2203  if (trace_scope_ != NULL) {
2204  PrintF(trace_scope_->file(),
2205  " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2206  reinterpret_cast<intptr_t>(object_slot),
2207  field_index);
2208  PrintF(trace_scope_->file(),
2209  "%" V8PRIdPTR " ; %s (%s)\n", value,
2210  converter.NameOfCPURegister(input_reg),
2211  TraceValueType(is_smi));
2212  }
2213  if (is_smi) {
2214  intptr_t tagged_value =
2215  reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2216  AddObjectTaggedValue(tagged_value);
2217  } else {
2218  double double_value = static_cast<double>(static_cast<int32_t>(value));
2219  AddObjectDoubleValue(double_value);
2220  }
2221  return;
2222  }
2223 
2224  case Translation::UINT32_REGISTER: {
2225  int input_reg = iterator->Next();
2226  uintptr_t value = static_cast<uintptr_t>(input_->GetRegister(input_reg));
2227  bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
2228  if (trace_scope_ != NULL) {
2229  PrintF(trace_scope_->file(),
2230  " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2231  reinterpret_cast<intptr_t>(object_slot),
2232  field_index);
2233  PrintF(trace_scope_->file(),
2234  "%" V8PRIdPTR " ; uint %s (%s)\n", value,
2235  converter.NameOfCPURegister(input_reg),
2236  TraceValueType(is_smi));
2237  }
2238  if (is_smi) {
2239  intptr_t tagged_value =
2240  reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2241  AddObjectTaggedValue(tagged_value);
2242  } else {
2243  double double_value = static_cast<double>(static_cast<uint32_t>(value));
2244  AddObjectDoubleValue(double_value);
2245  }
2246  return;
2247  }
2248 
2249  case Translation::DOUBLE_REGISTER: {
2250  int input_reg = iterator->Next();
2251  double value = input_->GetDoubleRegister(input_reg);
2252  if (trace_scope_ != NULL) {
2253  PrintF(trace_scope_->file(),
2254  " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2255  reinterpret_cast<intptr_t>(object_slot),
2256  field_index);
2257  PrintF(trace_scope_->file(),
2258  "%e ; %s\n", value,
2260  }
2261  AddObjectDoubleValue(value);
2262  return;
2263  }
2264 
2265  case Translation::STACK_SLOT: {
2266  int input_slot_index = iterator->Next();
2267  unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2268  intptr_t input_value = input_->GetFrameSlot(input_offset);
2269  if (trace_scope_ != NULL) {
2270  PrintF(trace_scope_->file(),
2271  " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2272  reinterpret_cast<intptr_t>(object_slot),
2273  field_index);
2274  PrintF(trace_scope_->file(),
2275  "0x%08" V8PRIxPTR " ; [sp + %d] ", input_value, input_offset);
2276  reinterpret_cast<Object*>(input_value)->ShortPrint(
2277  trace_scope_->file());
2278  PrintF(trace_scope_->file(),
2279  "\n");
2280  }
2281  AddObjectTaggedValue(input_value);
2282  return;
2283  }
2284 
2285  case Translation::INT32_STACK_SLOT: {
2286  int input_slot_index = iterator->Next();
2287  unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2288  intptr_t value = input_->GetFrameSlot(input_offset);
2289  bool is_smi = Smi::IsValid(value);
2290  if (trace_scope_ != NULL) {
2291  PrintF(trace_scope_->file(),
2292  " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2293  reinterpret_cast<intptr_t>(object_slot),
2294  field_index);
2295  PrintF(trace_scope_->file(),
2296  "%" V8PRIdPTR " ; [sp + %d] (%s)\n",
2297  value, input_offset, TraceValueType(is_smi));
2298  }
2299  if (is_smi) {
2300  intptr_t tagged_value =
2301  reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2302  AddObjectTaggedValue(tagged_value);
2303  } else {
2304  double double_value = static_cast<double>(static_cast<int32_t>(value));
2305  AddObjectDoubleValue(double_value);
2306  }
2307  return;
2308  }
2309 
2310  case Translation::UINT32_STACK_SLOT: {
2311  int input_slot_index = iterator->Next();
2312  unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2313  uintptr_t value =
2314  static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
2315  bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
2316  if (trace_scope_ != NULL) {
2317  PrintF(trace_scope_->file(),
2318  " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2319  reinterpret_cast<intptr_t>(object_slot),
2320  field_index);
2321  PrintF(trace_scope_->file(),
2322  "%" V8PRIdPTR " ; [sp + %d] (uint %s)\n",
2323  value, input_offset, TraceValueType(is_smi));
2324  }
2325  if (is_smi) {
2326  intptr_t tagged_value =
2327  reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2328  AddObjectTaggedValue(tagged_value);
2329  } else {
2330  double double_value = static_cast<double>(static_cast<uint32_t>(value));
2331  AddObjectDoubleValue(double_value);
2332  }
2333  return;
2334  }
2335 
2336  case Translation::DOUBLE_STACK_SLOT: {
2337  int input_slot_index = iterator->Next();
2338  unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2339  double value = input_->GetDoubleFrameSlot(input_offset);
2340  if (trace_scope_ != NULL) {
2341  PrintF(trace_scope_->file(),
2342  " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2343  reinterpret_cast<intptr_t>(object_slot),
2344  field_index);
2345  PrintF(trace_scope_->file(),
2346  "%e ; [sp + %d]\n", value, input_offset);
2347  }
2348  AddObjectDoubleValue(value);
2349  return;
2350  }
2351 
2352  case Translation::LITERAL: {
2353  Object* literal = ComputeLiteral(iterator->Next());
2354  if (trace_scope_ != NULL) {
2355  PrintF(trace_scope_->file(),
2356  " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2357  reinterpret_cast<intptr_t>(object_slot),
2358  field_index);
2359  literal->ShortPrint(trace_scope_->file());
2360  PrintF(trace_scope_->file(),
2361  " ; literal\n");
2362  }
2363  intptr_t value = reinterpret_cast<intptr_t>(literal);
2364  AddObjectTaggedValue(value);
2365  return;
2366  }
2367 
2368  case Translation::DUPLICATED_OBJECT: {
2369  int object_index = iterator->Next();
2370  if (trace_scope_ != NULL) {
2371  PrintF(trace_scope_->file(),
2372  " nested @0x%08" V8PRIxPTR ": [field #%d] <- ",
2373  reinterpret_cast<intptr_t>(object_slot),
2374  field_index);
2375  isolate_->heap()->arguments_marker()->ShortPrint(trace_scope_->file());
2376  PrintF(trace_scope_->file(),
2377  " ; duplicate of object #%d\n", object_index);
2378  }
2379  // Use the materialization marker value as a sentinel and fill in
2380  // the object after the deoptimized frame is built.
2381  intptr_t value = reinterpret_cast<intptr_t>(
2382  isolate_->heap()->arguments_marker());
2383  AddObjectDuplication(0, object_index);
2384  AddObjectTaggedValue(value);
2385  return;
2386  }
2387 
2388  case Translation::ARGUMENTS_OBJECT:
2389  case Translation::CAPTURED_OBJECT: {
2390  int length = iterator->Next();
2391  bool is_args = opcode == Translation::ARGUMENTS_OBJECT;
2392  if (trace_scope_ != NULL) {
2393  PrintF(trace_scope_->file(),
2394  " nested @0x%08" V8PRIxPTR ": [field #%d] <- ",
2395  reinterpret_cast<intptr_t>(object_slot),
2396  field_index);
2397  isolate_->heap()->arguments_marker()->ShortPrint(trace_scope_->file());
2398  PrintF(trace_scope_->file(),
2399  " ; object (length = %d, is_args = %d)\n", length, is_args);
2400  }
2401  // Use the materialization marker value as a sentinel and fill in
2402  // the object after the deoptimized frame is built.
2403  intptr_t value = reinterpret_cast<intptr_t>(
2404  isolate_->heap()->arguments_marker());
2405  AddObjectStart(0, length, is_args);
2406  AddObjectTaggedValue(value);
2407  // We save the object values on the side and materialize the actual
2408  // object after the deoptimized frame is built.
2409  int object_index = deferred_objects_.length() - 1;
2410  for (int i = 0; i < length; i++) {
2411  DoTranslateObject(iterator, object_index, i);
2412  }
2413  return;
2414  }
2415  }
2416 
2417  FATAL("Unexpected translation opcode");
2418 }
void AddObjectDoubleValue(double value)
void AddObjectTaggedValue(intptr_t value)

References AddObjectDoubleValue(), AddObjectDuplication(), AddObjectStart(), AddObjectTaggedValue(), v8::internal::DwVfpRegister::AllocationIndexToString(), ComputeLiteral(), deferred_objects_, FATAL, v8::internal::Smi::FromInt(), v8::internal::FrameDescription::GetDoubleFrameSlot(), v8::internal::FrameDescription::GetDoubleRegister(), v8::internal::FrameDescription::GetFrameSlot(), v8::internal::FrameDescription::GetOffsetFromSlotIndex(), v8::internal::FrameDescription::GetRegister(), v8::internal::Isolate::heap(), input_, input_offset(), isolate_, v8::internal::Smi::IsValid(), v8::internal::compiler::JS_FRAME, v8::internal::Smi::kMaxValue, disasm::NameConverter::NameOfCPURegister(), NULL, v8::internal::PrintF(), REGISTER, v8::internal::Object::ShortPrint(), trace_scope_, v8::internal::TraceValueType(), V8PRIdPTR, and V8PRIxPTR.

Referenced by DoTranslateCommand(), and DoTranslateObjectAndSkip().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ DoTranslateObjectAndSkip()

void v8::internal::Deoptimizer::DoTranslateObjectAndSkip ( TranslationIterator *  iterator)
private

Definition at line 2092 of file deoptimizer.cc.

2092  {
2093  Translation::Opcode opcode =
2094  static_cast<Translation::Opcode>(iterator->Next());
2095 
2096  switch (opcode) {
2097  case Translation::BEGIN:
2098  case Translation::JS_FRAME:
2099  case Translation::ARGUMENTS_ADAPTOR_FRAME:
2100  case Translation::CONSTRUCT_STUB_FRAME:
2101  case Translation::GETTER_STUB_FRAME:
2102  case Translation::SETTER_STUB_FRAME:
2103  case Translation::COMPILED_STUB_FRAME: {
2104  FATAL("Unexpected frame start translation opcode");
2105  return;
2106  }
2107 
2108  case Translation::REGISTER:
2109  case Translation::INT32_REGISTER:
2110  case Translation::UINT32_REGISTER:
2111  case Translation::DOUBLE_REGISTER:
2112  case Translation::STACK_SLOT:
2113  case Translation::INT32_STACK_SLOT:
2114  case Translation::UINT32_STACK_SLOT:
2115  case Translation::DOUBLE_STACK_SLOT:
2116  case Translation::LITERAL: {
2117  // The value is not part of any materialized object, so we can ignore it.
2118  iterator->Skip(Translation::NumberOfOperandsFor(opcode));
2119  return;
2120  }
2121 
2122  case Translation::DUPLICATED_OBJECT: {
2123  int object_index = iterator->Next();
2124  if (trace_scope_ != NULL) {
2125  PrintF(trace_scope_->file(), " skipping object ");
2126  PrintF(trace_scope_->file(),
2127  " ; duplicate of object #%d\n", object_index);
2128  }
2129  AddObjectDuplication(0, object_index);
2130  return;
2131  }
2132 
2133  case Translation::ARGUMENTS_OBJECT:
2134  case Translation::CAPTURED_OBJECT: {
2135  int length = iterator->Next();
2136  bool is_args = opcode == Translation::ARGUMENTS_OBJECT;
2137  if (trace_scope_ != NULL) {
2138  PrintF(trace_scope_->file(), " skipping object ");
2139  PrintF(trace_scope_->file(),
2140  " ; object (length = %d, is_args = %d)\n", length, is_args);
2141  }
2142 
2143  AddObjectStart(0, length, is_args);
2144 
2145  // We save the object values on the side and materialize the actual
2146  // object after the deoptimized frame is built.
2147  int object_index = deferred_objects_.length() - 1;
2148  for (int i = 0; i < length; i++) {
2149  DoTranslateObject(iterator, object_index, i);
2150  }
2151  return;
2152  }
2153  }
2154 
2155  FATAL("Unexpected translation opcode");
2156 }

References AddObjectDuplication(), AddObjectStart(), deferred_objects_, DoTranslateObject(), FATAL, v8::internal::compiler::JS_FRAME, NULL, v8::internal::PrintF(), REGISTER, and trace_scope_.

Referenced by DoComputeAccessorStubFrame().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ EnsureCodeForDeoptimizationEntry()

void v8::internal::Deoptimizer::EnsureCodeForDeoptimizationEntry ( Isolate isolate,
BailoutType  type,
int  max_entry_id 
)
static

Definition at line 2790 of file deoptimizer.cc.

2792  {
2793  // We cannot run this if the serializer is enabled because this will
2794  // cause us to emit relocation information for the external
2795  // references. This is fine because the deoptimizer's code section
2796  // isn't meant to be serialized at all.
2797  CHECK(type == EAGER || type == SOFT || type == LAZY);
2798  DeoptimizerData* data = isolate->deoptimizer_data();
2799  int entry_count = data->deopt_entry_code_entries_[type];
2800  if (max_entry_id < entry_count) return;
2801  entry_count = Max(entry_count, Deoptimizer::kMinNumberOfEntries);
2802  while (max_entry_id >= entry_count) entry_count *= 2;
2803  CHECK(entry_count <= Deoptimizer::kMaxNumberOfEntries);
2804 
2805  MacroAssembler masm(isolate, NULL, 16 * KB);
2806  masm.set_emit_debug_code(false);
2807  GenerateDeoptimizationEntries(&masm, entry_count, type);
2808  CodeDesc desc;
2809  masm.GetCode(&desc);
2810  DCHECK(!RelocInfo::RequiresRelocation(desc));
2811 
2812  MemoryChunk* chunk = data->deopt_entry_code_[type];
2813  CHECK(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >=
2814  desc.instr_size);
2815  chunk->CommitArea(desc.instr_size);
2816  CopyBytes(chunk->area_start(), desc.buffer,
2817  static_cast<size_t>(desc.instr_size));
2818  CpuFeatures::FlushICache(chunk->area_start(), desc.instr_size);
2819 
2820  data->deopt_entry_code_entries_[type] = entry_count;
2821 }
static void FlushICache(void *start, size_t size)
int deopt_entry_code_entries_[Deoptimizer::kBailoutTypesWithCodeEntry]
Definition: deoptimizer.h:643
static void GenerateDeoptimizationEntries(MacroAssembler *masm, int count, BailoutType type)
Definition: deoptimizer.cc:232
static const int kMaxNumberOfEntries
Definition: deoptimizer.h:296
static const int kMinNumberOfEntries
Definition: deoptimizer.h:295
static size_t GetMaxDeoptTableSize()
Definition: deoptimizer.cc:101
const int KB
Definition: globals.h:106
static LifetimePosition Max(LifetimePosition a, LifetimePosition b)
void CopyBytes(uint8_t *target, uint8_t *source)

References v8::internal::MemoryChunk::area_start(), v8::internal::CodeDesc::buffer, CHECK, v8::internal::MemoryChunk::CommitArea(), v8::internal::CopyBytes(), DCHECK, v8::internal::DeoptimizerData::deopt_entry_code_, v8::internal::DeoptimizerData::deopt_entry_code_entries_, v8::internal::Isolate::deoptimizer_data(), EAGER, v8::internal::CpuFeatures::FlushICache(), GenerateDeoptimizationEntries(), v8::internal::Assembler::GetCode(), GetMaxDeoptTableSize(), v8::internal::CodeDesc::instr_size, isolate(), v8::internal::KB, kMaxNumberOfEntries, kMinNumberOfEntries, LAZY, v8::internal::Max(), NULL, v8::internal::AssemblerBase::set_emit_debug_code(), and SOFT.

Referenced by GetDeoptimizationEntry(), and v8::internal::Isolate::Init().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ EnsureRelocSpaceForLazyDeoptimization()

static void v8::internal::Deoptimizer::EnsureRelocSpaceForLazyDeoptimization ( Handle< Code code)
static

◆ FillInputFrame()

void v8::internal::Deoptimizer::FillInputFrame ( Address  tos,
JavaScriptFrame frame 
)
private

Definition at line 82 of file deoptimizer-arm.cc.

82  {
83  // Set the register values. The values are not important as there are no
84  // callee saved registers in JavaScript frames, so all registers are
85  // spilled. Registers fp and sp are set to the correct values though.
86 
87  for (int i = 0; i < Register::kNumRegisters; i++) {
88  input_->SetRegister(i, i * 4);
89  }
90  input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp()));
91  input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp()));
92  for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) {
93  input_->SetDoubleRegister(i, 0.0);
94  }
95 
96  // Fill the frame content from the actual data on the frame.
97  for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) {
99  }
100 }
void SetRegister(unsigned n, intptr_t value)
Definition: deoptimizer.h:523
void SetDoubleRegister(unsigned n, double value)
Definition: deoptimizer.h:528
static uint32_t & uint32_at(Address addr)
Definition: v8memory.h:24
const Register fp
const Register sp
static const int kNumRegisters
Definition: assembler-arm.h:95

References v8::internal::Register::code(), v8::internal::fp, v8::internal::FrameDescription::GetFrameSize(), input_, v8::internal::Register::kNumRegisters, v8::internal::kPointerSize, v8::internal::DwVfpRegister::NumAllocatableRegisters(), v8::internal::FrameDescription::SetDoubleRegister(), v8::internal::FrameDescription::SetFrameSlot(), v8::internal::FrameDescription::SetRegister(), v8::internal::sp, and v8::internal::Memory::uint32_at().

Referenced by DebuggerInspectableFrame().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ FindDeoptimizingCode()

Code * v8::internal::Deoptimizer::FindDeoptimizingCode ( Address  addr)
private

Definition at line 60 of file deoptimizer.cc.

60  {
61  if (function_->IsHeapObject()) {
62  // Search all deoptimizing code in the native context of the function.
63  Context* native_context = function_->context()->native_context();
64  Object* element = native_context->DeoptimizedCodeListHead();
65  while (!element->IsUndefined()) {
66  Code* code = Code::cast(element);
67  CHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
68  if (code->contains(addr)) return code;
69  element = code->next_code_link();
70  }
71  }
72  return NULL;
73 }
Context * native_context()
Definition: contexts.cc:44

References CHECK, v8::internal::Code::contains(), v8::internal::JSFunction::context(), v8::internal::Context::DeoptimizedCodeListHead(), function_, v8::internal::Code::kind(), v8::internal::Context::native_context(), and NULL.

Referenced by FindOptimizedCode().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ FindOptimizedCode()

Code * v8::internal::Deoptimizer::FindOptimizedCode ( JSFunction function,
Code optimized_code 
)
private

Definition at line 618 of file deoptimizer.cc.

619  {
620  switch (bailout_type_) {
621  case Deoptimizer::SOFT:
622  case Deoptimizer::EAGER:
623  case Deoptimizer::LAZY: {
625  return (compiled_code == NULL)
626  ? static_cast<Code*>(isolate_->FindCodeObject(from_))
627  : compiled_code;
628  }
630  DCHECK(optimized_code->contains(from_));
631  return optimized_code;
632  }
633  FATAL("Could not find code for optimized function");
634  return NULL;
635 }
Code * FindDeoptimizingCode(Address addr)
Definition: deoptimizer.cc:60
Handle< Code > compiled_code() const
Definition: deoptimizer.h:150
Object * FindCodeObject(Address a)
Definition: isolate.cc:2214

References bailout_type_, compiled_code(), v8::internal::Code::contains(), DCHECK, DEBUGGER, EAGER, FATAL, v8::internal::Isolate::FindCodeObject(), FindDeoptimizingCode(), from_, isolate_, LAZY, NULL, and SOFT.

Referenced by Deoptimizer().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ function()

Handle<JSFunction> v8::internal::Deoptimizer::function ( ) const
inline

Definition at line 149 of file deoptimizer.h.

149 { return Handle<JSFunction>(function_); }

References function_.

Referenced by ComputeIncomingArgumentSize(), DeoptimizeFunction(), Deoptimizer(), DoComputeJSFrame(), v8::internal::RUNTIME_FUNCTION(), and VisitAllOptimizedFunctionsForContext().

+ Here is the caller graph for this function:

◆ GenerateDeoptimizationEntries()

void v8::internal::Deoptimizer::GenerateDeoptimizationEntries ( MacroAssembler masm,
int  count,
BailoutType  type 
)
staticprivate

Definition at line 232 of file deoptimizer.cc.

234  {
235  TableEntryGenerator generator(masm, type, count);
236  generator.Generate();
237 }

Referenced by EnsureCodeForDeoptimizationEntry().

+ Here is the caller graph for this function:

◆ GetDeoptimizationEntry()

Address v8::internal::Deoptimizer::GetDeoptimizationEntry ( Isolate isolate,
int  id,
BailoutType  type,
GetEntryMode  mode = ENSURE_ENTRY_CODE 
)
static

Definition at line 672 of file deoptimizer.cc.

675  {
676  CHECK_GE(id, 0);
677  if (id >= kMaxNumberOfEntries) return NULL;
678  if (mode == ENSURE_ENTRY_CODE) {
680  } else {
682  }
683  DeoptimizerData* data = isolate->deoptimizer_data();
685  MemoryChunk* base = data->deopt_entry_code_[type];
686  return base->area_start() + (id * table_entry_size_);
687 }
static const int kBailoutTypesWithCodeEntry
Definition: deoptimizer.h:102
static const int table_entry_size_
Definition: deoptimizer.h:451
static void EnsureCodeForDeoptimizationEntry(Isolate *isolate, BailoutType type, int max_entry_id)
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp

References v8::internal::MemoryChunk::area_start(), CALCULATE_ENTRY_ADDRESS, CHECK_EQ, CHECK_GE, CHECK_LT, v8::internal::DeoptimizerData::deopt_entry_code_, v8::internal::Isolate::deoptimizer_data(), ENSURE_ENTRY_CODE, EnsureCodeForDeoptimizationEntry(), isolate(), kBailoutTypesWithCodeEntry, kMaxNumberOfEntries, mode(), NULL, and table_entry_size_.

Referenced by v8::internal::LCodeGen::DeoptimizeBranch(), v8::internal::LCodeGen::DeoptimizeIf(), PatchCodeForDeoptimization(), and v8::internal::ExternalReferenceTable::PopulateTable().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GetDeoptimizationId()

int v8::internal::Deoptimizer::GetDeoptimizationId ( Isolate isolate,
Address  addr,
BailoutType  type 
)
static

Definition at line 690 of file deoptimizer.cc.

692  {
693  DeoptimizerData* data = isolate->deoptimizer_data();
694  MemoryChunk* base = data->deopt_entry_code_[type];
695  Address start = base->area_start();
696  if (base == NULL ||
697  addr < start ||
698  addr >= start + (kMaxNumberOfEntries * table_entry_size_)) {
700  }
701  DCHECK_EQ(0,
702  static_cast<int>(addr - start) % table_entry_size_);
703  return static_cast<int>(addr - start) / table_entry_size_;
704 }
MemoryChunk * deopt_entry_code_[Deoptimizer::kBailoutTypesWithCodeEntry]
Definition: deoptimizer.h:644
static const int kNotDeoptimizationEntry
Definition: deoptimizer.h:247
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206

References v8::internal::MemoryChunk::area_start(), DCHECK_EQ, v8::internal::DeoptimizerData::deopt_entry_code_, v8::internal::Isolate::deoptimizer_data(), isolate(), kMaxNumberOfEntries, kNotDeoptimizationEntry, NULL, and table_entry_size_.

Referenced by v8::internal::Code::PrintDeoptLocation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GetDeoptimizedCodeCount()

int v8::internal::Deoptimizer::GetDeoptimizedCodeCount ( Isolate isolate)
static

Definition at line 729 of file deoptimizer.cc.

729  {
730  int length = 0;
731  // Count all entries in the deoptimizing code list of every context.
732  Object* context = isolate->heap()->native_contexts_list();
733  while (!context->IsUndefined()) {
734  Context* native_context = Context::cast(context);
735  Object* element = native_context->DeoptimizedCodeListHead();
736  while (!element->IsUndefined()) {
737  Code* code = Code::cast(element);
738  DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
739  length++;
740  element = code->next_code_link();
741  }
742  context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
743  }
744  return length;
745 }
Object * get(int index)
Definition: objects-inl.h:2165

References v8::internal::Context::cast(), DCHECK, v8::internal::Context::DeoptimizedCodeListHead(), v8::internal::FixedArray::get(), v8::internal::Isolate::heap(), isolate(), v8::internal::Code::kind(), v8::internal::Heap::native_contexts_list(), and v8::internal::Context::NEXT_CONTEXT_LINK.

+ Here is the call graph for this function:

◆ GetMaxDeoptTableSize()

size_t v8::internal::Deoptimizer::GetMaxDeoptTableSize ( )
static

Definition at line 101 of file deoptimizer.cc.

101  {
102  int entries_size =
104  int commit_page_size = static_cast<int>(base::OS::CommitPageSize());
105  int page_count = ((kDeoptTableMaxEpilogueCodeSize + entries_size - 1) /
106  commit_page_size) + 1;
107  return static_cast<size_t>(commit_page_size * page_count);
108 }
static intptr_t CommitPageSize()
static const int kDeoptTableMaxEpilogueCodeSize
Definition: deoptimizer.cc:98

References v8::base::OS::CommitPageSize(), v8::internal::kDeoptTableMaxEpilogueCodeSize, kMaxNumberOfEntries, and table_entry_size_.

Referenced by v8::internal::AllocateCodeChunk(), and EnsureCodeForDeoptimizationEntry().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ GetOutputInfo()

int v8::internal::Deoptimizer::GetOutputInfo ( DeoptimizationOutputData data,
BailoutId  node_id,
SharedFunctionInfo shared 
)
static

Definition at line 707 of file deoptimizer.cc.

709  {
710  // TODO(kasperl): For now, we do a simple linear search for the PC
711  // offset associated with the given node id. This should probably be
712  // changed to a binary search.
713  int length = data->DeoptPoints();
714  for (int i = 0; i < length; i++) {
715  if (data->AstId(i) == id) {
716  return data->PcAndState(i)->value();
717  }
718  }
719  OFStream os(stderr);
720  os << "[couldn't find pc offset for node=" << id.ToInt() << "]\n"
721  << "[method: " << shared->DebugName()->ToCString().get() << "]\n"
722  << "[source:\n" << SourceCodeOf(shared) << "\n]" << endl;
723 
724  FATAL("unable to find pc offset during deoptimization");
725  return -1;
726 }
OStream & endl(OStream &os)
Definition: ostreams.cc:112

References v8::internal::DeoptimizationOutputData::AstId(), v8::internal::SharedFunctionInfo::DebugName(), v8::internal::DeoptimizationOutputData::DeoptPoints(), v8::internal::endl(), FATAL, v8::internal::DeoptimizationOutputData::PcAndState(), v8::internal::String::ToCString(), and v8::internal::Smi::value().

Referenced by DoComputeJSFrame(), v8::internal::OptimizedFrame::Summarize(), and v8::internal::SharedFunctionInfo::VerifyBailoutId().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Grab()

Deoptimizer * v8::internal::Deoptimizer::Grab ( Isolate isolate)
static

Definition at line 111 of file deoptimizer.cc.

111  {
113  CHECK_NE(result, NULL);
114  result->DeleteFrameDescriptions();
116  return result;
117 }

References CHECK_NE, v8::internal::DeoptimizerData::current_, DeleteFrameDescriptions(), v8::internal::Isolate::deoptimizer_data(), isolate(), and NULL.

Referenced by v8::internal::RUNTIME_FUNCTION().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ has_alignment_padding_offset()

static int v8::internal::Deoptimizer::has_alignment_padding_offset ( )
inlinestatic

Definition at line 241 of file deoptimizer.h.

241  {
243  }
#define OFFSET_OF(type, field)
Definition: macros.h:22

References has_alignment_padding_, and OFFSET_OF.

◆ HasAlignmentPadding()

bool v8::internal::Deoptimizer::HasAlignmentPadding ( JSFunction function)
private

Definition at line 122 of file deoptimizer-arm.cc.

122  {
123  // There is no dynamic alignment padding on ARM in the input frame.
124  return false;
125 }

Referenced by DoComputeJSFrame().

+ Here is the caller graph for this function:

◆ input_offset()

static int v8::internal::Deoptimizer::input_offset ( )
inlinestatic

Definition at line 235 of file deoptimizer.h.

235 { return OFFSET_OF(Deoptimizer, input_); }

References input_, and OFFSET_OF.

Referenced by DoComputeJSFrame(), DoTranslateCommand(), and DoTranslateObject().

+ Here is the caller graph for this function:

◆ isolate()

Isolate* v8::internal::Deoptimizer::isolate ( ) const
inline

◆ jsframe_count()

int v8::internal::Deoptimizer::jsframe_count ( ) const
inline

Definition at line 154 of file deoptimizer.h.

154 { return jsframe_count_; }

References jsframe_count_.

Referenced by DebuggerInspectableFrame(), and MaterializeHeapObjects().

+ Here is the caller graph for this function:

◆ MarkAllCodeForContext()

void v8::internal::Deoptimizer::MarkAllCodeForContext ( Context native_context)
staticprivate

Definition at line 492 of file deoptimizer.cc.

492  {
493  Object* element = context->OptimizedCodeListHead();
494  while (!element->IsUndefined()) {
495  Code* code = Code::cast(element);
496  CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
497  code->set_marked_for_deoptimization(true);
498  element = code->next_code_link();
499  }
500 }

References CHECK_EQ, v8::internal::Code::kind(), v8::internal::Context::OptimizedCodeListHead(), and v8::internal::Code::set_marked_for_deoptimization().

Referenced by DeoptimizeAll(), and DeoptimizeGlobalObject().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MaterializeHeapNumbersForDebuggerInspectableFrame()

void v8::internal::Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame ( Address  parameters_top,
uint32_t  parameters_size,
Address  expressions_top,
uint32_t  expressions_size,
DeoptimizedFrameInfo info 
)

Definition at line 2029 of file deoptimizer.cc.

2034  {
2036  Address parameters_bottom = parameters_top + parameters_size;
2037  Address expressions_bottom = expressions_top + expressions_size;
2038  for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
2039  HeapNumberMaterializationDescriptor<Address> d = deferred_heap_numbers_[i];
2040 
2041  // Check of the heap number to materialize actually belong to the frame
2042  // being extracted.
2043  Address slot = d.destination();
2044  if (parameters_top <= slot && slot < parameters_bottom) {
2045  Handle<Object> num = isolate_->factory()->NewNumber(d.value());
2046 
2047  int index = (info->parameters_count() - 1) -
2048  static_cast<int>(slot - parameters_top) / kPointerSize;
2049 
2050  if (trace_scope_ != NULL) {
2051  PrintF(trace_scope_->file(),
2052  "Materializing a new heap number %p [%e] in slot %p"
2053  "for parameter slot #%d\n",
2054  reinterpret_cast<void*>(*num),
2055  d.value(),
2056  d.destination(),
2057  index);
2058  }
2059 
2060  info->SetParameter(index, *num);
2061  } else if (expressions_top <= slot && slot < expressions_bottom) {
2062  Handle<Object> num = isolate_->factory()->NewNumber(d.value());
2063 
2064  int index = info->expression_count() - 1 -
2065  static_cast<int>(slot - expressions_top) / kPointerSize;
2066 
2067  if (trace_scope_ != NULL) {
2068  PrintF(trace_scope_->file(),
2069  "Materializing a new heap number %p [%e] in slot %p"
2070  "for expression slot #%d\n",
2071  reinterpret_cast<void*>(*num),
2072  d.value(),
2073  d.destination(),
2074  index);
2075  }
2076 
2077  info->SetExpression(index, *num);
2078  }
2079  }
2080 }
Factory * factory()
Definition: isolate.h:982

References bailout_type_, CHECK_EQ, DEBUGGER, deferred_heap_numbers_, v8::internal::DeoptimizedFrameInfo::expression_count(), v8::internal::Isolate::factory(), isolate_, v8::internal::kPointerSize, NULL, v8::internal::DeoptimizedFrameInfo::parameters_count(), v8::internal::PrintF(), v8::internal::DeoptimizedFrameInfo::SetExpression(), v8::internal::DeoptimizedFrameInfo::SetParameter(), and trace_scope_.

Referenced by DebuggerInspectableFrame().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MaterializeHeapObjects()

void v8::internal::Deoptimizer::MaterializeHeapObjects ( JavaScriptFrameIterator *  it)

Definition at line 1922 of file deoptimizer.cc.

1922  {
1924 
1925  MaterializedObjectStore* materialized_store =
1927  previously_materialized_objects_ = materialized_store->Get(stack_fp_);
1929  0 : previously_materialized_objects_->length();
1930 
1931  // Walk all JavaScript output frames with the given frame iterator.
1932  for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
1933  if (frame_index != 0) it->Advance();
1934  JavaScriptFrame* frame = it->frame();
1935  jsframe_functions_.Add(handle(frame->function(), isolate_));
1936  jsframe_has_adapted_arguments_.Add(frame->has_adapted_arguments());
1937  }
1938 
1939  // Handlify all tagged object values before triggering any allocation.
1940  List<Handle<Object> > values(deferred_objects_tagged_values_.length());
1941  for (int i = 0; i < deferred_objects_tagged_values_.length(); ++i) {
1942  values.Add(Handle<Object>(deferred_objects_tagged_values_[i], isolate_));
1943  }
1944 
1945  // Play it safe and clear all unhandlified values before we continue.
1947 
1948  // Materialize all heap numbers before looking at arguments because when the
1949  // output frames are used to materialize arguments objects later on they need
1950  // to already contain valid heap numbers.
1951  for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
1952  HeapNumberMaterializationDescriptor<Address> d = deferred_heap_numbers_[i];
1953  Handle<Object> num = isolate_->factory()->NewNumber(d.value());
1954  if (trace_scope_ != NULL) {
1955  PrintF(trace_scope_->file(),
1956  "Materialized a new heap number %p [%e] in slot %p\n",
1957  reinterpret_cast<void*>(*num),
1958  d.value(),
1959  d.destination());
1960  }
1961  Memory::Object_at(d.destination()) = *num;
1962  }
1963 
1964  // Materialize all heap numbers required for arguments/captured objects.
1965  for (int i = 0; i < deferred_objects_double_values_.length(); i++) {
1966  HeapNumberMaterializationDescriptor<int> d =
1968  Handle<Object> num = isolate_->factory()->NewNumber(d.value());
1969  if (trace_scope_ != NULL) {
1970  PrintF(trace_scope_->file(),
1971  "Materialized a new heap number %p [%e] for object at %d\n",
1972  reinterpret_cast<void*>(*num),
1973  d.value(),
1974  d.destination());
1975  }
1976  DCHECK(values.at(d.destination())->IsTheHole());
1977  values.Set(d.destination(), num);
1978  }
1979 
1980  // Play it safe and clear all object double values before we continue.
1982 
1983  // Materialize arguments/captured objects.
1984  if (!deferred_objects_.is_empty()) {
1985  List<Handle<Object> > materialized_objects(deferred_objects_.length());
1986  materialized_objects_ = &materialized_objects;
1987  materialized_values_ = &values;
1988 
1990  int object_index = materialization_object_index_;
1991  ObjectMaterializationDescriptor descriptor =
1992  deferred_objects_.at(object_index);
1993 
1994  // Find a previously materialized object by de-duplication or
1995  // materialize a new instance of the object if necessary. Store
1996  // the materialized object into the frame slot.
1997  Handle<Object> object = MaterializeNextHeapObject();
1998  if (descriptor.slot_address() != NULL) {
1999  Memory::Object_at(descriptor.slot_address()) = *object;
2000  }
2001  if (trace_scope_ != NULL) {
2002  if (descriptor.is_arguments()) {
2003  PrintF(trace_scope_->file(),
2004  "Materialized %sarguments object of length %d for %p: ",
2005  ArgumentsObjectIsAdapted(object_index) ? "(adapted) " : "",
2006  Handle<JSObject>::cast(object)->elements()->length(),
2007  reinterpret_cast<void*>(descriptor.slot_address()));
2008  } else {
2009  PrintF(trace_scope_->file(),
2010  "Materialized captured object of size %d for %p: ",
2011  Handle<HeapObject>::cast(object)->Size(),
2012  reinterpret_cast<void*>(descriptor.slot_address()));
2013  }
2014  object->ShortPrint(trace_scope_->file());
2015  PrintF(trace_scope_->file(), "\n");
2016  }
2017  }
2018 
2021  }
2022 
2023  if (prev_materialized_count_ > 0) {
2024  materialized_store->Remove(stack_fp_);
2025  }
2026 }
Handle< Object > MaterializeNextHeapObject()
bool ArgumentsObjectIsAdapted(int object_index)
Definition: deoptimizer.h:350
Handle< FixedArray > previously_materialized_objects_
Definition: deoptimizer.h:432
static Handle< T > cast(Handle< S > that)
Definition: handles.h:116
MaterializedObjectStore * materialized_object_store()
Definition: isolate.h:879
static Object *& Object_at(Address addr)
Definition: v8memory.h:60
#define DCHECK_NE(v1, v2)
Definition: logging.h:207
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146

References v8::internal::List< T, AllocationPolicy >::Add(), ArgumentsObjectIsAdapted(), v8::internal::List< T, AllocationPolicy >::at(), bailout_type_, CHECK_EQ, DCHECK, DCHECK_NE, DEBUGGER, deferred_heap_numbers_, deferred_objects_, deferred_objects_double_values_, deferred_objects_tagged_values_, v8::internal::Isolate::factory(), v8::internal::JavaScriptFrame::function(), v8::internal::MaterializedObjectStore::Get(), v8::internal::handle(), v8::internal::JavaScriptFrame::has_adapted_arguments(), isolate_, jsframe_count(), jsframe_functions_, jsframe_has_adapted_arguments_, materialization_object_index_, materialization_value_index_, v8::internal::Isolate::materialized_object_store(), materialized_objects_, materialized_values_, MaterializeNextHeapObject(), NULL, v8::internal::Memory::Object_at(), prev_materialized_count_, previously_materialized_objects_, v8::internal::PrintF(), v8::internal::MaterializedObjectStore::Remove(), v8::internal::List< T, AllocationPolicy >::Set(), stack_fp_, and trace_scope_.

Referenced by v8::internal::RUNTIME_FUNCTION().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MaterializeNextHeapObject()

Handle< Object > v8::internal::Deoptimizer::MaterializeNextHeapObject ( )
private

Definition at line 1804 of file deoptimizer.cc.

1804  {
1805  int object_index = materialization_object_index_++;
1806  ObjectMaterializationDescriptor desc = deferred_objects_[object_index];
1807  const int length = desc.object_length();
1808 
1809  if (desc.duplicate_object() >= 0) {
1810  // Found a previously materialized object by de-duplication.
1811  object_index = desc.duplicate_object();
1812  materialized_objects_->Add(Handle<Object>());
1813  } else if (desc.is_arguments() && ArgumentsObjectIsAdapted(object_index)) {
1814  // Use the arguments adapter frame we just built to materialize the
1815  // arguments object. FunctionGetArguments can't throw an exception.
1816  Handle<JSFunction> function = ArgumentsObjectFunction(object_index);
1817  Handle<JSObject> arguments = Handle<JSObject>::cast(
1819  materialized_objects_->Add(arguments);
1820  // To keep consistent object counters, we still materialize the
1821  // nested values (but we throw them away).
1822  for (int i = 0; i < length; ++i) {
1824  }
1825  } else if (desc.is_arguments()) {
1826  // Construct an arguments object and copy the parameters to a newly
1827  // allocated arguments object backing store.
1828  Handle<JSFunction> function = ArgumentsObjectFunction(object_index);
1829  Handle<JSObject> arguments =
1830  isolate_->factory()->NewArgumentsObject(function, length);
1831  Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length);
1832  DCHECK_EQ(array->length(), length);
1833  arguments->set_elements(*array);
1834  materialized_objects_->Add(arguments);
1835  for (int i = 0; i < length; ++i) {
1836  Handle<Object> value = MaterializeNextValue();
1837  array->set(i, *value);
1838  }
1839  } else {
1840  // Dispatch on the instance type of the object to be materialized.
1841  // We also need to make sure that the representation of all fields
1842  // in the given object are general enough to hold a tagged value.
1845  switch (map->instance_type()) {
1847  case HEAP_NUMBER_TYPE: {
1848  // Reuse the HeapNumber value directly as it is already properly
1849  // tagged and skip materializing the HeapNumber explicitly. Turn mutable
1850  // heap numbers immutable.
1851  Handle<Object> object = MaterializeNextValue();
1852  if (object_index < prev_materialized_count_) {
1853  materialized_objects_->Add(Handle<Object>(
1854  previously_materialized_objects_->get(object_index), isolate_));
1855  } else {
1856  materialized_objects_->Add(object);
1857  }
1859  break;
1860  }
1861  case JS_OBJECT_TYPE: {
1862  Handle<JSObject> object =
1863  isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED, false);
1864  if (object_index < prev_materialized_count_) {
1865  materialized_objects_->Add(Handle<Object>(
1866  previously_materialized_objects_->get(object_index), isolate_));
1867  } else {
1868  materialized_objects_->Add(object);
1869  }
1870  Handle<Object> properties = MaterializeNextValue();
1871  Handle<Object> elements = MaterializeNextValue();
1872  object->set_properties(FixedArray::cast(*properties));
1873  object->set_elements(FixedArrayBase::cast(*elements));
1874  for (int i = 0; i < length - 3; ++i) {
1875  Handle<Object> value = MaterializeNextValue();
1876  FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
1877  object->FastPropertyAtPut(index, *value);
1878  }
1879  break;
1880  }
1881  case JS_ARRAY_TYPE: {
1882  Handle<JSArray> object =
1883  isolate_->factory()->NewJSArray(0, map->elements_kind());
1884  if (object_index < prev_materialized_count_) {
1885  materialized_objects_->Add(Handle<Object>(
1886  previously_materialized_objects_->get(object_index), isolate_));
1887  } else {
1888  materialized_objects_->Add(object);
1889  }
1890  Handle<Object> properties = MaterializeNextValue();
1891  Handle<Object> elements = MaterializeNextValue();
1892  Handle<Object> length = MaterializeNextValue();
1893  object->set_properties(FixedArray::cast(*properties));
1894  object->set_elements(FixedArrayBase::cast(*elements));
1895  object->set_length(*length);
1896  break;
1897  }
1898  default:
1899  PrintF(stderr,
1900  "[couldn't handle instance type %d]\n", map->instance_type());
1901  FATAL("Unsupported instance type");
1902  }
1903  }
1904 
1905  return materialized_objects_->at(object_index);
1906 }
static Handle< Object > FunctionGetArguments(Handle< JSFunction > object)
Definition: accessors.cc:1157
Handle< JSFunction > ArgumentsObjectFunction(int object_index)
Definition: deoptimizer.h:356
Handle< Object > MaterializeNextValue()
static Handle< Map > GeneralizeAllFieldRepresentations(Handle< Map > map)
Definition: objects.cc:2676
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
const int kDoubleSize
Definition: globals.h:127
@ JS_ARRAY_TYPE
Definition: objects.h:738
@ JS_OBJECT_TYPE
Definition: objects.h:731
@ MUTABLE_HEAP_NUMBER_TYPE
Definition: objects.h:670
@ HEAP_NUMBER_TYPE
Definition: objects.h:669

References ArgumentsObjectFunction(), ArgumentsObjectIsAdapted(), v8::internal::Handle< T >::cast(), DCHECK_EQ, deferred_objects_, v8::internal::Isolate::factory(), FATAL, v8::internal::Accessors::FunctionGetArguments(), v8::internal::Map::GeneralizeAllFieldRepresentations(), v8::internal::HEAP_NUMBER_TYPE, isolate_, v8::internal::JS_ARRAY_TYPE, v8::internal::JS_OBJECT_TYPE, v8::internal::kDoubleSize, v8::internal::kPointerSize, map, materialization_object_index_, materialization_value_index_, materialized_objects_, MaterializeNextValue(), v8::internal::MUTABLE_HEAP_NUMBER_TYPE, v8::internal::NOT_TENURED, prev_materialized_count_, previously_materialized_objects_, and v8::internal::PrintF().

Referenced by MaterializeHeapObjects(), and MaterializeNextValue().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MaterializeNextValue()

Handle< Object > v8::internal::Deoptimizer::MaterializeNextValue ( )
private

Definition at line 1909 of file deoptimizer.cc.

1909  {
1910  int value_index = materialization_value_index_++;
1911  Handle<Object> value = materialized_values_->at(value_index);
1912  if (value->IsMutableHeapNumber()) {
1913  HeapNumber::cast(*value)->set_map(isolate_->heap()->heap_number_map());
1914  }
1915  if (*value == isolate_->heap()->arguments_marker()) {
1916  value = MaterializeNextHeapObject();
1917  }
1918  return value;
1919 }

References v8::internal::Isolate::heap(), isolate_, materialization_value_index_, materialized_values_, and MaterializeNextHeapObject().

Referenced by MaterializeNextHeapObject().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MessageFor()

const char * v8::internal::Deoptimizer::MessageFor ( BailoutType  type)
static

Definition at line 536 of file deoptimizer.cc.

536  {
537  switch (type) {
538  case EAGER: return "eager";
539  case SOFT: return "soft";
540  case LAZY: return "lazy";
541  case DEBUGGER: return "debugger";
542  }
543  FATAL("Unsupported deopt type");
544  return NULL;
545 }

References DEBUGGER, EAGER, FATAL, LAZY, NULL, and SOFT.

Referenced by DoComputeOutputFrames().

+ Here is the caller graph for this function:

◆ New()

Deoptimizer * v8::internal::Deoptimizer::New ( JSFunction function,
BailoutType  type,
unsigned  bailout_id,
Address  from,
int  fp_to_sp_delta,
Isolate isolate 
)
static

Definition at line 78 of file deoptimizer.cc.

83  {
84  Deoptimizer* deoptimizer = new Deoptimizer(isolate,
85  function,
86  type,
87  bailout_id,
88  from,
89  fp_to_sp_delta,
90  NULL);
92  isolate->deoptimizer_data()->current_ = deoptimizer;
93  return deoptimizer;
94 }

References CHECK, v8::internal::DeoptimizerData::current_, Deoptimizer(), v8::internal::Isolate::deoptimizer_data(), isolate(), and NULL.

+ Here is the call graph for this function:

◆ output_count()

int v8::internal::Deoptimizer::output_count ( ) const
inline

Definition at line 147 of file deoptimizer.h.

147 { return output_count_; }

References output_count_.

◆ output_count_offset()

static int v8::internal::Deoptimizer::output_count_offset ( )
inlinestatic

Definition at line 236 of file deoptimizer.h.

236  {
238  }

References OFFSET_OF, and output_count_.

◆ output_offset()

static int v8::internal::Deoptimizer::output_offset ( )
inlinestatic

Definition at line 239 of file deoptimizer.h.

239 { return OFFSET_OF(Deoptimizer, output_); }

References OFFSET_OF, and output_.

Referenced by DoComputeAccessorStubFrame(), DoComputeArgumentsAdaptorFrame(), DoComputeConstructStubFrame(), DoComputeJSFrame(), and DoTranslateCommand().

+ Here is the caller graph for this function:

◆ patch_size()

int v8::internal::Deoptimizer::patch_size ( )
static

Definition at line 18 of file deoptimizer-arm.cc.

18  {
19  const int kCallInstructionSizeInWords = 3;
20  return kCallInstructionSizeInWords * Assembler::kInstrSize;
21 }
static const int kInstrSize

References v8::internal::Assembler::kInstrSize.

Referenced by v8::internal::LCodeGen::GenerateBodyInstructionPre(), and PatchCodeForDeoptimization().

+ Here is the caller graph for this function:

◆ PatchCodeForDeoptimization()

void v8::internal::Deoptimizer::PatchCodeForDeoptimization ( Isolate isolate,
Code code 
)
staticprivate

Definition at line 24 of file deoptimizer-arm.cc.

24  {
25  Address code_start_address = code->instruction_start();
26  // Invalidate the relocation information, as it will become invalid by the
27  // code patching below, and is not needed any more.
28  code->InvalidateRelocation();
29 
30  if (FLAG_zap_code_space) {
31  // Fail hard and early if we enter this code object again.
32  byte* pointer = code->FindCodeAgeSequence();
33  if (pointer != NULL) {
34  pointer += kNoCodeAgeSequenceLength;
35  } else {
36  pointer = code->instruction_start();
37  }
38  CodePatcher patcher(pointer, 1);
39  patcher.masm()->bkpt(0);
40 
41  DeoptimizationInputData* data =
42  DeoptimizationInputData::cast(code->deoptimization_data());
43  int osr_offset = data->OsrPcOffset()->value();
44  if (osr_offset > 0) {
45  CodePatcher osr_patcher(code->instruction_start() + osr_offset, 1);
46  osr_patcher.masm()->bkpt(0);
47  }
48  }
49 
50  DeoptimizationInputData* deopt_data =
51  DeoptimizationInputData::cast(code->deoptimization_data());
52 #ifdef DEBUG
53  Address prev_call_address = NULL;
54 #endif
55  // For each LLazyBailout instruction insert a call to the corresponding
56  // deoptimization entry.
57  for (int i = 0; i < deopt_data->DeoptCount(); i++) {
58  if (deopt_data->Pc(i)->value() == -1) continue;
59  Address call_address = code_start_address + deopt_data->Pc(i)->value();
60  Address deopt_entry = GetDeoptimizationEntry(isolate, i, LAZY);
61  // We need calls to have a predictable size in the unoptimized code, but
62  // this is optimized code, so we don't have to have a predictable size.
63  int call_size_in_bytes =
65  deopt_entry,
67  int call_size_in_words = call_size_in_bytes / Assembler::kInstrSize;
68  DCHECK(call_size_in_bytes % Assembler::kInstrSize == 0);
69  DCHECK(call_size_in_bytes <= patch_size());
70  CodePatcher patcher(call_address, call_size_in_words);
71  patcher.masm()->Call(deopt_entry, RelocInfo::NONE32);
72  DCHECK(prev_call_address == NULL ||
73  call_address >= prev_call_address + patch_size());
74  DCHECK(call_address + patch_size() <= code->instruction_end());
75 #ifdef DEBUG
76  prev_call_address = call_address;
77 #endif
78  }
79 }
static Address GetDeoptimizationEntry(Isolate *isolate, int id, BailoutType type, GetEntryMode mode=ENSURE_ENTRY_CODE)
Definition: deoptimizer.cc:672
static int CallSizeNotPredictableCodeSize(Isolate *isolate, Address target, RelocInfo::Mode rmode, Condition cond=al)
static const int kNoCodeAgeSequenceLength

References v8::internal::Assembler::bkpt(), v8::internal::MacroAssembler::Call(), v8::internal::MacroAssembler::CallSizeNotPredictableCodeSize(), DCHECK, v8::internal::DeoptimizationInputData::DeoptCount(), v8::internal::Code::FindCodeAgeSequence(), GetDeoptimizationEntry(), v8::internal::Code::instruction_end(), v8::internal::Code::instruction_start(), v8::internal::Code::InvalidateRelocation(), isolate(), v8::internal::Assembler::kInstrSize, v8::internal::kNoCodeAgeSequenceLength, LAZY, v8::internal::CodePatcher::masm(), v8::internal::RelocInfo::NONE32, NULL, and patch_size().

Referenced by DeoptimizeMarkedCodeForContext().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PrintFunctionName()

void v8::internal::Deoptimizer::PrintFunctionName ( )
private

Definition at line 638 of file deoptimizer.cc.

638  {
639  if (function_->IsJSFunction()) {
640  function_->PrintName(trace_scope_->file());
641  } else {
642  PrintF(trace_scope_->file(),
644  }
645 }
static const char * Kind2String(Kind kind)
Definition: objects.cc:10627
void PrintName(FILE *out=stdout)
Definition: objects.cc:9548

References compiled_code_, function_, v8::internal::Code::kind(), v8::internal::Code::Kind2String(), v8::internal::PrintF(), v8::internal::JSFunction::PrintName(), and trace_scope_.

Referenced by DoComputeOutputFrames().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ SetPlatformCompiledStubRegisters()

void v8::internal::Deoptimizer::SetPlatformCompiledStubRegisters ( FrameDescription output_frame,
CodeStubDescriptor desc 
)
private

Definition at line 103 of file deoptimizer-arm.cc.

104  {
105  ApiFunction function(descriptor->deoptimization_handler());
106  ExternalReference xref(&function, ExternalReference::BUILTIN_CALL, isolate_);
107  intptr_t handler = reinterpret_cast<intptr_t>(xref.address());
108  int params = descriptor->GetHandlerParameterCount();
109  output_frame->SetRegister(r0.code(), params);
110  output_frame->SetRegister(r1.code(), handler);
111 }
const Register r0
const Register r1

References v8::internal::Register::code(), v8::internal::CodeStubDescriptor::deoptimization_handler(), v8::internal::CodeStubDescriptor::GetHandlerParameterCount(), isolate_, v8::internal::r0, v8::internal::r1, and v8::internal::FrameDescription::SetRegister().

Referenced by DoComputeCompiledStubFrame().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ TraceEnabledFor()

bool v8::internal::Deoptimizer::TraceEnabledFor ( BailoutType  deopt_type,
StackFrame::Type  frame_type 
)
static

Definition at line 520 of file deoptimizer.cc.

521  {
522  switch (deopt_type) {
523  case EAGER:
524  case SOFT:
525  case LAZY:
526  case DEBUGGER:
527  return (frame_type == StackFrame::STUB)
528  ? FLAG_trace_stub_failures
529  : FLAG_trace_deopt;
530  }
531  FATAL("Unsupported deopt type");
532  return false;
533 }

References DEBUGGER, EAGER, FATAL, LAZY, SOFT, and v8::internal::STUB.

Referenced by Deoptimizer().

+ Here is the caller graph for this function:

◆ VisitAllOptimizedFunctions()

void v8::internal::Deoptimizer::VisitAllOptimizedFunctions ( Isolate isolate,
OptimizedFunctionVisitor visitor 
)
static

Definition at line 284 of file deoptimizer.cc.

286  {
287  DisallowHeapAllocation no_allocation;
288 
289  // Run through the list of all native contexts.
290  Object* context = isolate->heap()->native_contexts_list();
291  while (!context->IsUndefined()) {
293  context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
294  }
295 }

References v8::internal::Context::cast(), v8::internal::FixedArray::get(), v8::internal::Isolate::heap(), isolate(), v8::internal::Heap::native_contexts_list(), v8::internal::Context::NEXT_CONTEXT_LINK, and VisitAllOptimizedFunctionsForContext().

Referenced by v8::internal::DeoptimizeDependentFunctions(), and v8::internal::EnumerateCompiledFunctions().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ VisitAllOptimizedFunctionsForContext()

void v8::internal::Deoptimizer::VisitAllOptimizedFunctionsForContext ( Context context,
OptimizedFunctionVisitor visitor 
)
staticprivate

Definition at line 240 of file deoptimizer.cc.

241  {
242  DisallowHeapAllocation no_allocation;
243 
244  CHECK(context->IsNativeContext());
245 
246  visitor->EnterContext(context);
247 
248  // Visit the list of optimized functions, removing elements that
249  // no longer refer to optimized code.
250  JSFunction* prev = NULL;
251  Object* element = context->OptimizedFunctionsListHead();
252  while (!element->IsUndefined()) {
253  JSFunction* function = JSFunction::cast(element);
254  Object* next = function->next_function_link();
255  if (function->code()->kind() != Code::OPTIMIZED_FUNCTION ||
256  (visitor->VisitFunction(function),
257  function->code()->kind() != Code::OPTIMIZED_FUNCTION)) {
258  // The function no longer refers to optimized code, or the visitor
259  // changed the code to which it refers to no longer be optimized code.
260  // Remove the function from this list.
261  if (prev != NULL) {
262  prev->set_next_function_link(next);
263  } else {
264  context->SetOptimizedFunctionsListHead(next);
265  }
266  // The visitor should not alter the link directly.
267  CHECK_EQ(function->next_function_link(), next);
268  // Set the next function link to undefined to indicate it is no longer
269  // in the optimized functions list.
270  function->set_next_function_link(context->GetHeap()->undefined_value());
271  } else {
272  // The visitor should not alter the link directly.
273  CHECK_EQ(function->next_function_link(), next);
274  // preserve this element.
275  prev = function;
276  }
277  element = next;
278  }
279 
280  visitor->LeaveContext(context);
281 }

References CHECK, CHECK_EQ, function(), v8::internal::HeapObject::GetHeap(), v8::internal::Context::IsNativeContext(), NULL, v8::internal::Context::OptimizedFunctionsListHead(), and v8::internal::Context::SetOptimizedFunctionsListHead().

Referenced by DeoptimizeMarkedCodeForContext(), and VisitAllOptimizedFunctions().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Friends And Related Function Documentation

◆ DeoptimizedFrameInfo

friend class DeoptimizedFrameInfo
friend

Definition at line 454 of file deoptimizer.h.

Referenced by DebuggerInspectableFrame().

◆ FrameDescription

Member Data Documentation

◆ bailout_id_

unsigned v8::internal::Deoptimizer::bailout_id_
private

Definition at line 408 of file deoptimizer.h.

Referenced by ComputeOutgoingArgumentSize(), and DoComputeOutputFrames().

◆ bailout_type_

◆ compiled_code_

◆ deferred_heap_numbers_

List<HeapNumberMaterializationDescriptor<Address> > v8::internal::Deoptimizer::deferred_heap_numbers_
private

◆ deferred_objects_

◆ deferred_objects_double_values_

List<HeapNumberMaterializationDescriptor<int> > v8::internal::Deoptimizer::deferred_objects_double_values_
private

Definition at line 426 of file deoptimizer.h.

Referenced by AddObjectDoubleValue(), and MaterializeHeapObjects().

◆ deferred_objects_tagged_values_

List<Object*> v8::internal::Deoptimizer::deferred_objects_tagged_values_
private

◆ fp_to_sp_delta_

int v8::internal::Deoptimizer::fp_to_sp_delta_
private

Definition at line 411 of file deoptimizer.h.

Referenced by ComputeInputFrameSize(), and DoComputeOutputFrames().

◆ from_

Address v8::internal::Deoptimizer::from_
private

Definition at line 410 of file deoptimizer.h.

Referenced by FindOptimizedCode().

◆ function_

JSFunction* v8::internal::Deoptimizer::function_
private

◆ has_alignment_padding_

int v8::internal::Deoptimizer::has_alignment_padding_
private

◆ input_

◆ isolate_

◆ jsframe_count_

int v8::internal::Deoptimizer::jsframe_count_
private

◆ jsframe_functions_

List<Handle<JSFunction> > v8::internal::Deoptimizer::jsframe_functions_
private

Definition at line 436 of file deoptimizer.h.

Referenced by ArgumentsObjectFunction(), and MaterializeHeapObjects().

◆ jsframe_has_adapted_arguments_

List<bool> v8::internal::Deoptimizer::jsframe_has_adapted_arguments_
private

Definition at line 437 of file deoptimizer.h.

Referenced by ArgumentsObjectIsAdapted(), and MaterializeHeapObjects().

◆ kBailoutTypesWithCodeEntry

const int v8::internal::Deoptimizer::kBailoutTypesWithCodeEntry = SOFT + 1
static

◆ kMaxNumberOfEntries

const int v8::internal::Deoptimizer::kMaxNumberOfEntries = 16384
staticprivate

◆ kMinNumberOfEntries

const int v8::internal::Deoptimizer::kMinNumberOfEntries = 64
staticprivate

Definition at line 295 of file deoptimizer.h.

Referenced by EnsureCodeForDeoptimizationEntry().

◆ kNotDeoptimizationEntry

const int v8::internal::Deoptimizer::kNotDeoptimizationEntry = -1
static

Definition at line 247 of file deoptimizer.h.

Referenced by GetDeoptimizationId().

◆ materialization_object_index_

int v8::internal::Deoptimizer::materialization_object_index_
private

Definition at line 443 of file deoptimizer.h.

Referenced by MaterializeHeapObjects(), and MaterializeNextHeapObject().

◆ materialization_value_index_

int v8::internal::Deoptimizer::materialization_value_index_
private

◆ materialized_objects_

List<Handle<Object> >* v8::internal::Deoptimizer::materialized_objects_
private

Definition at line 441 of file deoptimizer.h.

Referenced by MaterializeHeapObjects(), and MaterializeNextHeapObject().

◆ materialized_values_

List<Handle<Object> >* v8::internal::Deoptimizer::materialized_values_
private

Definition at line 440 of file deoptimizer.h.

Referenced by MaterializeHeapObjects(), and MaterializeNextValue().

◆ output_

◆ output_count_

◆ prev_materialized_count_

int v8::internal::Deoptimizer::prev_materialized_count_
private

Definition at line 433 of file deoptimizer.h.

Referenced by MaterializeHeapObjects(), and MaterializeNextHeapObject().

◆ previously_materialized_objects_

Handle<FixedArray> v8::internal::Deoptimizer::previously_materialized_objects_
private

Definition at line 432 of file deoptimizer.h.

Referenced by MaterializeHeapObjects(), and MaterializeNextHeapObject().

◆ stack_fp_

Address v8::internal::Deoptimizer::stack_fp_
private

Definition at line 431 of file deoptimizer.h.

Referenced by DoComputeOutputFrames(), and MaterializeHeapObjects().

◆ table_entry_size_

const int v8::internal::Deoptimizer::table_entry_size_ = 8
staticprivate

◆ trace_scope_


The documentation for this class was generated from the following files: