OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 23 matching lines...) Expand all Loading... | |
34 #include "macro-assembler.h" | 34 #include "macro-assembler.h" |
35 #include "zone-inl.h" | 35 #include "zone-inl.h" |
36 | 36 |
37 | 37 |
38 namespace v8 { | 38 namespace v8 { |
39 namespace internal { | 39 namespace internal { |
40 | 40 |
41 class FrameDescription; | 41 class FrameDescription; |
42 class TranslationIterator; | 42 class TranslationIterator; |
43 class DeoptimizingCodeListNode; | 43 class DeoptimizingCodeListNode; |
44 | 44 class DeoptimizedFrameInfo; |
45 | 45 |
46 class HeapNumberMaterializationDescriptor BASE_EMBEDDED { | 46 class HeapNumberMaterializationDescriptor BASE_EMBEDDED { |
47 public: | 47 public: |
48 HeapNumberMaterializationDescriptor(Address slot_address, double val) | 48 HeapNumberMaterializationDescriptor(Address slot_address, double val) |
49 : slot_address_(slot_address), val_(val) { } | 49 : slot_address_(slot_address), val_(val) { } |
50 | 50 |
51 Address slot_address() const { return slot_address_; } | 51 Address slot_address() const { return slot_address_; } |
52 double value() const { return val_; } | 52 double value() const { return val_; } |
53 | 53 |
54 private: | 54 private: |
(...skipping 19 matching lines...) Expand all Loading... | |
74 | 74 |
75 | 75 |
76 class Deoptimizer; | 76 class Deoptimizer; |
77 | 77 |
78 | 78 |
79 class DeoptimizerData { | 79 class DeoptimizerData { |
80 public: | 80 public: |
81 DeoptimizerData(); | 81 DeoptimizerData(); |
82 ~DeoptimizerData(); | 82 ~DeoptimizerData(); |
83 | 83 |
84 #ifdef ENABLE_DEBUGGER_SUPPORT | |
85 void Iterate(ObjectVisitor* v); | |
86 #endif | |
87 | |
84 private: | 88 private: |
85 LargeObjectChunk* eager_deoptimization_entry_code_; | 89 LargeObjectChunk* eager_deoptimization_entry_code_; |
86 LargeObjectChunk* lazy_deoptimization_entry_code_; | 90 LargeObjectChunk* lazy_deoptimization_entry_code_; |
87 Deoptimizer* current_; | 91 Deoptimizer* current_; |
88 | 92 |
93 #ifdef ENABLE_DEBUGGER_SUPPORT | |
94 DeoptimizedFrameInfo* deoptimized_frame_info_; | |
95 #endif | |
96 | |
89 // List of deoptimized code which still have references from active stack | 97 // List of deoptimized code which still have references from active stack |
90 // frames. These code objects are needed by the deoptimizer when deoptimizing | 98 // frames. These code objects are needed by the deoptimizer when deoptimizing |
91 // a frame for which the code object for the function function has been | 99 // a frame for which the code object for the function function has been |
92 // changed from the code present when deoptimizing was done. | 100 // changed from the code present when deoptimizing was done. |
93 DeoptimizingCodeListNode* deoptimizing_code_list_; | 101 DeoptimizingCodeListNode* deoptimizing_code_list_; |
94 | 102 |
95 friend class Deoptimizer; | 103 friend class Deoptimizer; |
96 | 104 |
97 DISALLOW_COPY_AND_ASSIGN(DeoptimizerData); | 105 DISALLOW_COPY_AND_ASSIGN(DeoptimizerData); |
98 }; | 106 }; |
99 | 107 |
100 | 108 |
101 class Deoptimizer : public Malloced { | 109 class Deoptimizer : public Malloced { |
102 public: | 110 public: |
103 enum BailoutType { | 111 enum BailoutType { |
104 EAGER, | 112 EAGER, |
105 LAZY, | 113 LAZY, |
106 OSR | 114 OSR, |
115 // This last bailout type is not really a bailout, but used by the | |
116 // debugger to deoptimize stack frames to allow inspection. | |
117 DEBUGGER | |
107 }; | 118 }; |
108 | 119 |
109 int output_count() const { return output_count_; } | 120 int output_count() const { return output_count_; } |
110 | 121 |
111 static Deoptimizer* New(JSFunction* function, | 122 static Deoptimizer* New(JSFunction* function, |
112 BailoutType type, | 123 BailoutType type, |
113 unsigned bailout_id, | 124 unsigned bailout_id, |
114 Address from, | 125 Address from, |
115 int fp_to_sp_delta, | 126 int fp_to_sp_delta, |
116 Isolate* isolate); | 127 Isolate* isolate); |
117 static Deoptimizer* Grab(Isolate* isolate); | 128 static Deoptimizer* Grab(Isolate* isolate); |
118 | 129 |
130 #ifdef ENABLE_DEBUGGER_SUPPORT | |
131 // The returned object with information on the optimized frame needs to be | |
132 // freed before another one can be generated. | |
133 static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame, | |
134 int frame_index, | |
135 Isolate* isolate); | |
136 static void DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, | |
137 Isolate* isolate); | |
138 #endif | |
139 | |
119 // Makes sure that there is enough room in the relocation | 140 // Makes sure that there is enough room in the relocation |
120 // information of a code object to perform lazy deoptimization | 141 // information of a code object to perform lazy deoptimization |
121 // patching. If there is not enough room a new relocation | 142 // patching. If there is not enough room a new relocation |
122 // information object is allocated and comments are added until it | 143 // information object is allocated and comments are added until it |
123 // is big enough. | 144 // is big enough. |
124 static void EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code); | 145 static void EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code); |
125 | 146 |
126 // Deoptimize the function now. Its current optimized code will never be run | 147 // Deoptimize the function now. Its current optimized code will never be run |
127 // again and any activations of the optimized code will get deoptimized when | 148 // again and any activations of the optimized code will get deoptimized when |
128 // execution returns. | 149 // execution returns. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
164 | 185 |
165 // Change all patched stack guard checks in the unoptimized code | 186 // Change all patched stack guard checks in the unoptimized code |
166 // back to a normal stack guard check. | 187 // back to a normal stack guard check. |
167 static void RevertStackCheckCodeAt(Address pc_after, | 188 static void RevertStackCheckCodeAt(Address pc_after, |
168 Code* check_code, | 189 Code* check_code, |
169 Code* replacement_code); | 190 Code* replacement_code); |
170 | 191 |
171 ~Deoptimizer(); | 192 ~Deoptimizer(); |
172 | 193 |
173 void MaterializeHeapNumbers(); | 194 void MaterializeHeapNumbers(); |
195 void MaterializeHeapNumbersForDebuggerInspectableFrame( | |
fschneider
2011/06/29 10:47:35
Maybe add
#ifdef ENABLE_DEBUGGER_SUPPORT
here t
Søren Thygesen Gjesse
2011/06/29 12:42:10
Done.
| |
196 Address top, intptr_t size, DeoptimizedFrameInfo* info); | |
174 | 197 |
175 static void ComputeOutputFrames(Deoptimizer* deoptimizer); | 198 static void ComputeOutputFrames(Deoptimizer* deoptimizer); |
176 | 199 |
177 static Address GetDeoptimizationEntry(int id, BailoutType type); | 200 static Address GetDeoptimizationEntry(int id, BailoutType type); |
178 static int GetDeoptimizationId(Address addr, BailoutType type); | 201 static int GetDeoptimizationId(Address addr, BailoutType type); |
179 static int GetOutputInfo(DeoptimizationOutputData* data, | 202 static int GetOutputInfo(DeoptimizationOutputData* data, |
180 unsigned node_id, | 203 unsigned node_id, |
181 SharedFunctionInfo* shared); | 204 SharedFunctionInfo* shared); |
182 | 205 |
183 // Code generation support. | 206 // Code generation support. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
226 }; | 249 }; |
227 | 250 |
228 private: | 251 private: |
229 static const int kNumberOfEntries = 4096; | 252 static const int kNumberOfEntries = 4096; |
230 | 253 |
231 Deoptimizer(Isolate* isolate, | 254 Deoptimizer(Isolate* isolate, |
232 JSFunction* function, | 255 JSFunction* function, |
233 BailoutType type, | 256 BailoutType type, |
234 unsigned bailout_id, | 257 unsigned bailout_id, |
235 Address from, | 258 Address from, |
236 int fp_to_sp_delta); | 259 int fp_to_sp_delta, |
260 Code* optimized_code); | |
237 void DeleteFrameDescriptions(); | 261 void DeleteFrameDescriptions(); |
238 | 262 |
239 void DoComputeOutputFrames(); | 263 void DoComputeOutputFrames(); |
240 void DoComputeOsrOutputFrame(); | 264 void DoComputeOsrOutputFrame(); |
241 void DoComputeFrame(TranslationIterator* iterator, int frame_index); | 265 void DoComputeFrame(TranslationIterator* iterator, int frame_index); |
242 void DoTranslateCommand(TranslationIterator* iterator, | 266 void DoTranslateCommand(TranslationIterator* iterator, |
243 int frame_index, | 267 int frame_index, |
244 unsigned output_offset); | 268 unsigned output_offset); |
245 // Translate a command for OSR. Updates the input offset to be used for | 269 // Translate a command for OSR. Updates the input offset to be used for |
246 // the next command. Returns false if translation of the command failed | 270 // the next command. Returns false if translation of the command failed |
(...skipping 15 matching lines...) Expand all Loading... | |
262 static LargeObjectChunk* CreateCode(BailoutType type); | 286 static LargeObjectChunk* CreateCode(BailoutType type); |
263 static void GenerateDeoptimizationEntries( | 287 static void GenerateDeoptimizationEntries( |
264 MacroAssembler* masm, int count, BailoutType type); | 288 MacroAssembler* masm, int count, BailoutType type); |
265 | 289 |
266 // Weak handle callback for deoptimizing code objects. | 290 // Weak handle callback for deoptimizing code objects. |
267 static void HandleWeakDeoptimizedCode( | 291 static void HandleWeakDeoptimizedCode( |
268 v8::Persistent<v8::Value> obj, void* data); | 292 v8::Persistent<v8::Value> obj, void* data); |
269 static Code* FindDeoptimizingCodeFromAddress(Address addr); | 293 static Code* FindDeoptimizingCodeFromAddress(Address addr); |
270 static void RemoveDeoptimizingCode(Code* code); | 294 static void RemoveDeoptimizingCode(Code* code); |
271 | 295 |
296 // Fill the input from from a JavaScript frame. This is used when | |
297 // the debugger needs to inspect an optimized frame. For normal | |
298 // deoptimizations the input frame is filled in generated code. | |
299 void FillInputFrame(Address tos, JavaScriptFrame* frame); | |
300 | |
272 Isolate* isolate_; | 301 Isolate* isolate_; |
273 JSFunction* function_; | 302 JSFunction* function_; |
274 Code* optimized_code_; | 303 Code* optimized_code_; |
275 unsigned bailout_id_; | 304 unsigned bailout_id_; |
276 BailoutType bailout_type_; | 305 BailoutType bailout_type_; |
277 Address from_; | 306 Address from_; |
278 int fp_to_sp_delta_; | 307 int fp_to_sp_delta_; |
279 | 308 |
280 // Input frame description. | 309 // Input frame description. |
281 FrameDescription* input_; | 310 FrameDescription* input_; |
282 // Number of output frames. | 311 // Number of output frames. |
283 int output_count_; | 312 int output_count_; |
284 // Array of output frame descriptions. | 313 // Array of output frame descriptions. |
285 FrameDescription** output_; | 314 FrameDescription** output_; |
286 | 315 |
287 List<HeapNumberMaterializationDescriptor> deferred_heap_numbers_; | 316 List<HeapNumberMaterializationDescriptor> deferred_heap_numbers_; |
288 | 317 |
289 static int table_entry_size_; | 318 static int table_entry_size_; |
290 | 319 |
291 friend class FrameDescription; | 320 friend class FrameDescription; |
292 friend class DeoptimizingCodeListNode; | 321 friend class DeoptimizingCodeListNode; |
322 friend class DeoptimizedFrameInfo; | |
293 }; | 323 }; |
294 | 324 |
295 | 325 |
296 class FrameDescription { | 326 class FrameDescription { |
297 public: | 327 public: |
298 FrameDescription(uint32_t frame_size, | 328 FrameDescription(uint32_t frame_size, |
299 JSFunction* function); | 329 JSFunction* function); |
300 | 330 |
301 void* operator new(size_t size, uint32_t frame_size) { | 331 void* operator new(size_t size, uint32_t frame_size) { |
302 // Subtracts kPointerSize, as the member frame_content_ already supplies | 332 // Subtracts kPointerSize, as the member frame_content_ already supplies |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
353 void SetPc(intptr_t pc) { pc_ = pc; } | 383 void SetPc(intptr_t pc) { pc_ = pc; } |
354 | 384 |
355 intptr_t GetFp() const { return fp_; } | 385 intptr_t GetFp() const { return fp_; } |
356 void SetFp(intptr_t fp) { fp_ = fp; } | 386 void SetFp(intptr_t fp) { fp_ = fp; } |
357 | 387 |
358 Smi* GetState() const { return state_; } | 388 Smi* GetState() const { return state_; } |
359 void SetState(Smi* state) { state_ = state; } | 389 void SetState(Smi* state) { state_ = state; } |
360 | 390 |
361 void SetContinuation(intptr_t pc) { continuation_ = pc; } | 391 void SetContinuation(intptr_t pc) { continuation_ = pc; } |
362 | 392 |
393 #ifdef DEBUG | |
394 Code::Kind GetKind() const { return kind_; } | |
395 void SetKind(Code::Kind kind) { kind_ = kind; } | |
396 #endif | |
397 | |
398 // Get the expression stack height for a unoptimized frame. | |
399 unsigned GetExpressionCount(Deoptimizer* deoptimizer); | |
400 | |
401 // Get the expression stack value for an unoptimized frame. | |
402 Object* GetExpression(Deoptimizer* deoptimizer, int index); | |
403 | |
363 static int registers_offset() { | 404 static int registers_offset() { |
364 return OFFSET_OF(FrameDescription, registers_); | 405 return OFFSET_OF(FrameDescription, registers_); |
365 } | 406 } |
366 | 407 |
367 static int double_registers_offset() { | 408 static int double_registers_offset() { |
368 return OFFSET_OF(FrameDescription, double_registers_); | 409 return OFFSET_OF(FrameDescription, double_registers_); |
369 } | 410 } |
370 | 411 |
371 static int frame_size_offset() { | 412 static int frame_size_offset() { |
372 return OFFSET_OF(FrameDescription, frame_size_); | 413 return OFFSET_OF(FrameDescription, frame_size_); |
(...skipping 19 matching lines...) Expand all Loading... | |
392 static const uint32_t kZapUint32 = 0xbeeddead; | 433 static const uint32_t kZapUint32 = 0xbeeddead; |
393 | 434 |
394 uintptr_t frame_size_; // Number of bytes. | 435 uintptr_t frame_size_; // Number of bytes. |
395 JSFunction* function_; | 436 JSFunction* function_; |
396 intptr_t registers_[Register::kNumRegisters]; | 437 intptr_t registers_[Register::kNumRegisters]; |
397 double double_registers_[DoubleRegister::kNumAllocatableRegisters]; | 438 double double_registers_[DoubleRegister::kNumAllocatableRegisters]; |
398 intptr_t top_; | 439 intptr_t top_; |
399 intptr_t pc_; | 440 intptr_t pc_; |
400 intptr_t fp_; | 441 intptr_t fp_; |
401 Smi* state_; | 442 Smi* state_; |
443 #ifdef DEBUG | |
444 Code::Kind kind_; | |
445 #endif | |
402 | 446 |
403 // Continuation is the PC where the execution continues after | 447 // Continuation is the PC where the execution continues after |
404 // deoptimizing. | 448 // deoptimizing. |
405 intptr_t continuation_; | 449 intptr_t continuation_; |
406 | 450 |
407 // This must be at the end of the object as the object is allocated larger | 451 // This must be at the end of the object as the object is allocated larger |
408 // than it's definition indicate to extend this array. | 452 // than it's definition indicate to extend this array. |
409 intptr_t frame_content_[1]; | 453 intptr_t frame_content_[1]; |
410 | 454 |
411 intptr_t* GetFrameSlotPointer(unsigned offset) { | 455 intptr_t* GetFrameSlotPointer(unsigned offset) { |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
590 return frame->fp() + offset - ((slot_index + 1) * kPointerSize); | 634 return frame->fp() + offset - ((slot_index + 1) * kPointerSize); |
591 } | 635 } |
592 } | 636 } |
593 | 637 |
594 static SlotRef ComputeSlotForNextArgument(TranslationIterator* iterator, | 638 static SlotRef ComputeSlotForNextArgument(TranslationIterator* iterator, |
595 DeoptimizationInputData* data, | 639 DeoptimizationInputData* data, |
596 JavaScriptFrame* frame); | 640 JavaScriptFrame* frame); |
597 }; | 641 }; |
598 | 642 |
599 | 643 |
644 #ifdef ENABLE_DEBUGGER_SUPPORT | |
645 // Class used to represent an unoptimized frame when the debugger | |
646 // needs to inspect a frame that is part of an optimized frame. The | |
647 // internally used FrameDescription objects are not GC safe so for use | |
648 // by the debugger frame information is copied to an object of this type. | |
649 class DeoptimizedFrameInfo : public Malloced { | |
650 public: | |
651 DeoptimizedFrameInfo(Deoptimizer* deoptimizer, int frame_index); | |
652 virtual ~DeoptimizedFrameInfo(); | |
653 | |
654 // GC support. | |
655 void Iterate(ObjectVisitor* v); | |
656 | |
657 // Return the height of the expression stack. | |
658 int expression_count() { return expression_count_; } | |
659 | |
660 // Get an expression from the expression stack. | |
661 Object* GetExpression(int index) { | |
662 ASSERT(0 <= index && index < expression_count()); | |
663 return expression_stack_[index]; | |
664 } | |
665 | |
666 private: | |
667 // Set an expression on the expression stack. | |
668 void SetExpression(int index, Object* obj) { | |
669 ASSERT(0 <= index && index < expression_count()); | |
670 expression_stack_[index] = obj; | |
671 } | |
672 | |
673 int expression_count_; | |
674 Object** expression_stack_; | |
675 | |
676 friend class Deoptimizer; | |
677 }; | |
678 #endif | |
679 | |
600 } } // namespace v8::internal | 680 } } // namespace v8::internal |
601 | 681 |
602 #endif // V8_DEOPTIMIZER_H_ | 682 #endif // V8_DEOPTIMIZER_H_ |
OLD | NEW |