| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 1 | // Copyright 2012 the V8 project authors. All rights reserved. | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 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 |  | 
| Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 33 | #include "allocation.h" | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 34 | #include "macro-assembler.h" | 
|  | 35 | #include "zone-inl.h" | 
|  | 36 |  | 
|  | 37 |  | 
|  | 38 | namespace v8 { | 
|  | 39 | namespace internal { | 
|  | 40 |  | 
|  | 41 | class FrameDescription; | 
|  | 42 | class TranslationIterator; | 
|  | 43 | class DeoptimizingCodeListNode; | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 44 | class DeoptimizedFrameInfo; | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 45 |  | 
| Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 46 | class HeapNumberMaterializationDescriptor BASE_EMBEDDED { | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 47 | public: | 
| Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 48 | HeapNumberMaterializationDescriptor(Address slot_address, double val) | 
|  | 49 | : slot_address_(slot_address), val_(val) { } | 
|  | 50 |  | 
|  | 51 | Address slot_address() const { return slot_address_; } | 
|  | 52 | double value() const { return val_; } | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 53 |  | 
|  | 54 | private: | 
| Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 55 | Address slot_address_; | 
|  | 56 | double val_; | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 57 | }; | 
|  | 58 |  | 
|  | 59 |  | 
|  | 60 | class OptimizedFunctionVisitor BASE_EMBEDDED { | 
|  | 61 | public: | 
|  | 62 | virtual ~OptimizedFunctionVisitor() {} | 
|  | 63 |  | 
|  | 64 | // Function which is called before iteration of any optimized functions | 
|  | 65 | // from given global context. | 
|  | 66 | virtual void EnterContext(Context* context) = 0; | 
|  | 67 |  | 
|  | 68 | virtual void VisitFunction(JSFunction* function) = 0; | 
|  | 69 |  | 
|  | 70 | // Function which is called after iteration of all optimized functions | 
|  | 71 | // from given global context. | 
|  | 72 | virtual void LeaveContext(Context* context) = 0; | 
|  | 73 | }; | 
|  | 74 |  | 
|  | 75 |  | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 76 | class Deoptimizer; | 
|  | 77 |  | 
|  | 78 |  | 
|  | 79 | class DeoptimizerData { | 
|  | 80 | public: | 
|  | 81 | DeoptimizerData(); | 
|  | 82 | ~DeoptimizerData(); | 
|  | 83 |  | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 84 | #ifdef ENABLE_DEBUGGER_SUPPORT | 
|  | 85 | void Iterate(ObjectVisitor* v); | 
|  | 86 | #endif | 
|  | 87 |  | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 88 | private: | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 89 | MemoryChunk* eager_deoptimization_entry_code_; | 
|  | 90 | MemoryChunk* lazy_deoptimization_entry_code_; | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 91 | Deoptimizer* current_; | 
|  | 92 |  | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 93 | #ifdef ENABLE_DEBUGGER_SUPPORT | 
|  | 94 | DeoptimizedFrameInfo* deoptimized_frame_info_; | 
|  | 95 | #endif | 
|  | 96 |  | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 97 | // List of deoptimized code which still have references from active stack | 
|  | 98 | // frames. These code objects are needed by the deoptimizer when deoptimizing | 
|  | 99 | // a frame for which the code object for the function function has been | 
|  | 100 | // changed from the code present when deoptimizing was done. | 
|  | 101 | DeoptimizingCodeListNode* deoptimizing_code_list_; | 
|  | 102 |  | 
|  | 103 | friend class Deoptimizer; | 
|  | 104 |  | 
|  | 105 | DISALLOW_COPY_AND_ASSIGN(DeoptimizerData); | 
|  | 106 | }; | 
|  | 107 |  | 
|  | 108 |  | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 109 | class Deoptimizer : public Malloced { | 
|  | 110 | public: | 
|  | 111 | enum BailoutType { | 
|  | 112 | EAGER, | 
|  | 113 | LAZY, | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 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 | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 118 | }; | 
|  | 119 |  | 
|  | 120 | int output_count() const { return output_count_; } | 
|  | 121 |  | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 122 | // Number of created JS frames. Not all created frames are necessarily JS. | 
|  | 123 | int jsframe_count() const { return jsframe_count_; } | 
|  | 124 |  | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 125 | static Deoptimizer* New(JSFunction* function, | 
|  | 126 | BailoutType type, | 
|  | 127 | unsigned bailout_id, | 
|  | 128 | Address from, | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 129 | int fp_to_sp_delta, | 
|  | 130 | Isolate* isolate); | 
|  | 131 | static Deoptimizer* Grab(Isolate* isolate); | 
|  | 132 |  | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 133 | #ifdef ENABLE_DEBUGGER_SUPPORT | 
|  | 134 | // The returned object with information on the optimized frame needs to be | 
|  | 135 | // freed before another one can be generated. | 
|  | 136 | static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame, | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 137 | int jsframe_index, | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 138 | Isolate* isolate); | 
|  | 139 | static void DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, | 
|  | 140 | Isolate* isolate); | 
|  | 141 | #endif | 
|  | 142 |  | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 143 | // Makes sure that there is enough room in the relocation | 
|  | 144 | // information of a code object to perform lazy deoptimization | 
|  | 145 | // patching. If there is not enough room a new relocation | 
|  | 146 | // information object is allocated and comments are added until it | 
|  | 147 | // is big enough. | 
|  | 148 | static void EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 149 |  | 
|  | 150 | // Deoptimize the function now. Its current optimized code will never be run | 
|  | 151 | // again and any activations of the optimized code will get deoptimized when | 
|  | 152 | // execution returns. | 
|  | 153 | static void DeoptimizeFunction(JSFunction* function); | 
|  | 154 |  | 
|  | 155 | // Deoptimize all functions in the heap. | 
|  | 156 | static void DeoptimizeAll(); | 
|  | 157 |  | 
|  | 158 | static void DeoptimizeGlobalObject(JSObject* object); | 
|  | 159 |  | 
|  | 160 | static void VisitAllOptimizedFunctionsForContext( | 
|  | 161 | Context* context, OptimizedFunctionVisitor* visitor); | 
|  | 162 |  | 
|  | 163 | static void VisitAllOptimizedFunctionsForGlobalObject( | 
|  | 164 | JSObject* object, OptimizedFunctionVisitor* visitor); | 
|  | 165 |  | 
|  | 166 | static void VisitAllOptimizedFunctions(OptimizedFunctionVisitor* visitor); | 
|  | 167 |  | 
| Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 168 | // The size in bytes of the code required at a lazy deopt patch site. | 
|  | 169 | static int patch_size(); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 170 |  | 
| Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 171 | // Patch all stack guard checks in the unoptimized code to | 
|  | 172 | // unconditionally call replacement_code. | 
|  | 173 | static void PatchStackCheckCode(Code* unoptimized_code, | 
|  | 174 | Code* check_code, | 
|  | 175 | Code* replacement_code); | 
|  | 176 |  | 
|  | 177 | // Patch stack guard check at instruction before pc_after in | 
|  | 178 | // the unoptimized code to unconditionally call replacement_code. | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 179 | static void PatchStackCheckCodeAt(Code* unoptimized_code, | 
|  | 180 | Address pc_after, | 
| Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 181 | Code* check_code, | 
|  | 182 | Code* replacement_code); | 
|  | 183 |  | 
|  | 184 | // Change all patched stack guard checks in the unoptimized code | 
|  | 185 | // back to a normal stack guard check. | 
|  | 186 | static void RevertStackCheckCode(Code* unoptimized_code, | 
|  | 187 | Code* check_code, | 
|  | 188 | Code* replacement_code); | 
|  | 189 |  | 
|  | 190 | // Change all patched stack guard checks in the unoptimized code | 
|  | 191 | // back to a normal stack guard check. | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 192 | static void RevertStackCheckCodeAt(Code* unoptimized_code, | 
|  | 193 | Address pc_after, | 
| Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 194 | Code* check_code, | 
|  | 195 | Code* replacement_code); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 196 |  | 
|  | 197 | ~Deoptimizer(); | 
|  | 198 |  | 
| Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 199 | void MaterializeHeapNumbers(); | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 200 | #ifdef ENABLE_DEBUGGER_SUPPORT | 
|  | 201 | void MaterializeHeapNumbersForDebuggerInspectableFrame( | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 202 | Address parameters_top, | 
|  | 203 | uint32_t parameters_size, | 
|  | 204 | Address expressions_top, | 
|  | 205 | uint32_t expressions_size, | 
|  | 206 | DeoptimizedFrameInfo* info); | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 207 | #endif | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 208 |  | 
| Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 209 | static void ComputeOutputFrames(Deoptimizer* deoptimizer); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 210 |  | 
|  | 211 | static Address GetDeoptimizationEntry(int id, BailoutType type); | 
|  | 212 | static int GetDeoptimizationId(Address addr, BailoutType type); | 
| Steve Block | 9fac840 | 2011-05-12 15:51:54 +0100 | [diff] [blame] | 213 | static int GetOutputInfo(DeoptimizationOutputData* data, | 
|  | 214 | unsigned node_id, | 
|  | 215 | SharedFunctionInfo* shared); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 216 |  | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 217 | // Code generation support. | 
|  | 218 | static int input_offset() { return OFFSET_OF(Deoptimizer, input_); } | 
|  | 219 | static int output_count_offset() { | 
|  | 220 | return OFFSET_OF(Deoptimizer, output_count_); | 
|  | 221 | } | 
|  | 222 | static int output_offset() { return OFFSET_OF(Deoptimizer, output_); } | 
|  | 223 |  | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 224 | static int GetDeoptimizedCodeCount(Isolate* isolate); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 225 |  | 
|  | 226 | static const int kNotDeoptimizationEntry = -1; | 
|  | 227 |  | 
|  | 228 | // Generators for the deoptimization entry code. | 
|  | 229 | class EntryGenerator BASE_EMBEDDED { | 
|  | 230 | public: | 
|  | 231 | EntryGenerator(MacroAssembler* masm, BailoutType type) | 
|  | 232 | : masm_(masm), type_(type) { } | 
|  | 233 | virtual ~EntryGenerator() { } | 
|  | 234 |  | 
|  | 235 | void Generate(); | 
|  | 236 |  | 
|  | 237 | protected: | 
|  | 238 | MacroAssembler* masm() const { return masm_; } | 
|  | 239 | BailoutType type() const { return type_; } | 
|  | 240 |  | 
|  | 241 | virtual void GeneratePrologue() { } | 
|  | 242 |  | 
|  | 243 | private: | 
|  | 244 | MacroAssembler* masm_; | 
|  | 245 | Deoptimizer::BailoutType type_; | 
|  | 246 | }; | 
|  | 247 |  | 
|  | 248 | class TableEntryGenerator : public EntryGenerator { | 
|  | 249 | public: | 
|  | 250 | TableEntryGenerator(MacroAssembler* masm, BailoutType type,  int count) | 
|  | 251 | : EntryGenerator(masm, type), count_(count) { } | 
|  | 252 |  | 
|  | 253 | protected: | 
|  | 254 | virtual void GeneratePrologue(); | 
|  | 255 |  | 
|  | 256 | private: | 
|  | 257 | int count() const { return count_; } | 
|  | 258 |  | 
|  | 259 | int count_; | 
|  | 260 | }; | 
|  | 261 |  | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 262 | int ConvertJSFrameIndexToFrameIndex(int jsframe_index); | 
|  | 263 |  | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 264 | private: | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 265 | static const int kNumberOfEntries = 16384; | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 266 |  | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 267 | Deoptimizer(Isolate* isolate, | 
|  | 268 | JSFunction* function, | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 269 | BailoutType type, | 
|  | 270 | unsigned bailout_id, | 
|  | 271 | Address from, | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 272 | int fp_to_sp_delta, | 
|  | 273 | Code* optimized_code); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 274 | void DeleteFrameDescriptions(); | 
|  | 275 |  | 
|  | 276 | void DoComputeOutputFrames(); | 
|  | 277 | void DoComputeOsrOutputFrame(); | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 278 | void DoComputeJSFrame(TranslationIterator* iterator, int frame_index); | 
|  | 279 | void DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, | 
|  | 280 | int frame_index); | 
|  | 281 | void DoComputeConstructStubFrame(TranslationIterator* iterator, | 
|  | 282 | int frame_index); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 283 | void DoTranslateCommand(TranslationIterator* iterator, | 
|  | 284 | int frame_index, | 
|  | 285 | unsigned output_offset); | 
|  | 286 | // Translate a command for OSR.  Updates the input offset to be used for | 
|  | 287 | // the next command.  Returns false if translation of the command failed | 
|  | 288 | // (e.g., a number conversion failed) and may or may not have updated the | 
|  | 289 | // input offset. | 
|  | 290 | bool DoOsrTranslateCommand(TranslationIterator* iterator, | 
|  | 291 | int* input_offset); | 
|  | 292 |  | 
|  | 293 | unsigned ComputeInputFrameSize() const; | 
|  | 294 | unsigned ComputeFixedSize(JSFunction* function) const; | 
|  | 295 |  | 
|  | 296 | unsigned ComputeIncomingArgumentSize(JSFunction* function) const; | 
|  | 297 | unsigned ComputeOutgoingArgumentSize() const; | 
|  | 298 |  | 
|  | 299 | Object* ComputeLiteral(int index) const; | 
|  | 300 |  | 
| Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 301 | void AddDoubleValue(intptr_t slot_address, double value); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 302 |  | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 303 | static MemoryChunk* CreateCode(BailoutType type); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 304 | static void GenerateDeoptimizationEntries( | 
|  | 305 | MacroAssembler* masm, int count, BailoutType type); | 
|  | 306 |  | 
|  | 307 | // Weak handle callback for deoptimizing code objects. | 
|  | 308 | static void HandleWeakDeoptimizedCode( | 
|  | 309 | v8::Persistent<v8::Value> obj, void* data); | 
|  | 310 | static Code* FindDeoptimizingCodeFromAddress(Address addr); | 
|  | 311 | static void RemoveDeoptimizingCode(Code* code); | 
|  | 312 |  | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 313 | // Fill the input from from a JavaScript frame. This is used when | 
|  | 314 | // the debugger needs to inspect an optimized frame. For normal | 
|  | 315 | // deoptimizations the input frame is filled in generated code. | 
|  | 316 | void FillInputFrame(Address tos, JavaScriptFrame* frame); | 
|  | 317 |  | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 318 | Isolate* isolate_; | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 319 | JSFunction* function_; | 
|  | 320 | Code* optimized_code_; | 
|  | 321 | unsigned bailout_id_; | 
|  | 322 | BailoutType bailout_type_; | 
|  | 323 | Address from_; | 
|  | 324 | int fp_to_sp_delta_; | 
|  | 325 |  | 
|  | 326 | // Input frame description. | 
|  | 327 | FrameDescription* input_; | 
|  | 328 | // Number of output frames. | 
|  | 329 | int output_count_; | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 330 | // Number of output js frames. | 
|  | 331 | int jsframe_count_; | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 332 | // Array of output frame descriptions. | 
|  | 333 | FrameDescription** output_; | 
|  | 334 |  | 
| Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 335 | List<HeapNumberMaterializationDescriptor> deferred_heap_numbers_; | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 336 |  | 
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 337 | static const int table_entry_size_; | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 338 |  | 
|  | 339 | friend class FrameDescription; | 
|  | 340 | friend class DeoptimizingCodeListNode; | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 341 | friend class DeoptimizedFrameInfo; | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 342 | }; | 
|  | 343 |  | 
|  | 344 |  | 
|  | 345 | class FrameDescription { | 
|  | 346 | public: | 
|  | 347 | FrameDescription(uint32_t frame_size, | 
|  | 348 | JSFunction* function); | 
|  | 349 |  | 
|  | 350 | void* operator new(size_t size, uint32_t frame_size) { | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 351 | // Subtracts kPointerSize, as the member frame_content_ already supplies | 
|  | 352 | // the first element of the area to store the frame. | 
|  | 353 | return malloc(size + frame_size - kPointerSize); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 354 | } | 
|  | 355 |  | 
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 356 | void operator delete(void* pointer, uint32_t frame_size) { | 
|  | 357 | free(pointer); | 
|  | 358 | } | 
|  | 359 |  | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 360 | void operator delete(void* description) { | 
|  | 361 | free(description); | 
|  | 362 | } | 
|  | 363 |  | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 364 | uint32_t GetFrameSize() const { | 
|  | 365 | ASSERT(static_cast<uint32_t>(frame_size_) == frame_size_); | 
|  | 366 | return static_cast<uint32_t>(frame_size_); | 
|  | 367 | } | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 368 |  | 
|  | 369 | JSFunction* GetFunction() const { return function_; } | 
|  | 370 |  | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 371 | unsigned GetOffsetFromSlotIndex(int slot_index); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 372 |  | 
|  | 373 | intptr_t GetFrameSlot(unsigned offset) { | 
|  | 374 | return *GetFrameSlotPointer(offset); | 
|  | 375 | } | 
|  | 376 |  | 
|  | 377 | double GetDoubleFrameSlot(unsigned offset) { | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 378 | intptr_t* ptr = GetFrameSlotPointer(offset); | 
|  | 379 | #if V8_TARGET_ARCH_MIPS | 
|  | 380 | // Prevent gcc from using load-double (mips ldc1) on (possibly) | 
|  | 381 | // non-64-bit aligned double. Uses two lwc1 instructions. | 
|  | 382 | union conversion { | 
|  | 383 | double d; | 
|  | 384 | uint32_t u[2]; | 
|  | 385 | } c; | 
|  | 386 | c.u[0] = *reinterpret_cast<uint32_t*>(ptr); | 
|  | 387 | c.u[1] = *(reinterpret_cast<uint32_t*>(ptr) + 1); | 
|  | 388 | return c.d; | 
|  | 389 | #else | 
|  | 390 | return *reinterpret_cast<double*>(ptr); | 
|  | 391 | #endif | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 392 | } | 
|  | 393 |  | 
|  | 394 | void SetFrameSlot(unsigned offset, intptr_t value) { | 
|  | 395 | *GetFrameSlotPointer(offset) = value; | 
|  | 396 | } | 
|  | 397 |  | 
|  | 398 | intptr_t GetRegister(unsigned n) const { | 
|  | 399 | ASSERT(n < ARRAY_SIZE(registers_)); | 
|  | 400 | return registers_[n]; | 
|  | 401 | } | 
|  | 402 |  | 
|  | 403 | double GetDoubleRegister(unsigned n) const { | 
|  | 404 | ASSERT(n < ARRAY_SIZE(double_registers_)); | 
|  | 405 | return double_registers_[n]; | 
|  | 406 | } | 
|  | 407 |  | 
|  | 408 | void SetRegister(unsigned n, intptr_t value) { | 
|  | 409 | ASSERT(n < ARRAY_SIZE(registers_)); | 
|  | 410 | registers_[n] = value; | 
|  | 411 | } | 
|  | 412 |  | 
|  | 413 | void SetDoubleRegister(unsigned n, double value) { | 
|  | 414 | ASSERT(n < ARRAY_SIZE(double_registers_)); | 
|  | 415 | double_registers_[n] = value; | 
|  | 416 | } | 
|  | 417 |  | 
|  | 418 | intptr_t GetTop() const { return top_; } | 
|  | 419 | void SetTop(intptr_t top) { top_ = top; } | 
|  | 420 |  | 
|  | 421 | intptr_t GetPc() const { return pc_; } | 
|  | 422 | void SetPc(intptr_t pc) { pc_ = pc; } | 
|  | 423 |  | 
|  | 424 | intptr_t GetFp() const { return fp_; } | 
|  | 425 | void SetFp(intptr_t fp) { fp_ = fp; } | 
|  | 426 |  | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 427 | intptr_t GetContext() const { return context_; } | 
|  | 428 | void SetContext(intptr_t context) { context_ = context; } | 
|  | 429 |  | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 430 | Smi* GetState() const { return state_; } | 
|  | 431 | void SetState(Smi* state) { state_ = state; } | 
|  | 432 |  | 
|  | 433 | void SetContinuation(intptr_t pc) { continuation_ = pc; } | 
|  | 434 |  | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 435 | StackFrame::Type GetFrameType() const { return type_; } | 
|  | 436 | void SetFrameType(StackFrame::Type type) { type_ = type; } | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 437 |  | 
|  | 438 | // Get the incoming arguments count. | 
|  | 439 | int ComputeParametersCount(); | 
|  | 440 |  | 
|  | 441 | // Get a parameter value for an unoptimized frame. | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 442 | Object* GetParameter(int index); | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 443 |  | 
|  | 444 | // Get the expression stack height for a unoptimized frame. | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 445 | unsigned GetExpressionCount(); | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 446 |  | 
|  | 447 | // Get the expression stack value for an unoptimized frame. | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 448 | Object* GetExpression(int index); | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 449 |  | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 450 | static int registers_offset() { | 
|  | 451 | return OFFSET_OF(FrameDescription, registers_); | 
|  | 452 | } | 
|  | 453 |  | 
|  | 454 | static int double_registers_offset() { | 
|  | 455 | return OFFSET_OF(FrameDescription, double_registers_); | 
|  | 456 | } | 
|  | 457 |  | 
|  | 458 | static int frame_size_offset() { | 
|  | 459 | return OFFSET_OF(FrameDescription, frame_size_); | 
|  | 460 | } | 
|  | 461 |  | 
|  | 462 | static int pc_offset() { | 
|  | 463 | return OFFSET_OF(FrameDescription, pc_); | 
|  | 464 | } | 
|  | 465 |  | 
|  | 466 | static int state_offset() { | 
|  | 467 | return OFFSET_OF(FrameDescription, state_); | 
|  | 468 | } | 
|  | 469 |  | 
|  | 470 | static int continuation_offset() { | 
|  | 471 | return OFFSET_OF(FrameDescription, continuation_); | 
|  | 472 | } | 
|  | 473 |  | 
|  | 474 | static int frame_content_offset() { | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 475 | return OFFSET_OF(FrameDescription, frame_content_); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 476 | } | 
|  | 477 |  | 
|  | 478 | private: | 
|  | 479 | static const uint32_t kZapUint32 = 0xbeeddead; | 
|  | 480 |  | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 481 | // Frame_size_ must hold a uint32_t value.  It is only a uintptr_t to | 
|  | 482 | // keep the variable-size array frame_content_ of type intptr_t at | 
|  | 483 | // the end of the structure aligned. | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 484 | uintptr_t frame_size_;  // Number of bytes. | 
|  | 485 | JSFunction* function_; | 
|  | 486 | intptr_t registers_[Register::kNumRegisters]; | 
|  | 487 | double double_registers_[DoubleRegister::kNumAllocatableRegisters]; | 
|  | 488 | intptr_t top_; | 
|  | 489 | intptr_t pc_; | 
|  | 490 | intptr_t fp_; | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 491 | intptr_t context_; | 
|  | 492 | StackFrame::Type type_; | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 493 | Smi* state_; | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 494 | #ifdef DEBUG | 
|  | 495 | Code::Kind kind_; | 
|  | 496 | #endif | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 497 |  | 
|  | 498 | // Continuation is the PC where the execution continues after | 
|  | 499 | // deoptimizing. | 
|  | 500 | intptr_t continuation_; | 
|  | 501 |  | 
| Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 502 | // This must be at the end of the object as the object is allocated larger | 
|  | 503 | // than it's definition indicate to extend this array. | 
|  | 504 | intptr_t frame_content_[1]; | 
|  | 505 |  | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 506 | intptr_t* GetFrameSlotPointer(unsigned offset) { | 
|  | 507 | ASSERT(offset < frame_size_); | 
|  | 508 | return reinterpret_cast<intptr_t*>( | 
|  | 509 | reinterpret_cast<Address>(this) + frame_content_offset() + offset); | 
|  | 510 | } | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 511 |  | 
|  | 512 | int ComputeFixedSize(); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 513 | }; | 
|  | 514 |  | 
|  | 515 |  | 
|  | 516 | class TranslationBuffer BASE_EMBEDDED { | 
|  | 517 | public: | 
|  | 518 | TranslationBuffer() : contents_(256) { } | 
|  | 519 |  | 
|  | 520 | int CurrentIndex() const { return contents_.length(); } | 
|  | 521 | void Add(int32_t value); | 
|  | 522 |  | 
|  | 523 | Handle<ByteArray> CreateByteArray(); | 
|  | 524 |  | 
|  | 525 | private: | 
|  | 526 | ZoneList<uint8_t> contents_; | 
|  | 527 | }; | 
|  | 528 |  | 
|  | 529 |  | 
|  | 530 | class TranslationIterator BASE_EMBEDDED { | 
|  | 531 | public: | 
|  | 532 | TranslationIterator(ByteArray* buffer, int index) | 
|  | 533 | : buffer_(buffer), index_(index) { | 
|  | 534 | ASSERT(index >= 0 && index < buffer->length()); | 
|  | 535 | } | 
|  | 536 |  | 
|  | 537 | int32_t Next(); | 
|  | 538 |  | 
| Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 539 | bool HasNext() const { return index_ < buffer_->length(); } | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 540 |  | 
|  | 541 | void Skip(int n) { | 
|  | 542 | for (int i = 0; i < n; i++) Next(); | 
|  | 543 | } | 
|  | 544 |  | 
|  | 545 | private: | 
|  | 546 | ByteArray* buffer_; | 
|  | 547 | int index_; | 
|  | 548 | }; | 
|  | 549 |  | 
|  | 550 |  | 
|  | 551 | class Translation BASE_EMBEDDED { | 
|  | 552 | public: | 
|  | 553 | enum Opcode { | 
|  | 554 | BEGIN, | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 555 | JS_FRAME, | 
|  | 556 | CONSTRUCT_STUB_FRAME, | 
|  | 557 | ARGUMENTS_ADAPTOR_FRAME, | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 558 | REGISTER, | 
|  | 559 | INT32_REGISTER, | 
|  | 560 | DOUBLE_REGISTER, | 
|  | 561 | STACK_SLOT, | 
|  | 562 | INT32_STACK_SLOT, | 
|  | 563 | DOUBLE_STACK_SLOT, | 
|  | 564 | LITERAL, | 
|  | 565 | ARGUMENTS_OBJECT, | 
|  | 566 |  | 
|  | 567 | // A prefix indicating that the next command is a duplicate of the one | 
|  | 568 | // that follows it. | 
|  | 569 | DUPLICATE | 
|  | 570 | }; | 
|  | 571 |  | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 572 | Translation(TranslationBuffer* buffer, int frame_count, int jsframe_count) | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 573 | : buffer_(buffer), | 
|  | 574 | index_(buffer->CurrentIndex()) { | 
|  | 575 | buffer_->Add(BEGIN); | 
|  | 576 | buffer_->Add(frame_count); | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 577 | buffer_->Add(jsframe_count); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 578 | } | 
|  | 579 |  | 
|  | 580 | int index() const { return index_; } | 
|  | 581 |  | 
|  | 582 | // Commands. | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 583 | void BeginJSFrame(int node_id, int literal_id, unsigned height); | 
|  | 584 | void BeginArgumentsAdaptorFrame(int literal_id, unsigned height); | 
|  | 585 | void BeginConstructStubFrame(int literal_id, unsigned height); | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 586 | void StoreRegister(Register reg); | 
|  | 587 | void StoreInt32Register(Register reg); | 
|  | 588 | void StoreDoubleRegister(DoubleRegister reg); | 
|  | 589 | void StoreStackSlot(int index); | 
|  | 590 | void StoreInt32StackSlot(int index); | 
|  | 591 | void StoreDoubleStackSlot(int index); | 
|  | 592 | void StoreLiteral(int literal_id); | 
|  | 593 | void StoreArgumentsObject(); | 
|  | 594 | void MarkDuplicate(); | 
|  | 595 |  | 
|  | 596 | static int NumberOfOperandsFor(Opcode opcode); | 
|  | 597 |  | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 598 | #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 599 | static const char* StringFor(Opcode opcode); | 
|  | 600 | #endif | 
|  | 601 |  | 
|  | 602 | private: | 
|  | 603 | TranslationBuffer* buffer_; | 
|  | 604 | int index_; | 
|  | 605 | }; | 
|  | 606 |  | 
|  | 607 |  | 
|  | 608 | // Linked list holding deoptimizing code objects. The deoptimizing code objects | 
|  | 609 | // are kept as weak handles until they are no longer activated on the stack. | 
|  | 610 | class DeoptimizingCodeListNode : public Malloced { | 
|  | 611 | public: | 
|  | 612 | explicit DeoptimizingCodeListNode(Code* code); | 
|  | 613 | ~DeoptimizingCodeListNode(); | 
|  | 614 |  | 
|  | 615 | DeoptimizingCodeListNode* next() const { return next_; } | 
|  | 616 | void set_next(DeoptimizingCodeListNode* next) { next_ = next; } | 
|  | 617 | Handle<Code> code() const { return code_; } | 
|  | 618 |  | 
|  | 619 | private: | 
|  | 620 | // Global (weak) handle to the deoptimizing code object. | 
|  | 621 | Handle<Code> code_; | 
|  | 622 |  | 
|  | 623 | // Next pointer for linked list. | 
|  | 624 | DeoptimizingCodeListNode* next_; | 
|  | 625 | }; | 
|  | 626 |  | 
|  | 627 |  | 
| Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 628 | class SlotRef BASE_EMBEDDED { | 
|  | 629 | public: | 
|  | 630 | enum SlotRepresentation { | 
|  | 631 | UNKNOWN, | 
|  | 632 | TAGGED, | 
|  | 633 | INT32, | 
|  | 634 | DOUBLE, | 
|  | 635 | LITERAL | 
|  | 636 | }; | 
|  | 637 |  | 
|  | 638 | SlotRef() | 
|  | 639 | : addr_(NULL), representation_(UNKNOWN) { } | 
|  | 640 |  | 
|  | 641 | SlotRef(Address addr, SlotRepresentation representation) | 
|  | 642 | : addr_(addr), representation_(representation) { } | 
|  | 643 |  | 
|  | 644 | explicit SlotRef(Object* literal) | 
|  | 645 | : literal_(literal), representation_(LITERAL) { } | 
|  | 646 |  | 
|  | 647 | Handle<Object> GetValue() { | 
|  | 648 | switch (representation_) { | 
|  | 649 | case TAGGED: | 
|  | 650 | return Handle<Object>(Memory::Object_at(addr_)); | 
|  | 651 |  | 
|  | 652 | case INT32: { | 
|  | 653 | int value = Memory::int32_at(addr_); | 
|  | 654 | if (Smi::IsValid(value)) { | 
|  | 655 | return Handle<Object>(Smi::FromInt(value)); | 
|  | 656 | } else { | 
|  | 657 | return Isolate::Current()->factory()->NewNumberFromInt(value); | 
|  | 658 | } | 
|  | 659 | } | 
|  | 660 |  | 
|  | 661 | case DOUBLE: { | 
|  | 662 | double value = Memory::double_at(addr_); | 
|  | 663 | return Isolate::Current()->factory()->NewNumber(value); | 
|  | 664 | } | 
|  | 665 |  | 
|  | 666 | case LITERAL: | 
|  | 667 | return literal_; | 
|  | 668 |  | 
|  | 669 | default: | 
|  | 670 | UNREACHABLE(); | 
|  | 671 | return Handle<Object>::null(); | 
|  | 672 | } | 
|  | 673 | } | 
|  | 674 |  | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 675 | static Vector<SlotRef> ComputeSlotMappingForArguments( | 
|  | 676 | JavaScriptFrame* frame, | 
|  | 677 | int inlined_frame_index, | 
|  | 678 | int formal_parameter_count); | 
| Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 679 |  | 
|  | 680 | private: | 
|  | 681 | Address addr_; | 
|  | 682 | Handle<Object> literal_; | 
|  | 683 | SlotRepresentation representation_; | 
|  | 684 |  | 
|  | 685 | static Address SlotAddress(JavaScriptFrame* frame, int slot_index) { | 
|  | 686 | if (slot_index >= 0) { | 
|  | 687 | const int offset = JavaScriptFrameConstants::kLocal0Offset; | 
|  | 688 | return frame->fp() + offset - (slot_index * kPointerSize); | 
|  | 689 | } else { | 
|  | 690 | const int offset = JavaScriptFrameConstants::kLastParameterOffset; | 
|  | 691 | return frame->fp() + offset - ((slot_index + 1) * kPointerSize); | 
|  | 692 | } | 
|  | 693 | } | 
|  | 694 |  | 
|  | 695 | static SlotRef ComputeSlotForNextArgument(TranslationIterator* iterator, | 
|  | 696 | DeoptimizationInputData* data, | 
|  | 697 | JavaScriptFrame* frame); | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 698 |  | 
|  | 699 | static void ComputeSlotsForArguments( | 
|  | 700 | Vector<SlotRef>* args_slots, | 
|  | 701 | TranslationIterator* iterator, | 
|  | 702 | DeoptimizationInputData* data, | 
|  | 703 | JavaScriptFrame* frame); | 
| Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 704 | }; | 
|  | 705 |  | 
|  | 706 |  | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 707 | #ifdef ENABLE_DEBUGGER_SUPPORT | 
|  | 708 | // Class used to represent an unoptimized frame when the debugger | 
|  | 709 | // needs to inspect a frame that is part of an optimized frame. The | 
|  | 710 | // internally used FrameDescription objects are not GC safe so for use | 
|  | 711 | // by the debugger frame information is copied to an object of this type. | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 712 | // Represents parameters in unadapted form so their number might mismatch | 
|  | 713 | // formal parameter count. | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 714 | class DeoptimizedFrameInfo : public Malloced { | 
|  | 715 | public: | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 716 | DeoptimizedFrameInfo(Deoptimizer* deoptimizer, | 
|  | 717 | int frame_index, | 
|  | 718 | bool has_arguments_adaptor, | 
|  | 719 | bool has_construct_stub); | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 720 | virtual ~DeoptimizedFrameInfo(); | 
|  | 721 |  | 
|  | 722 | // GC support. | 
|  | 723 | void Iterate(ObjectVisitor* v); | 
|  | 724 |  | 
|  | 725 | // Return the number of incoming arguments. | 
|  | 726 | int parameters_count() { return parameters_count_; } | 
|  | 727 |  | 
|  | 728 | // Return the height of the expression stack. | 
|  | 729 | int expression_count() { return expression_count_; } | 
|  | 730 |  | 
|  | 731 | // Get the frame function. | 
|  | 732 | JSFunction* GetFunction() { | 
|  | 733 | return function_; | 
|  | 734 | } | 
|  | 735 |  | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 736 | // Check if this frame is preceded by construct stub frame.  The bottom-most | 
|  | 737 | // inlined frame might still be called by an uninlined construct stub. | 
|  | 738 | bool HasConstructStub() { | 
|  | 739 | return has_construct_stub_; | 
|  | 740 | } | 
|  | 741 |  | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 742 | // Get an incoming argument. | 
|  | 743 | Object* GetParameter(int index) { | 
|  | 744 | ASSERT(0 <= index && index < parameters_count()); | 
|  | 745 | return parameters_[index]; | 
|  | 746 | } | 
|  | 747 |  | 
|  | 748 | // Get an expression from the expression stack. | 
|  | 749 | Object* GetExpression(int index) { | 
|  | 750 | ASSERT(0 <= index && index < expression_count()); | 
|  | 751 | return expression_stack_[index]; | 
|  | 752 | } | 
|  | 753 |  | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 754 | int GetSourcePosition() { | 
|  | 755 | return source_position_; | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 756 | } | 
|  | 757 |  | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 758 | private: | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 759 | // Set an incoming argument. | 
|  | 760 | void SetParameter(int index, Object* obj) { | 
|  | 761 | ASSERT(0 <= index && index < parameters_count()); | 
|  | 762 | parameters_[index] = obj; | 
|  | 763 | } | 
|  | 764 |  | 
|  | 765 | // Set an expression on the expression stack. | 
|  | 766 | void SetExpression(int index, Object* obj) { | 
|  | 767 | ASSERT(0 <= index && index < expression_count()); | 
|  | 768 | expression_stack_[index] = obj; | 
|  | 769 | } | 
|  | 770 |  | 
|  | 771 | JSFunction* function_; | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 772 | bool has_construct_stub_; | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 773 | int parameters_count_; | 
|  | 774 | int expression_count_; | 
|  | 775 | Object** parameters_; | 
|  | 776 | Object** expression_stack_; | 
| Ben Murdoch | 3ef787d | 2012-04-12 10:51:47 +0100 | [diff] [blame^] | 777 | int source_position_; | 
| Ben Murdoch | 3fb3ca8 | 2011-12-02 17:19:32 +0000 | [diff] [blame] | 778 |  | 
|  | 779 | friend class Deoptimizer; | 
|  | 780 | }; | 
|  | 781 | #endif | 
|  | 782 |  | 
| Ben Murdoch | b0fe162 | 2011-05-05 13:52:32 +0100 | [diff] [blame] | 783 | } }  // namespace v8::internal | 
|  | 784 |  | 
|  | 785 | #endif  // V8_DEOPTIMIZER_H_ |