The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / deoptimizer.h @ f230a1cf

History | View | Annotate | Download (29.6 KB)

1
// Copyright 2012 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
#ifndef V8_DEOPTIMIZER_H_
29
#define V8_DEOPTIMIZER_H_
30

    
31
#include "v8.h"
32

    
33
#include "allocation.h"
34
#include "macro-assembler.h"
35
#include "zone-inl.h"
36

    
37

    
38
namespace v8 {
39
namespace internal {
40

    
41

    
42
static inline double read_double_value(Address p) {
43
#ifdef V8_HOST_CAN_READ_UNALIGNED
44
  return Memory::double_at(p);
45
#else  // V8_HOST_CAN_READ_UNALIGNED
46
  // Prevent gcc from using load-double (mips ldc1) on (possibly)
47
  // non-64-bit aligned address.
48
  union conversion {
49
    double d;
50
    uint32_t u[2];
51
  } c;
52
  c.u[0] = *reinterpret_cast<uint32_t*>(p);
53
  c.u[1] = *reinterpret_cast<uint32_t*>(p + 4);
54
  return c.d;
55
#endif  // V8_HOST_CAN_READ_UNALIGNED
56
}
57

    
58

    
59
class FrameDescription;
60
class TranslationIterator;
61
class DeoptimizedFrameInfo;
62

    
63
template<typename T>
64
class HeapNumberMaterializationDescriptor BASE_EMBEDDED {
65
 public:
66
  HeapNumberMaterializationDescriptor(T destination, double value)
67
      : destination_(destination), value_(value) { }
68

    
69
  T destination() const { return destination_; }
70
  double value() const { return value_; }
71

    
72
 private:
73
  T destination_;
74
  double value_;
75
};
76

    
77

    
78
class ObjectMaterializationDescriptor BASE_EMBEDDED {
79
 public:
80
  ObjectMaterializationDescriptor(
81
      Address slot_address, int frame, int length, int duplicate, bool is_args)
82
      : slot_address_(slot_address),
83
        jsframe_index_(frame),
84
        object_length_(length),
85
        duplicate_object_(duplicate),
86
        is_arguments_(is_args) { }
87

    
88
  Address slot_address() const { return slot_address_; }
89
  int jsframe_index() const { return jsframe_index_; }
90
  int object_length() const { return object_length_; }
91
  int duplicate_object() const { return duplicate_object_; }
92
  bool is_arguments() const { return is_arguments_; }
93

    
94
  // Only used for allocated receivers in DoComputeConstructStubFrame.
95
  void patch_slot_address(intptr_t slot) {
96
    slot_address_ = reinterpret_cast<Address>(slot);
97
  }
98

    
99
 private:
100
  Address slot_address_;
101
  int jsframe_index_;
102
  int object_length_;
103
  int duplicate_object_;
104
  bool is_arguments_;
105
};
106

    
107

    
108
class OptimizedFunctionVisitor BASE_EMBEDDED {
109
 public:
110
  virtual ~OptimizedFunctionVisitor() {}
111

    
112
  // Function which is called before iteration of any optimized functions
113
  // from given native context.
114
  virtual void EnterContext(Context* context) = 0;
115

    
116
  virtual void VisitFunction(JSFunction* function) = 0;
117

    
118
  // Function which is called after iteration of all optimized functions
119
  // from given native context.
120
  virtual void LeaveContext(Context* context) = 0;
121
};
122

    
123

    
124
class Deoptimizer : public Malloced {
125
 public:
126
  enum BailoutType {
127
    EAGER,
128
    LAZY,
129
    SOFT,
130
    // This last bailout type is not really a bailout, but used by the
131
    // debugger to deoptimize stack frames to allow inspection.
132
    DEBUGGER
133
  };
134

    
135
  static const int kBailoutTypesWithCodeEntry = SOFT + 1;
136

    
137
  struct JumpTableEntry {
138
    inline JumpTableEntry(Address entry,
139
                          Deoptimizer::BailoutType type,
140
                          bool frame)
141
        : label(),
142
          address(entry),
143
          bailout_type(type),
144
          needs_frame(frame) { }
145
    Label label;
146
    Address address;
147
    Deoptimizer::BailoutType bailout_type;
148
    bool needs_frame;
149
  };
150

    
151
  static bool TraceEnabledFor(BailoutType deopt_type,
152
                              StackFrame::Type frame_type);
153
  static const char* MessageFor(BailoutType type);
154

    
155
  int output_count() const { return output_count_; }
156

    
157
  Handle<JSFunction> function() const { return Handle<JSFunction>(function_); }
158
  Handle<Code> compiled_code() const { return Handle<Code>(compiled_code_); }
159
  BailoutType bailout_type() const { return bailout_type_; }
160

    
161
  // Number of created JS frames. Not all created frames are necessarily JS.
162
  int jsframe_count() const { return jsframe_count_; }
163

    
164
  static Deoptimizer* New(JSFunction* function,
165
                          BailoutType type,
166
                          unsigned bailout_id,
167
                          Address from,
168
                          int fp_to_sp_delta,
169
                          Isolate* isolate);
170
  static Deoptimizer* Grab(Isolate* isolate);
171

    
172
#ifdef ENABLE_DEBUGGER_SUPPORT
173
  // The returned object with information on the optimized frame needs to be
174
  // freed before another one can be generated.
175
  static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame,
176
                                                        int jsframe_index,
177
                                                        Isolate* isolate);
178
  static void DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
179
                                             Isolate* isolate);
180
#endif
181

    
182
  // Makes sure that there is enough room in the relocation
183
  // information of a code object to perform lazy deoptimization
184
  // patching. If there is not enough room a new relocation
185
  // information object is allocated and comments are added until it
186
  // is big enough.
187
  static void EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code);
188

    
189
  // Deoptimize the function now. Its current optimized code will never be run
190
  // again and any activations of the optimized code will get deoptimized when
191
  // execution returns.
192
  static void DeoptimizeFunction(JSFunction* function);
193

    
194
  // Deoptimize all code in the given isolate.
195
  static void DeoptimizeAll(Isolate* isolate);
196

    
197
  // Deoptimize code associated with the given global object.
198
  static void DeoptimizeGlobalObject(JSObject* object);
199

    
200
  // Deoptimizes all optimized code that has been previously marked
201
  // (via code->set_marked_for_deoptimization) and unlinks all functions that
202
  // refer to that code.
203
  static void DeoptimizeMarkedCode(Isolate* isolate);
204

    
205
  // Visit all the known optimized functions in a given isolate.
206
  static void VisitAllOptimizedFunctions(
207
      Isolate* isolate, OptimizedFunctionVisitor* visitor);
208

    
209
  // The size in bytes of the code required at a lazy deopt patch site.
210
  static int patch_size();
211

    
212
  ~Deoptimizer();
213

    
214
  void MaterializeHeapObjects(JavaScriptFrameIterator* it);
215
#ifdef ENABLE_DEBUGGER_SUPPORT
216
  void MaterializeHeapNumbersForDebuggerInspectableFrame(
217
      Address parameters_top,
218
      uint32_t parameters_size,
219
      Address expressions_top,
220
      uint32_t expressions_size,
221
      DeoptimizedFrameInfo* info);
222
#endif
223

    
224
  static void ComputeOutputFrames(Deoptimizer* deoptimizer);
225

    
226

    
227
  enum GetEntryMode {
228
    CALCULATE_ENTRY_ADDRESS,
229
    ENSURE_ENTRY_CODE
230
  };
231

    
232

    
233
  static Address GetDeoptimizationEntry(
234
      Isolate* isolate,
235
      int id,
236
      BailoutType type,
237
      GetEntryMode mode = ENSURE_ENTRY_CODE);
238
  static int GetDeoptimizationId(Isolate* isolate,
239
                                 Address addr,
240
                                 BailoutType type);
241
  static int GetOutputInfo(DeoptimizationOutputData* data,
242
                           BailoutId node_id,
243
                           SharedFunctionInfo* shared);
244

    
245
  // Code generation support.
246
  static int input_offset() { return OFFSET_OF(Deoptimizer, input_); }
247
  static int output_count_offset() {
248
    return OFFSET_OF(Deoptimizer, output_count_);
249
  }
250
  static int output_offset() { return OFFSET_OF(Deoptimizer, output_); }
251

    
252
  static int has_alignment_padding_offset() {
253
    return OFFSET_OF(Deoptimizer, has_alignment_padding_);
254
  }
255

    
256
  static int GetDeoptimizedCodeCount(Isolate* isolate);
257

    
258
  static const int kNotDeoptimizationEntry = -1;
259

    
260
  // Generators for the deoptimization entry code.
261
  class EntryGenerator BASE_EMBEDDED {
262
   public:
263
    EntryGenerator(MacroAssembler* masm, BailoutType type)
264
        : masm_(masm), type_(type) { }
265
    virtual ~EntryGenerator() { }
266

    
267
    void Generate();
268

    
269
   protected:
270
    MacroAssembler* masm() const { return masm_; }
271
    BailoutType type() const { return type_; }
272
    Isolate* isolate() const { return masm_->isolate(); }
273

    
274
    virtual void GeneratePrologue() { }
275

    
276
   private:
277
    MacroAssembler* masm_;
278
    Deoptimizer::BailoutType type_;
279
  };
280

    
281
  class TableEntryGenerator : public EntryGenerator {
282
   public:
283
    TableEntryGenerator(MacroAssembler* masm, BailoutType type,  int count)
284
        : EntryGenerator(masm, type), count_(count) { }
285

    
286
   protected:
287
    virtual void GeneratePrologue();
288

    
289
   private:
290
    int count() const { return count_; }
291

    
292
    int count_;
293
  };
294

    
295
  int ConvertJSFrameIndexToFrameIndex(int jsframe_index);
296

    
297
  static size_t GetMaxDeoptTableSize();
298

    
299
  static void EnsureCodeForDeoptimizationEntry(Isolate* isolate,
300
                                               BailoutType type,
301
                                               int max_entry_id);
302

    
303
  Isolate* isolate() const { return isolate_; }
304

    
305
 private:
306
  static const int kMinNumberOfEntries = 64;
307
  static const int kMaxNumberOfEntries = 16384;
308

    
309
  Deoptimizer(Isolate* isolate,
310
              JSFunction* function,
311
              BailoutType type,
312
              unsigned bailout_id,
313
              Address from,
314
              int fp_to_sp_delta,
315
              Code* optimized_code);
316
  Code* FindOptimizedCode(JSFunction* function, Code* optimized_code);
317
  void PrintFunctionName();
318
  void DeleteFrameDescriptions();
319

    
320
  void DoComputeOutputFrames();
321
  void DoComputeJSFrame(TranslationIterator* iterator, int frame_index);
322
  void DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
323
                                      int frame_index);
324
  void DoComputeConstructStubFrame(TranslationIterator* iterator,
325
                                   int frame_index);
326
  void DoComputeAccessorStubFrame(TranslationIterator* iterator,
327
                                  int frame_index,
328
                                  bool is_setter_stub_frame);
329
  void DoComputeCompiledStubFrame(TranslationIterator* iterator,
330
                                  int frame_index);
331

    
332
  void DoTranslateObject(TranslationIterator* iterator,
333
                         int object_index,
334
                         int field_index);
335

    
336
  enum DeoptimizerTranslatedValueType {
337
    TRANSLATED_VALUE_IS_NATIVE,
338
    TRANSLATED_VALUE_IS_TAGGED
339
  };
340

    
341
  void DoTranslateCommand(TranslationIterator* iterator,
342
      int frame_index,
343
      unsigned output_offset,
344
      DeoptimizerTranslatedValueType value_type = TRANSLATED_VALUE_IS_TAGGED);
345

    
346
  unsigned ComputeInputFrameSize() const;
347
  unsigned ComputeFixedSize(JSFunction* function) const;
348

    
349
  unsigned ComputeIncomingArgumentSize(JSFunction* function) const;
350
  unsigned ComputeOutgoingArgumentSize() const;
351

    
352
  Object* ComputeLiteral(int index) const;
353

    
354
  void AddObjectStart(intptr_t slot_address, int argc, bool is_arguments);
355
  void AddObjectDuplication(intptr_t slot, int object_index);
356
  void AddObjectTaggedValue(intptr_t value);
357
  void AddObjectDoubleValue(double value);
358
  void AddDoubleValue(intptr_t slot_address, double value);
359

    
360
  bool ArgumentsObjectIsAdapted(int object_index) {
361
    ObjectMaterializationDescriptor desc = deferred_objects_.at(object_index);
362
    int reverse_jsframe_index = jsframe_count_ - desc.jsframe_index() - 1;
363
    return jsframe_has_adapted_arguments_[reverse_jsframe_index];
364
  }
365

    
366
  Handle<JSFunction> ArgumentsObjectFunction(int object_index) {
367
    ObjectMaterializationDescriptor desc = deferred_objects_.at(object_index);
368
    int reverse_jsframe_index = jsframe_count_ - desc.jsframe_index() - 1;
369
    return jsframe_functions_[reverse_jsframe_index];
370
  }
371

    
372
  // Helper function for heap object materialization.
373
  Handle<Object> MaterializeNextHeapObject();
374
  Handle<Object> MaterializeNextValue();
375

    
376
  static void GenerateDeoptimizationEntries(
377
      MacroAssembler* masm, int count, BailoutType type);
378

    
379
  // Marks all the code in the given context for deoptimization.
380
  static void MarkAllCodeForContext(Context* native_context);
381

    
382
  // Visit all the known optimized functions in a given context.
383
  static void VisitAllOptimizedFunctionsForContext(
384
      Context* context, OptimizedFunctionVisitor* visitor);
385

    
386
  // Deoptimizes all code marked in the given context.
387
  static void DeoptimizeMarkedCodeForContext(Context* native_context);
388

    
389
  // Patch the given code so that it will deoptimize itself.
390
  static void PatchCodeForDeoptimization(Isolate* isolate, Code* code);
391

    
392
  // Searches the list of known deoptimizing code for a Code object
393
  // containing the given address (which is supposedly faster than
394
  // searching all code objects).
395
  Code* FindDeoptimizingCode(Address addr);
396

    
397
  // Fill the input from from a JavaScript frame. This is used when
398
  // the debugger needs to inspect an optimized frame. For normal
399
  // deoptimizations the input frame is filled in generated code.
400
  void FillInputFrame(Address tos, JavaScriptFrame* frame);
401

    
402
  // Fill the given output frame's registers to contain the failure handler
403
  // address and the number of parameters for a stub failure trampoline.
404
  void SetPlatformCompiledStubRegisters(FrameDescription* output_frame,
405
                                        CodeStubInterfaceDescriptor* desc);
406

    
407
  // Fill the given output frame's double registers with the original values
408
  // from the input frame's double registers.
409
  void CopyDoubleRegisters(FrameDescription* output_frame);
410

    
411
  // Determines whether the input frame contains alignment padding by looking
412
  // at the dynamic alignment state slot inside the frame.
413
  bool HasAlignmentPadding(JSFunction* function);
414

    
415
  Isolate* isolate_;
416
  JSFunction* function_;
417
  Code* compiled_code_;
418
  unsigned bailout_id_;
419
  BailoutType bailout_type_;
420
  Address from_;
421
  int fp_to_sp_delta_;
422
  int has_alignment_padding_;
423

    
424
  // Input frame description.
425
  FrameDescription* input_;
426
  // Number of output frames.
427
  int output_count_;
428
  // Number of output js frames.
429
  int jsframe_count_;
430
  // Array of output frame descriptions.
431
  FrameDescription** output_;
432

    
433
  // Deferred values to be materialized.
434
  List<Object*> deferred_objects_tagged_values_;
435
  List<HeapNumberMaterializationDescriptor<int> >
436
      deferred_objects_double_values_;
437
  List<ObjectMaterializationDescriptor> deferred_objects_;
438
  List<HeapNumberMaterializationDescriptor<Address> > deferred_heap_numbers_;
439

    
440
  // Output frame information. Only used during heap object materialization.
441
  List<Handle<JSFunction> > jsframe_functions_;
442
  List<bool> jsframe_has_adapted_arguments_;
443

    
444
  // Materialized objects. Only used during heap object materialization.
445
  List<Handle<Object> >* materialized_values_;
446
  List<Handle<Object> >* materialized_objects_;
447
  int materialization_value_index_;
448
  int materialization_object_index_;
449

    
450
#ifdef DEBUG
451
  DisallowHeapAllocation* disallow_heap_allocation_;
452
#endif  // DEBUG
453

    
454
  bool trace_;
455

    
456
  static const int table_entry_size_;
457

    
458
  friend class FrameDescription;
459
  friend class DeoptimizedFrameInfo;
460
};
461

    
462

    
463
class FrameDescription {
464
 public:
465
  FrameDescription(uint32_t frame_size,
466
                   JSFunction* function);
467

    
468
  void* operator new(size_t size, uint32_t frame_size) {
469
    // Subtracts kPointerSize, as the member frame_content_ already supplies
470
    // the first element of the area to store the frame.
471
    return malloc(size + frame_size - kPointerSize);
472
  }
473

    
474
  void operator delete(void* pointer, uint32_t frame_size) {
475
    free(pointer);
476
  }
477

    
478
  void operator delete(void* description) {
479
    free(description);
480
  }
481

    
482
  uint32_t GetFrameSize() const {
483
    ASSERT(static_cast<uint32_t>(frame_size_) == frame_size_);
484
    return static_cast<uint32_t>(frame_size_);
485
  }
486

    
487
  JSFunction* GetFunction() const { return function_; }
488

    
489
  unsigned GetOffsetFromSlotIndex(int slot_index);
490

    
491
  intptr_t GetFrameSlot(unsigned offset) {
492
    return *GetFrameSlotPointer(offset);
493
  }
494

    
495
  double GetDoubleFrameSlot(unsigned offset) {
496
    intptr_t* ptr = GetFrameSlotPointer(offset);
497
    return read_double_value(reinterpret_cast<Address>(ptr));
498
  }
499

    
500
  void SetFrameSlot(unsigned offset, intptr_t value) {
501
    *GetFrameSlotPointer(offset) = value;
502
  }
503

    
504
  void SetCallerPc(unsigned offset, intptr_t value);
505

    
506
  void SetCallerFp(unsigned offset, intptr_t value);
507

    
508
  intptr_t GetRegister(unsigned n) const {
509
#if DEBUG
510
    // This convoluted ASSERT is needed to work around a gcc problem that
511
    // improperly detects an array bounds overflow in optimized debug builds
512
    // when using a plain ASSERT.
513
    if (n >= ARRAY_SIZE(registers_)) {
514
      ASSERT(false);
515
      return 0;
516
    }
517
#endif
518
    return registers_[n];
519
  }
520

    
521
  double GetDoubleRegister(unsigned n) const {
522
    ASSERT(n < ARRAY_SIZE(double_registers_));
523
    return double_registers_[n];
524
  }
525

    
526
  void SetRegister(unsigned n, intptr_t value) {
527
    ASSERT(n < ARRAY_SIZE(registers_));
528
    registers_[n] = value;
529
  }
530

    
531
  void SetDoubleRegister(unsigned n, double value) {
532
    ASSERT(n < ARRAY_SIZE(double_registers_));
533
    double_registers_[n] = value;
534
  }
535

    
536
  intptr_t GetTop() const { return top_; }
537
  void SetTop(intptr_t top) { top_ = top; }
538

    
539
  intptr_t GetPc() const { return pc_; }
540
  void SetPc(intptr_t pc) { pc_ = pc; }
541

    
542
  intptr_t GetFp() const { return fp_; }
543
  void SetFp(intptr_t fp) { fp_ = fp; }
544

    
545
  intptr_t GetContext() const { return context_; }
546
  void SetContext(intptr_t context) { context_ = context; }
547

    
548
  Smi* GetState() const { return state_; }
549
  void SetState(Smi* state) { state_ = state; }
550

    
551
  void SetContinuation(intptr_t pc) { continuation_ = pc; }
552

    
553
  StackFrame::Type GetFrameType() const { return type_; }
554
  void SetFrameType(StackFrame::Type type) { type_ = type; }
555

    
556
  // Get the incoming arguments count.
557
  int ComputeParametersCount();
558

    
559
  // Get a parameter value for an unoptimized frame.
560
  Object* GetParameter(int index);
561

    
562
  // Get the expression stack height for a unoptimized frame.
563
  unsigned GetExpressionCount();
564

    
565
  // Get the expression stack value for an unoptimized frame.
566
  Object* GetExpression(int index);
567

    
568
  static int registers_offset() {
569
    return OFFSET_OF(FrameDescription, registers_);
570
  }
571

    
572
  static int double_registers_offset() {
573
    return OFFSET_OF(FrameDescription, double_registers_);
574
  }
575

    
576
  static int frame_size_offset() {
577
    return OFFSET_OF(FrameDescription, frame_size_);
578
  }
579

    
580
  static int pc_offset() {
581
    return OFFSET_OF(FrameDescription, pc_);
582
  }
583

    
584
  static int state_offset() {
585
    return OFFSET_OF(FrameDescription, state_);
586
  }
587

    
588
  static int continuation_offset() {
589
    return OFFSET_OF(FrameDescription, continuation_);
590
  }
591

    
592
  static int frame_content_offset() {
593
    return OFFSET_OF(FrameDescription, frame_content_);
594
  }
595

    
596
 private:
597
  static const uint32_t kZapUint32 = 0xbeeddead;
598

    
599
  // Frame_size_ must hold a uint32_t value.  It is only a uintptr_t to
600
  // keep the variable-size array frame_content_ of type intptr_t at
601
  // the end of the structure aligned.
602
  uintptr_t frame_size_;  // Number of bytes.
603
  JSFunction* function_;
604
  intptr_t registers_[Register::kNumRegisters];
605
  double double_registers_[DoubleRegister::kMaxNumRegisters];
606
  intptr_t top_;
607
  intptr_t pc_;
608
  intptr_t fp_;
609
  intptr_t context_;
610
  StackFrame::Type type_;
611
  Smi* state_;
612

    
613
  // Continuation is the PC where the execution continues after
614
  // deoptimizing.
615
  intptr_t continuation_;
616

    
617
  // This must be at the end of the object as the object is allocated larger
618
  // than it's definition indicate to extend this array.
619
  intptr_t frame_content_[1];
620

    
621
  intptr_t* GetFrameSlotPointer(unsigned offset) {
622
    ASSERT(offset < frame_size_);
623
    return reinterpret_cast<intptr_t*>(
624
        reinterpret_cast<Address>(this) + frame_content_offset() + offset);
625
  }
626

    
627
  int ComputeFixedSize();
628
};
629

    
630

    
631
class DeoptimizerData {
632
 public:
633
  explicit DeoptimizerData(MemoryAllocator* allocator);
634
  ~DeoptimizerData();
635

    
636
#ifdef ENABLE_DEBUGGER_SUPPORT
637
  void Iterate(ObjectVisitor* v);
638
#endif
639

    
640
 private:
641
  MemoryAllocator* allocator_;
642
  int deopt_entry_code_entries_[Deoptimizer::kBailoutTypesWithCodeEntry];
643
  MemoryChunk* deopt_entry_code_[Deoptimizer::kBailoutTypesWithCodeEntry];
644

    
645
#ifdef ENABLE_DEBUGGER_SUPPORT
646
  DeoptimizedFrameInfo* deoptimized_frame_info_;
647
#endif
648

    
649
  Deoptimizer* current_;
650

    
651
  friend class Deoptimizer;
652

    
653
  DISALLOW_COPY_AND_ASSIGN(DeoptimizerData);
654
};
655

    
656

    
657
class TranslationBuffer BASE_EMBEDDED {
658
 public:
659
  explicit TranslationBuffer(Zone* zone) : contents_(256, zone) { }
660

    
661
  int CurrentIndex() const { return contents_.length(); }
662
  void Add(int32_t value, Zone* zone);
663

    
664
  Handle<ByteArray> CreateByteArray(Factory* factory);
665

    
666
 private:
667
  ZoneList<uint8_t> contents_;
668
};
669

    
670

    
671
class TranslationIterator BASE_EMBEDDED {
672
 public:
673
  TranslationIterator(ByteArray* buffer, int index)
674
      : buffer_(buffer), index_(index) {
675
    ASSERT(index >= 0 && index < buffer->length());
676
  }
677

    
678
  int32_t Next();
679

    
680
  bool HasNext() const { return index_ < buffer_->length(); }
681

    
682
  void Skip(int n) {
683
    for (int i = 0; i < n; i++) Next();
684
  }
685

    
686
 private:
687
  ByteArray* buffer_;
688
  int index_;
689
};
690

    
691

    
692
#define TRANSLATION_OPCODE_LIST(V)                                             \
693
  V(BEGIN)                                                                     \
694
  V(JS_FRAME)                                                                  \
695
  V(CONSTRUCT_STUB_FRAME)                                                      \
696
  V(GETTER_STUB_FRAME)                                                         \
697
  V(SETTER_STUB_FRAME)                                                         \
698
  V(ARGUMENTS_ADAPTOR_FRAME)                                                   \
699
  V(COMPILED_STUB_FRAME)                                                       \
700
  V(DUPLICATED_OBJECT)                                                         \
701
  V(ARGUMENTS_OBJECT)                                                          \
702
  V(CAPTURED_OBJECT)                                                           \
703
  V(REGISTER)                                                                  \
704
  V(INT32_REGISTER)                                                            \
705
  V(UINT32_REGISTER)                                                           \
706
  V(DOUBLE_REGISTER)                                                           \
707
  V(STACK_SLOT)                                                                \
708
  V(INT32_STACK_SLOT)                                                          \
709
  V(UINT32_STACK_SLOT)                                                         \
710
  V(DOUBLE_STACK_SLOT)                                                         \
711
  V(LITERAL)
712

    
713

    
714
class Translation BASE_EMBEDDED {
715
 public:
716
#define DECLARE_TRANSLATION_OPCODE_ENUM(item) item,
717
  enum Opcode {
718
    TRANSLATION_OPCODE_LIST(DECLARE_TRANSLATION_OPCODE_ENUM)
719
    LAST = LITERAL
720
  };
721
#undef DECLARE_TRANSLATION_OPCODE_ENUM
722

    
723
  Translation(TranslationBuffer* buffer, int frame_count, int jsframe_count,
724
              Zone* zone)
725
      : buffer_(buffer),
726
        index_(buffer->CurrentIndex()),
727
        zone_(zone) {
728
    buffer_->Add(BEGIN, zone);
729
    buffer_->Add(frame_count, zone);
730
    buffer_->Add(jsframe_count, zone);
731
  }
732

    
733
  int index() const { return index_; }
734

    
735
  // Commands.
736
  void BeginJSFrame(BailoutId node_id, int literal_id, unsigned height);
737
  void BeginCompiledStubFrame();
738
  void BeginArgumentsAdaptorFrame(int literal_id, unsigned height);
739
  void BeginConstructStubFrame(int literal_id, unsigned height);
740
  void BeginGetterStubFrame(int literal_id);
741
  void BeginSetterStubFrame(int literal_id);
742
  void BeginArgumentsObject(int args_length);
743
  void BeginCapturedObject(int length);
744
  void DuplicateObject(int object_index);
745
  void StoreRegister(Register reg);
746
  void StoreInt32Register(Register reg);
747
  void StoreUint32Register(Register reg);
748
  void StoreDoubleRegister(DoubleRegister reg);
749
  void StoreStackSlot(int index);
750
  void StoreInt32StackSlot(int index);
751
  void StoreUint32StackSlot(int index);
752
  void StoreDoubleStackSlot(int index);
753
  void StoreLiteral(int literal_id);
754
  void StoreArgumentsObject(bool args_known, int args_index, int args_length);
755

    
756
  Zone* zone() const { return zone_; }
757

    
758
  static int NumberOfOperandsFor(Opcode opcode);
759

    
760
#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
761
  static const char* StringFor(Opcode opcode);
762
#endif
763

    
764
  // A literal id which refers to the JSFunction itself.
765
  static const int kSelfLiteralId = -239;
766

    
767
 private:
768
  TranslationBuffer* buffer_;
769
  int index_;
770
  Zone* zone_;
771
};
772

    
773

    
774
class SlotRef BASE_EMBEDDED {
775
 public:
776
  enum SlotRepresentation {
777
    UNKNOWN,
778
    TAGGED,
779
    INT32,
780
    UINT32,
781
    DOUBLE,
782
    LITERAL
783
  };
784

    
785
  SlotRef()
786
      : addr_(NULL), representation_(UNKNOWN) { }
787

    
788
  SlotRef(Address addr, SlotRepresentation representation)
789
      : addr_(addr), representation_(representation) { }
790

    
791
  SlotRef(Isolate* isolate, Object* literal)
792
      : literal_(literal, isolate), representation_(LITERAL) { }
793

    
794
  Handle<Object> GetValue(Isolate* isolate) {
795
    switch (representation_) {
796
      case TAGGED:
797
        return Handle<Object>(Memory::Object_at(addr_), isolate);
798

    
799
      case INT32: {
800
        int value = Memory::int32_at(addr_);
801
        if (Smi::IsValid(value)) {
802
          return Handle<Object>(Smi::FromInt(value), isolate);
803
        } else {
804
          return isolate->factory()->NewNumberFromInt(value);
805
        }
806
      }
807

    
808
      case UINT32: {
809
        uint32_t value = Memory::uint32_at(addr_);
810
        if (value <= static_cast<uint32_t>(Smi::kMaxValue)) {
811
          return Handle<Object>(Smi::FromInt(static_cast<int>(value)), isolate);
812
        } else {
813
          return isolate->factory()->NewNumber(static_cast<double>(value));
814
        }
815
      }
816

    
817
      case DOUBLE: {
818
        double value = read_double_value(addr_);
819
        return isolate->factory()->NewNumber(value);
820
      }
821

    
822
      case LITERAL:
823
        return literal_;
824

    
825
      default:
826
        UNREACHABLE();
827
        return Handle<Object>::null();
828
    }
829
  }
830

    
831
  static Vector<SlotRef> ComputeSlotMappingForArguments(
832
      JavaScriptFrame* frame,
833
      int inlined_frame_index,
834
      int formal_parameter_count);
835

    
836
 private:
837
  Address addr_;
838
  Handle<Object> literal_;
839
  SlotRepresentation representation_;
840

    
841
  static Address SlotAddress(JavaScriptFrame* frame, int slot_index) {
842
    if (slot_index >= 0) {
843
      const int offset = JavaScriptFrameConstants::kLocal0Offset;
844
      return frame->fp() + offset - (slot_index * kPointerSize);
845
    } else {
846
      const int offset = JavaScriptFrameConstants::kLastParameterOffset;
847
      return frame->fp() + offset - ((slot_index + 1) * kPointerSize);
848
    }
849
  }
850

    
851
  static SlotRef ComputeSlotForNextArgument(TranslationIterator* iterator,
852
                                            DeoptimizationInputData* data,
853
                                            JavaScriptFrame* frame);
854

    
855
  static void ComputeSlotsForArguments(
856
      Vector<SlotRef>* args_slots,
857
      TranslationIterator* iterator,
858
      DeoptimizationInputData* data,
859
      JavaScriptFrame* frame);
860
};
861

    
862

    
863
#ifdef ENABLE_DEBUGGER_SUPPORT
864
// Class used to represent an unoptimized frame when the debugger
865
// needs to inspect a frame that is part of an optimized frame. The
866
// internally used FrameDescription objects are not GC safe so for use
867
// by the debugger frame information is copied to an object of this type.
868
// Represents parameters in unadapted form so their number might mismatch
869
// formal parameter count.
870
class DeoptimizedFrameInfo : public Malloced {
871
 public:
872
  DeoptimizedFrameInfo(Deoptimizer* deoptimizer,
873
                       int frame_index,
874
                       bool has_arguments_adaptor,
875
                       bool has_construct_stub);
876
  virtual ~DeoptimizedFrameInfo();
877

    
878
  // GC support.
879
  void Iterate(ObjectVisitor* v);
880

    
881
  // Return the number of incoming arguments.
882
  int parameters_count() { return parameters_count_; }
883

    
884
  // Return the height of the expression stack.
885
  int expression_count() { return expression_count_; }
886

    
887
  // Get the frame function.
888
  JSFunction* GetFunction() {
889
    return function_;
890
  }
891

    
892
  // Check if this frame is preceded by construct stub frame.  The bottom-most
893
  // inlined frame might still be called by an uninlined construct stub.
894
  bool HasConstructStub() {
895
    return has_construct_stub_;
896
  }
897

    
898
  // Get an incoming argument.
899
  Object* GetParameter(int index) {
900
    ASSERT(0 <= index && index < parameters_count());
901
    return parameters_[index];
902
  }
903

    
904
  // Get an expression from the expression stack.
905
  Object* GetExpression(int index) {
906
    ASSERT(0 <= index && index < expression_count());
907
    return expression_stack_[index];
908
  }
909

    
910
  int GetSourcePosition() {
911
    return source_position_;
912
  }
913

    
914
 private:
915
  // Set an incoming argument.
916
  void SetParameter(int index, Object* obj) {
917
    ASSERT(0 <= index && index < parameters_count());
918
    parameters_[index] = obj;
919
  }
920

    
921
  // Set an expression on the expression stack.
922
  void SetExpression(int index, Object* obj) {
923
    ASSERT(0 <= index && index < expression_count());
924
    expression_stack_[index] = obj;
925
  }
926

    
927
  JSFunction* function_;
928
  bool has_construct_stub_;
929
  int parameters_count_;
930
  int expression_count_;
931
  Object** parameters_;
932
  Object** expression_stack_;
933
  int source_position_;
934

    
935
  friend class Deoptimizer;
936
};
937
#endif
938

    
939
} }  // namespace v8::internal
940

    
941
#endif  // V8_DEOPTIMIZER_H_