OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 } | 80 } |
81 | 81 |
82 | 82 |
83 Code* Deoptimizer::FindDeoptimizingCode(Address addr) { | 83 Code* Deoptimizer::FindDeoptimizingCode(Address addr) { |
84 if (function_->IsHeapObject()) { | 84 if (function_->IsHeapObject()) { |
85 // Search all deoptimizing code in the native context of the function. | 85 // Search all deoptimizing code in the native context of the function. |
86 Context* native_context = function_->context()->native_context(); | 86 Context* native_context = function_->context()->native_context(); |
87 Object* element = native_context->DeoptimizedCodeListHead(); | 87 Object* element = native_context->DeoptimizedCodeListHead(); |
88 while (!element->IsUndefined()) { | 88 while (!element->IsUndefined()) { |
89 Code* code = Code::cast(element); | 89 Code* code = Code::cast(element); |
90 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); | 90 CHECK(code->kind() == Code::OPTIMIZED_FUNCTION); |
91 if (code->contains(addr)) return code; | 91 if (code->contains(addr)) return code; |
92 element = code->next_code_link(); | 92 element = code->next_code_link(); |
93 } | 93 } |
94 } | 94 } |
95 return NULL; | 95 return NULL; |
96 } | 96 } |
97 | 97 |
98 | 98 |
99 // We rely on this function not causing a GC. It is called from generated code | 99 // We rely on this function not causing a GC. It is called from generated code |
100 // without having a real stack frame in place. | 100 // without having a real stack frame in place. |
101 Deoptimizer* Deoptimizer::New(JSFunction* function, | 101 Deoptimizer* Deoptimizer::New(JSFunction* function, |
102 BailoutType type, | 102 BailoutType type, |
103 unsigned bailout_id, | 103 unsigned bailout_id, |
104 Address from, | 104 Address from, |
105 int fp_to_sp_delta, | 105 int fp_to_sp_delta, |
106 Isolate* isolate) { | 106 Isolate* isolate) { |
107 Deoptimizer* deoptimizer = new Deoptimizer(isolate, | 107 Deoptimizer* deoptimizer = new Deoptimizer(isolate, |
108 function, | 108 function, |
109 type, | 109 type, |
110 bailout_id, | 110 bailout_id, |
111 from, | 111 from, |
112 fp_to_sp_delta, | 112 fp_to_sp_delta, |
113 NULL); | 113 NULL); |
114 ASSERT(isolate->deoptimizer_data()->current_ == NULL); | 114 CHECK(isolate->deoptimizer_data()->current_ == NULL); |
115 isolate->deoptimizer_data()->current_ = deoptimizer; | 115 isolate->deoptimizer_data()->current_ = deoptimizer; |
116 return deoptimizer; | 116 return deoptimizer; |
117 } | 117 } |
118 | 118 |
119 | 119 |
120 // No larger than 2K on all platforms | 120 // No larger than 2K on all platforms |
121 static const int kDeoptTableMaxEpilogueCodeSize = 2 * KB; | 121 static const int kDeoptTableMaxEpilogueCodeSize = 2 * KB; |
122 | 122 |
123 | 123 |
124 size_t Deoptimizer::GetMaxDeoptTableSize() { | 124 size_t Deoptimizer::GetMaxDeoptTableSize() { |
125 int entries_size = | 125 int entries_size = |
126 Deoptimizer::kMaxNumberOfEntries * Deoptimizer::table_entry_size_; | 126 Deoptimizer::kMaxNumberOfEntries * Deoptimizer::table_entry_size_; |
127 int commit_page_size = static_cast<int>(OS::CommitPageSize()); | 127 int commit_page_size = static_cast<int>(OS::CommitPageSize()); |
128 int page_count = ((kDeoptTableMaxEpilogueCodeSize + entries_size - 1) / | 128 int page_count = ((kDeoptTableMaxEpilogueCodeSize + entries_size - 1) / |
129 commit_page_size) + 1; | 129 commit_page_size) + 1; |
130 return static_cast<size_t>(commit_page_size * page_count); | 130 return static_cast<size_t>(commit_page_size * page_count); |
131 } | 131 } |
132 | 132 |
133 | 133 |
134 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { | 134 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { |
135 Deoptimizer* result = isolate->deoptimizer_data()->current_; | 135 Deoptimizer* result = isolate->deoptimizer_data()->current_; |
136 ASSERT(result != NULL); | 136 CHECK_NE(result, NULL); |
137 result->DeleteFrameDescriptions(); | 137 result->DeleteFrameDescriptions(); |
138 isolate->deoptimizer_data()->current_ = NULL; | 138 isolate->deoptimizer_data()->current_ = NULL; |
139 return result; | 139 return result; |
140 } | 140 } |
141 | 141 |
142 | 142 |
143 int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) { | 143 int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) { |
144 if (jsframe_index == 0) return 0; | 144 if (jsframe_index == 0) return 0; |
145 | 145 |
146 int frame_index = 0; | 146 int frame_index = 0; |
147 while (jsframe_index >= 0) { | 147 while (jsframe_index >= 0) { |
148 FrameDescription* frame = output_[frame_index]; | 148 FrameDescription* frame = output_[frame_index]; |
149 if (frame->GetFrameType() == StackFrame::JAVA_SCRIPT) { | 149 if (frame->GetFrameType() == StackFrame::JAVA_SCRIPT) { |
150 jsframe_index--; | 150 jsframe_index--; |
151 } | 151 } |
152 frame_index++; | 152 frame_index++; |
153 } | 153 } |
154 | 154 |
155 return frame_index - 1; | 155 return frame_index - 1; |
156 } | 156 } |
157 | 157 |
158 | 158 |
159 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( | 159 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( |
160 JavaScriptFrame* frame, | 160 JavaScriptFrame* frame, |
161 int jsframe_index, | 161 int jsframe_index, |
162 Isolate* isolate) { | 162 Isolate* isolate) { |
163 ASSERT(frame->is_optimized()); | 163 CHECK(frame->is_optimized()); |
164 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL); | 164 CHECK(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL); |
165 | 165 |
166 // Get the function and code from the frame. | 166 // Get the function and code from the frame. |
167 JSFunction* function = frame->function(); | 167 JSFunction* function = frame->function(); |
168 Code* code = frame->LookupCode(); | 168 Code* code = frame->LookupCode(); |
169 | 169 |
170 // Locate the deoptimization point in the code. As we are at a call the | 170 // Locate the deoptimization point in the code. As we are at a call the |
171 // return address must be at a place in the code with deoptimization support. | 171 // return address must be at a place in the code with deoptimization support. |
172 SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc()); | 172 SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc()); |
173 int deoptimization_index = safepoint_entry.deoptimization_index(); | 173 int deoptimization_index = safepoint_entry.deoptimization_index(); |
174 ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex); | 174 CHECK_NE(deoptimization_index, Safepoint::kNoDeoptimizationIndex); |
175 | 175 |
176 // Always use the actual stack slots when calculating the fp to sp | 176 // Always use the actual stack slots when calculating the fp to sp |
177 // delta adding two for the function and context. | 177 // delta adding two for the function and context. |
178 unsigned stack_slots = code->stack_slots(); | 178 unsigned stack_slots = code->stack_slots(); |
179 unsigned fp_to_sp_delta = (stack_slots * kPointerSize) + | 179 unsigned fp_to_sp_delta = (stack_slots * kPointerSize) + |
180 StandardFrameConstants::kFixedFrameSizeFromFp; | 180 StandardFrameConstants::kFixedFrameSizeFromFp; |
181 | 181 |
182 Deoptimizer* deoptimizer = new Deoptimizer(isolate, | 182 Deoptimizer* deoptimizer = new Deoptimizer(isolate, |
183 function, | 183 function, |
184 Deoptimizer::DEBUGGER, | 184 Deoptimizer::DEBUGGER, |
185 deoptimization_index, | 185 deoptimization_index, |
186 frame->pc(), | 186 frame->pc(), |
187 fp_to_sp_delta, | 187 fp_to_sp_delta, |
188 code); | 188 code); |
189 Address tos = frame->fp() - fp_to_sp_delta; | 189 Address tos = frame->fp() - fp_to_sp_delta; |
190 deoptimizer->FillInputFrame(tos, frame); | 190 deoptimizer->FillInputFrame(tos, frame); |
191 | 191 |
192 // Calculate the output frames. | 192 // Calculate the output frames. |
193 Deoptimizer::ComputeOutputFrames(deoptimizer); | 193 Deoptimizer::ComputeOutputFrames(deoptimizer); |
194 | 194 |
195 // Create the GC safe output frame information and register it for GC | 195 // Create the GC safe output frame information and register it for GC |
196 // handling. | 196 // handling. |
197 ASSERT_LT(jsframe_index, deoptimizer->jsframe_count()); | 197 CHECK_LT(jsframe_index, deoptimizer->jsframe_count()); |
198 | 198 |
199 // Convert JS frame index into frame index. | 199 // Convert JS frame index into frame index. |
200 int frame_index = deoptimizer->ConvertJSFrameIndexToFrameIndex(jsframe_index); | 200 int frame_index = deoptimizer->ConvertJSFrameIndexToFrameIndex(jsframe_index); |
201 | 201 |
202 bool has_arguments_adaptor = | 202 bool has_arguments_adaptor = |
203 frame_index > 0 && | 203 frame_index > 0 && |
204 deoptimizer->output_[frame_index - 1]->GetFrameType() == | 204 deoptimizer->output_[frame_index - 1]->GetFrameType() == |
205 StackFrame::ARGUMENTS_ADAPTOR; | 205 StackFrame::ARGUMENTS_ADAPTOR; |
206 | 206 |
207 int construct_offset = has_arguments_adaptor ? 2 : 1; | 207 int construct_offset = has_arguments_adaptor ? 2 : 1; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 | 239 |
240 // Finished using the deoptimizer instance. | 240 // Finished using the deoptimizer instance. |
241 delete deoptimizer; | 241 delete deoptimizer; |
242 | 242 |
243 return info; | 243 return info; |
244 } | 244 } |
245 | 245 |
246 | 246 |
247 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, | 247 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, |
248 Isolate* isolate) { | 248 Isolate* isolate) { |
249 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == info); | 249 CHECK_EQ(isolate->deoptimizer_data()->deoptimized_frame_info_, info); |
250 delete info; | 250 delete info; |
251 isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL; | 251 isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL; |
252 } | 252 } |
253 | 253 |
254 | 254 |
255 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, | 255 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, |
256 int count, | 256 int count, |
257 BailoutType type) { | 257 BailoutType type) { |
258 TableEntryGenerator generator(masm, type, count); | 258 TableEntryGenerator generator(masm, type, count); |
259 generator.Generate(); | 259 generator.Generate(); |
260 } | 260 } |
261 | 261 |
262 | 262 |
263 void Deoptimizer::VisitAllOptimizedFunctionsForContext( | 263 void Deoptimizer::VisitAllOptimizedFunctionsForContext( |
264 Context* context, OptimizedFunctionVisitor* visitor) { | 264 Context* context, OptimizedFunctionVisitor* visitor) { |
265 DisallowHeapAllocation no_allocation; | 265 DisallowHeapAllocation no_allocation; |
266 | 266 |
267 ASSERT(context->IsNativeContext()); | 267 CHECK(context->IsNativeContext()); |
268 | 268 |
269 visitor->EnterContext(context); | 269 visitor->EnterContext(context); |
270 | 270 |
271 // Visit the list of optimized functions, removing elements that | 271 // Visit the list of optimized functions, removing elements that |
272 // no longer refer to optimized code. | 272 // no longer refer to optimized code. |
273 JSFunction* prev = NULL; | 273 JSFunction* prev = NULL; |
274 Object* element = context->OptimizedFunctionsListHead(); | 274 Object* element = context->OptimizedFunctionsListHead(); |
275 while (!element->IsUndefined()) { | 275 while (!element->IsUndefined()) { |
276 JSFunction* function = JSFunction::cast(element); | 276 JSFunction* function = JSFunction::cast(element); |
277 Object* next = function->next_function_link(); | 277 Object* next = function->next_function_link(); |
278 if (function->code()->kind() != Code::OPTIMIZED_FUNCTION || | 278 if (function->code()->kind() != Code::OPTIMIZED_FUNCTION || |
279 (visitor->VisitFunction(function), | 279 (visitor->VisitFunction(function), |
280 function->code()->kind() != Code::OPTIMIZED_FUNCTION)) { | 280 function->code()->kind() != Code::OPTIMIZED_FUNCTION)) { |
281 // The function no longer refers to optimized code, or the visitor | 281 // The function no longer refers to optimized code, or the visitor |
282 // changed the code to which it refers to no longer be optimized code. | 282 // changed the code to which it refers to no longer be optimized code. |
283 // Remove the function from this list. | 283 // Remove the function from this list. |
284 if (prev != NULL) { | 284 if (prev != NULL) { |
285 prev->set_next_function_link(next); | 285 prev->set_next_function_link(next); |
286 } else { | 286 } else { |
287 context->SetOptimizedFunctionsListHead(next); | 287 context->SetOptimizedFunctionsListHead(next); |
288 } | 288 } |
289 // The visitor should not alter the link directly. | 289 // The visitor should not alter the link directly. |
290 ASSERT(function->next_function_link() == next); | 290 CHECK_EQ(function->next_function_link(), next); |
291 // Set the next function link to undefined to indicate it is no longer | 291 // Set the next function link to undefined to indicate it is no longer |
292 // in the optimized functions list. | 292 // in the optimized functions list. |
293 function->set_next_function_link(context->GetHeap()->undefined_value()); | 293 function->set_next_function_link(context->GetHeap()->undefined_value()); |
294 } else { | 294 } else { |
295 // The visitor should not alter the link directly. | 295 // The visitor should not alter the link directly. |
296 ASSERT(function->next_function_link() == next); | 296 CHECK_EQ(function->next_function_link(), next); |
297 // preserve this element. | 297 // preserve this element. |
298 prev = function; | 298 prev = function; |
299 } | 299 } |
300 element = next; | 300 element = next; |
301 } | 301 } |
302 | 302 |
303 visitor->LeaveContext(context); | 303 visitor->LeaveContext(context); |
304 } | 304 } |
305 | 305 |
306 | 306 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 // Move marked code from the optimized code list to the deoptimized | 388 // Move marked code from the optimized code list to the deoptimized |
389 // code list, collecting them into a ZoneList. | 389 // code list, collecting them into a ZoneList. |
390 Zone zone(isolate); | 390 Zone zone(isolate); |
391 ZoneList<Code*> codes(10, &zone); | 391 ZoneList<Code*> codes(10, &zone); |
392 | 392 |
393 // Walk over all optimized code objects in this native context. | 393 // Walk over all optimized code objects in this native context. |
394 Code* prev = NULL; | 394 Code* prev = NULL; |
395 Object* element = context->OptimizedCodeListHead(); | 395 Object* element = context->OptimizedCodeListHead(); |
396 while (!element->IsUndefined()) { | 396 while (!element->IsUndefined()) { |
397 Code* code = Code::cast(element); | 397 Code* code = Code::cast(element); |
398 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); | 398 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION); |
399 Object* next = code->next_code_link(); | 399 Object* next = code->next_code_link(); |
400 if (code->marked_for_deoptimization()) { | 400 if (code->marked_for_deoptimization()) { |
401 // Put the code into the list for later patching. | 401 // Put the code into the list for later patching. |
402 codes.Add(code, &zone); | 402 codes.Add(code, &zone); |
403 | 403 |
404 if (prev != NULL) { | 404 if (prev != NULL) { |
405 // Skip this code in the optimized code list. | 405 // Skip this code in the optimized code list. |
406 prev->set_next_code_link(next); | 406 prev->set_next_code_link(next); |
407 } else { | 407 } else { |
408 // There was no previous node, the next node is the new head. | 408 // There was no previous node, the next node is the new head. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 | 476 |
477 | 477 |
478 void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) { | 478 void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) { |
479 if (FLAG_trace_deopt) { | 479 if (FLAG_trace_deopt) { |
480 CodeTracer::Scope scope(object->GetHeap()->isolate()->GetCodeTracer()); | 480 CodeTracer::Scope scope(object->GetHeap()->isolate()->GetCodeTracer()); |
481 PrintF(scope.file(), "[deoptimize global object @ 0x%08" V8PRIxPTR "]\n", | 481 PrintF(scope.file(), "[deoptimize global object @ 0x%08" V8PRIxPTR "]\n", |
482 reinterpret_cast<intptr_t>(object)); | 482 reinterpret_cast<intptr_t>(object)); |
483 } | 483 } |
484 if (object->IsJSGlobalProxy()) { | 484 if (object->IsJSGlobalProxy()) { |
485 Object* proto = object->GetPrototype(); | 485 Object* proto = object->GetPrototype(); |
486 ASSERT(proto->IsJSGlobalObject()); | 486 CHECK(proto->IsJSGlobalObject()); |
487 Context* native_context = GlobalObject::cast(proto)->native_context(); | 487 Context* native_context = GlobalObject::cast(proto)->native_context(); |
488 MarkAllCodeForContext(native_context); | 488 MarkAllCodeForContext(native_context); |
489 DeoptimizeMarkedCodeForContext(native_context); | 489 DeoptimizeMarkedCodeForContext(native_context); |
490 } else if (object->IsGlobalObject()) { | 490 } else if (object->IsGlobalObject()) { |
491 Context* native_context = GlobalObject::cast(object)->native_context(); | 491 Context* native_context = GlobalObject::cast(object)->native_context(); |
492 MarkAllCodeForContext(native_context); | 492 MarkAllCodeForContext(native_context); |
493 DeoptimizeMarkedCodeForContext(native_context); | 493 DeoptimizeMarkedCodeForContext(native_context); |
494 } | 494 } |
495 } | 495 } |
496 | 496 |
497 | 497 |
498 void Deoptimizer::MarkAllCodeForContext(Context* context) { | 498 void Deoptimizer::MarkAllCodeForContext(Context* context) { |
499 Object* element = context->OptimizedCodeListHead(); | 499 Object* element = context->OptimizedCodeListHead(); |
500 while (!element->IsUndefined()) { | 500 while (!element->IsUndefined()) { |
501 Code* code = Code::cast(element); | 501 Code* code = Code::cast(element); |
502 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); | 502 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION); |
503 code->set_marked_for_deoptimization(true); | 503 code->set_marked_for_deoptimization(true); |
504 element = code->next_code_link(); | 504 element = code->next_code_link(); |
505 } | 505 } |
506 } | 506 } |
507 | 507 |
508 | 508 |
509 void Deoptimizer::DeoptimizeFunction(JSFunction* function) { | 509 void Deoptimizer::DeoptimizeFunction(JSFunction* function) { |
510 Code* code = function->code(); | 510 Code* code = function->code(); |
511 if (code->kind() == Code::OPTIMIZED_FUNCTION) { | 511 if (code->kind() == Code::OPTIMIZED_FUNCTION) { |
512 // Mark the code for deoptimization and unlink any functions that also | 512 // Mark the code for deoptimization and unlink any functions that also |
(...skipping 14 matching lines...) Expand all Loading... |
527 StackFrame::Type frame_type) { | 527 StackFrame::Type frame_type) { |
528 switch (deopt_type) { | 528 switch (deopt_type) { |
529 case EAGER: | 529 case EAGER: |
530 case SOFT: | 530 case SOFT: |
531 case LAZY: | 531 case LAZY: |
532 case DEBUGGER: | 532 case DEBUGGER: |
533 return (frame_type == StackFrame::STUB) | 533 return (frame_type == StackFrame::STUB) |
534 ? FLAG_trace_stub_failures | 534 ? FLAG_trace_stub_failures |
535 : FLAG_trace_deopt; | 535 : FLAG_trace_deopt; |
536 } | 536 } |
537 UNREACHABLE(); | 537 FATAL("Unsupported deopt type"); |
538 return false; | 538 return false; |
539 } | 539 } |
540 | 540 |
541 | 541 |
542 const char* Deoptimizer::MessageFor(BailoutType type) { | 542 const char* Deoptimizer::MessageFor(BailoutType type) { |
543 switch (type) { | 543 switch (type) { |
544 case EAGER: return "eager"; | 544 case EAGER: return "eager"; |
545 case SOFT: return "soft"; | 545 case SOFT: return "soft"; |
546 case LAZY: return "lazy"; | 546 case LAZY: return "lazy"; |
547 case DEBUGGER: return "debugger"; | 547 case DEBUGGER: return "debugger"; |
548 } | 548 } |
549 UNREACHABLE(); | 549 FATAL("Unsupported deopt type"); |
550 return NULL; | 550 return NULL; |
551 } | 551 } |
552 | 552 |
553 | 553 |
554 Deoptimizer::Deoptimizer(Isolate* isolate, | 554 Deoptimizer::Deoptimizer(Isolate* isolate, |
555 JSFunction* function, | 555 JSFunction* function, |
556 BailoutType type, | 556 BailoutType type, |
557 unsigned bailout_id, | 557 unsigned bailout_id, |
558 Address from, | 558 Address from, |
559 int fp_to_sp_delta, | 559 int fp_to_sp_delta, |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
629 case Deoptimizer::LAZY: { | 629 case Deoptimizer::LAZY: { |
630 Code* compiled_code = FindDeoptimizingCode(from_); | 630 Code* compiled_code = FindDeoptimizingCode(from_); |
631 return (compiled_code == NULL) | 631 return (compiled_code == NULL) |
632 ? static_cast<Code*>(isolate_->FindCodeObject(from_)) | 632 ? static_cast<Code*>(isolate_->FindCodeObject(from_)) |
633 : compiled_code; | 633 : compiled_code; |
634 } | 634 } |
635 case Deoptimizer::DEBUGGER: | 635 case Deoptimizer::DEBUGGER: |
636 ASSERT(optimized_code->contains(from_)); | 636 ASSERT(optimized_code->contains(from_)); |
637 return optimized_code; | 637 return optimized_code; |
638 } | 638 } |
639 UNREACHABLE(); | 639 FATAL("Could not find code for optimized function"); |
640 return NULL; | 640 return NULL; |
641 } | 641 } |
642 | 642 |
643 | 643 |
644 void Deoptimizer::PrintFunctionName() { | 644 void Deoptimizer::PrintFunctionName() { |
645 if (function_->IsJSFunction()) { | 645 if (function_->IsJSFunction()) { |
646 function_->PrintName(trace_scope_->file()); | 646 function_->PrintName(trace_scope_->file()); |
647 } else { | 647 } else { |
648 PrintF(trace_scope_->file(), | 648 PrintF(trace_scope_->file(), |
649 "%s", Code::Kind2String(compiled_code_->kind())); | 649 "%s", Code::Kind2String(compiled_code_->kind())); |
(...skipping 22 matching lines...) Expand all Loading... |
672 delete disallow_heap_allocation_; | 672 delete disallow_heap_allocation_; |
673 disallow_heap_allocation_ = NULL; | 673 disallow_heap_allocation_ = NULL; |
674 #endif // DEBUG | 674 #endif // DEBUG |
675 } | 675 } |
676 | 676 |
677 | 677 |
678 Address Deoptimizer::GetDeoptimizationEntry(Isolate* isolate, | 678 Address Deoptimizer::GetDeoptimizationEntry(Isolate* isolate, |
679 int id, | 679 int id, |
680 BailoutType type, | 680 BailoutType type, |
681 GetEntryMode mode) { | 681 GetEntryMode mode) { |
682 ASSERT(id >= 0); | 682 CHECK_GE(id, 0); |
683 if (id >= kMaxNumberOfEntries) return NULL; | 683 if (id >= kMaxNumberOfEntries) return NULL; |
684 if (mode == ENSURE_ENTRY_CODE) { | 684 if (mode == ENSURE_ENTRY_CODE) { |
685 EnsureCodeForDeoptimizationEntry(isolate, type, id); | 685 EnsureCodeForDeoptimizationEntry(isolate, type, id); |
686 } else { | 686 } else { |
687 ASSERT(mode == CALCULATE_ENTRY_ADDRESS); | 687 CHECK_EQ(mode, CALCULATE_ENTRY_ADDRESS); |
688 } | 688 } |
689 DeoptimizerData* data = isolate->deoptimizer_data(); | 689 DeoptimizerData* data = isolate->deoptimizer_data(); |
690 ASSERT(type < kBailoutTypesWithCodeEntry); | 690 CHECK_LT(type, kBailoutTypesWithCodeEntry); |
691 MemoryChunk* base = data->deopt_entry_code_[type]; | 691 MemoryChunk* base = data->deopt_entry_code_[type]; |
692 return base->area_start() + (id * table_entry_size_); | 692 return base->area_start() + (id * table_entry_size_); |
693 } | 693 } |
694 | 694 |
695 | 695 |
696 int Deoptimizer::GetDeoptimizationId(Isolate* isolate, | 696 int Deoptimizer::GetDeoptimizationId(Isolate* isolate, |
697 Address addr, | 697 Address addr, |
698 BailoutType type) { | 698 BailoutType type) { |
699 DeoptimizerData* data = isolate->deoptimizer_data(); | 699 DeoptimizerData* data = isolate->deoptimizer_data(); |
700 MemoryChunk* base = data->deopt_entry_code_[type]; | 700 MemoryChunk* base = data->deopt_entry_code_[type]; |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
843 case Translation::INT32_REGISTER: | 843 case Translation::INT32_REGISTER: |
844 case Translation::UINT32_REGISTER: | 844 case Translation::UINT32_REGISTER: |
845 case Translation::DOUBLE_REGISTER: | 845 case Translation::DOUBLE_REGISTER: |
846 case Translation::STACK_SLOT: | 846 case Translation::STACK_SLOT: |
847 case Translation::INT32_STACK_SLOT: | 847 case Translation::INT32_STACK_SLOT: |
848 case Translation::UINT32_STACK_SLOT: | 848 case Translation::UINT32_STACK_SLOT: |
849 case Translation::DOUBLE_STACK_SLOT: | 849 case Translation::DOUBLE_STACK_SLOT: |
850 case Translation::LITERAL: | 850 case Translation::LITERAL: |
851 case Translation::ARGUMENTS_OBJECT: | 851 case Translation::ARGUMENTS_OBJECT: |
852 default: | 852 default: |
853 UNREACHABLE(); | 853 FATAL("Unsupported translation"); |
854 break; | 854 break; |
855 } | 855 } |
856 } | 856 } |
857 | 857 |
858 // Print some helpful diagnostic information. | 858 // Print some helpful diagnostic information. |
859 if (trace_scope_ != NULL) { | 859 if (trace_scope_ != NULL) { |
860 double ms = timer.Elapsed().InMillisecondsF(); | 860 double ms = timer.Elapsed().InMillisecondsF(); |
861 int index = output_count_ - 1; // Index of the topmost frame. | 861 int index = output_count_ - 1; // Index of the topmost frame. |
862 JSFunction* function = output_[index]->GetFunction(); | 862 JSFunction* function = output_[index]->GetFunction(); |
863 PrintF(trace_scope_->file(), | 863 PrintF(trace_scope_->file(), |
(...skipping 18 matching lines...) Expand all Loading... |
882 | 882 |
883 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, | 883 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, |
884 int frame_index) { | 884 int frame_index) { |
885 BailoutId node_id = BailoutId(iterator->Next()); | 885 BailoutId node_id = BailoutId(iterator->Next()); |
886 JSFunction* function; | 886 JSFunction* function; |
887 if (frame_index != 0) { | 887 if (frame_index != 0) { |
888 function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 888 function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
889 } else { | 889 } else { |
890 int closure_id = iterator->Next(); | 890 int closure_id = iterator->Next(); |
891 USE(closure_id); | 891 USE(closure_id); |
892 ASSERT_EQ(Translation::kSelfLiteralId, closure_id); | 892 CHECK_EQ(Translation::kSelfLiteralId, closure_id); |
893 function = function_; | 893 function = function_; |
894 } | 894 } |
895 unsigned height = iterator->Next(); | 895 unsigned height = iterator->Next(); |
896 unsigned height_in_bytes = height * kPointerSize; | 896 unsigned height_in_bytes = height * kPointerSize; |
897 if (trace_scope_ != NULL) { | 897 if (trace_scope_ != NULL) { |
898 PrintF(trace_scope_->file(), " translating "); | 898 PrintF(trace_scope_->file(), " translating "); |
899 function->PrintName(trace_scope_->file()); | 899 function->PrintName(trace_scope_->file()); |
900 PrintF(trace_scope_->file(), | 900 PrintF(trace_scope_->file(), |
901 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); | 901 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); |
902 } | 902 } |
903 | 903 |
904 // The 'fixed' part of the frame consists of the incoming parameters and | 904 // The 'fixed' part of the frame consists of the incoming parameters and |
905 // the part described by JavaScriptFrameConstants. | 905 // the part described by JavaScriptFrameConstants. |
906 unsigned fixed_frame_size = ComputeFixedSize(function); | 906 unsigned fixed_frame_size = ComputeFixedSize(function); |
907 unsigned input_frame_size = input_->GetFrameSize(); | 907 unsigned input_frame_size = input_->GetFrameSize(); |
908 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 908 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
909 | 909 |
910 // Allocate and store the output frame description. | 910 // Allocate and store the output frame description. |
911 FrameDescription* output_frame = | 911 FrameDescription* output_frame = |
912 new(output_frame_size) FrameDescription(output_frame_size, function); | 912 new(output_frame_size) FrameDescription(output_frame_size, function); |
913 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); | 913 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); |
914 | 914 |
915 bool is_bottommost = (0 == frame_index); | 915 bool is_bottommost = (0 == frame_index); |
916 bool is_topmost = (output_count_ - 1 == frame_index); | 916 bool is_topmost = (output_count_ - 1 == frame_index); |
917 ASSERT(frame_index >= 0 && frame_index < output_count_); | 917 CHECK(frame_index >= 0 && frame_index < output_count_); |
918 ASSERT(output_[frame_index] == NULL); | 918 CHECK_EQ(output_[frame_index], NULL); |
919 output_[frame_index] = output_frame; | 919 output_[frame_index] = output_frame; |
920 | 920 |
921 // The top address for the bottommost output frame can be computed from | 921 // The top address for the bottommost output frame can be computed from |
922 // the input frame pointer and the output frame's height. For all | 922 // the input frame pointer and the output frame's height. For all |
923 // subsequent output frames, it can be computed from the previous one's | 923 // subsequent output frames, it can be computed from the previous one's |
924 // top address and the current frame's size. | 924 // top address and the current frame's size. |
925 Register fp_reg = JavaScriptFrame::fp_register(); | 925 Register fp_reg = JavaScriptFrame::fp_register(); |
926 intptr_t top_address; | 926 intptr_t top_address; |
927 if (is_bottommost) { | 927 if (is_bottommost) { |
928 // Determine whether the input frame contains alignment padding. | 928 // Determine whether the input frame contains alignment padding. |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1052 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1052 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
1053 V8PRIxPTR "; function\n", | 1053 V8PRIxPTR "; function\n", |
1054 top_address + output_offset, output_offset, value); | 1054 top_address + output_offset, output_offset, value); |
1055 } | 1055 } |
1056 | 1056 |
1057 // Translate the rest of the frame. | 1057 // Translate the rest of the frame. |
1058 for (unsigned i = 0; i < height; ++i) { | 1058 for (unsigned i = 0; i < height; ++i) { |
1059 output_offset -= kPointerSize; | 1059 output_offset -= kPointerSize; |
1060 DoTranslateCommand(iterator, frame_index, output_offset); | 1060 DoTranslateCommand(iterator, frame_index, output_offset); |
1061 } | 1061 } |
1062 ASSERT(0 == output_offset); | 1062 CHECK_EQ(0, output_offset); |
1063 | 1063 |
1064 // Compute this frame's PC, state, and continuation. | 1064 // Compute this frame's PC, state, and continuation. |
1065 Code* non_optimized_code = function->shared()->code(); | 1065 Code* non_optimized_code = function->shared()->code(); |
1066 FixedArray* raw_data = non_optimized_code->deoptimization_data(); | 1066 FixedArray* raw_data = non_optimized_code->deoptimization_data(); |
1067 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); | 1067 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); |
1068 Address start = non_optimized_code->instruction_start(); | 1068 Address start = non_optimized_code->instruction_start(); |
1069 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); | 1069 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); |
1070 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); | 1070 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); |
1071 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); | 1071 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); |
1072 output_frame->SetPc(pc_value); | 1072 output_frame->SetPc(pc_value); |
(...skipping 16 matching lines...) Expand all Loading... |
1089 | 1089 |
1090 // Set the continuation for the topmost frame. | 1090 // Set the continuation for the topmost frame. |
1091 if (is_topmost && bailout_type_ != DEBUGGER) { | 1091 if (is_topmost && bailout_type_ != DEBUGGER) { |
1092 Builtins* builtins = isolate_->builtins(); | 1092 Builtins* builtins = isolate_->builtins(); |
1093 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); | 1093 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); |
1094 if (bailout_type_ == LAZY) { | 1094 if (bailout_type_ == LAZY) { |
1095 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); | 1095 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
1096 } else if (bailout_type_ == SOFT) { | 1096 } else if (bailout_type_ == SOFT) { |
1097 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); | 1097 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); |
1098 } else { | 1098 } else { |
1099 ASSERT(bailout_type_ == EAGER); | 1099 CHECK_EQ(bailout_type_, EAGER); |
1100 } | 1100 } |
1101 output_frame->SetContinuation( | 1101 output_frame->SetContinuation( |
1102 reinterpret_cast<intptr_t>(continuation->entry())); | 1102 reinterpret_cast<intptr_t>(continuation->entry())); |
1103 } | 1103 } |
1104 } | 1104 } |
1105 | 1105 |
1106 | 1106 |
1107 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, | 1107 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, |
1108 int frame_index) { | 1108 int frame_index) { |
1109 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 1109 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
1110 unsigned height = iterator->Next(); | 1110 unsigned height = iterator->Next(); |
1111 unsigned height_in_bytes = height * kPointerSize; | 1111 unsigned height_in_bytes = height * kPointerSize; |
1112 if (trace_scope_ != NULL) { | 1112 if (trace_scope_ != NULL) { |
1113 PrintF(trace_scope_->file(), | 1113 PrintF(trace_scope_->file(), |
1114 " translating arguments adaptor => height=%d\n", height_in_bytes); | 1114 " translating arguments adaptor => height=%d\n", height_in_bytes); |
1115 } | 1115 } |
1116 | 1116 |
1117 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize; | 1117 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize; |
1118 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 1118 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
1119 | 1119 |
1120 // Allocate and store the output frame description. | 1120 // Allocate and store the output frame description. |
1121 FrameDescription* output_frame = | 1121 FrameDescription* output_frame = |
1122 new(output_frame_size) FrameDescription(output_frame_size, function); | 1122 new(output_frame_size) FrameDescription(output_frame_size, function); |
1123 output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR); | 1123 output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR); |
1124 | 1124 |
1125 // Arguments adaptor can not be topmost or bottommost. | 1125 // Arguments adaptor can not be topmost or bottommost. |
1126 ASSERT(frame_index > 0 && frame_index < output_count_ - 1); | 1126 CHECK(frame_index > 0 && frame_index < output_count_ - 1); |
1127 ASSERT(output_[frame_index] == NULL); | 1127 CHECK(output_[frame_index] == NULL); |
1128 output_[frame_index] = output_frame; | 1128 output_[frame_index] = output_frame; |
1129 | 1129 |
1130 // The top address of the frame is computed from the previous | 1130 // The top address of the frame is computed from the previous |
1131 // frame's top and this frame's size. | 1131 // frame's top and this frame's size. |
1132 intptr_t top_address; | 1132 intptr_t top_address; |
1133 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; | 1133 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
1134 output_frame->SetTop(top_address); | 1134 output_frame->SetTop(top_address); |
1135 | 1135 |
1136 // Compute the incoming parameter translation. | 1136 // Compute the incoming parameter translation. |
1137 int parameter_count = height; | 1137 int parameter_count = height; |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1263 int parameter_count = height; | 1263 int parameter_count = height; |
1264 unsigned output_offset = output_frame_size; | 1264 unsigned output_offset = output_frame_size; |
1265 for (int i = 0; i < parameter_count; ++i) { | 1265 for (int i = 0; i < parameter_count; ++i) { |
1266 output_offset -= kPointerSize; | 1266 output_offset -= kPointerSize; |
1267 int deferred_object_index = deferred_objects_.length(); | 1267 int deferred_object_index = deferred_objects_.length(); |
1268 DoTranslateCommand(iterator, frame_index, output_offset); | 1268 DoTranslateCommand(iterator, frame_index, output_offset); |
1269 // The allocated receiver of a construct stub frame is passed as the | 1269 // The allocated receiver of a construct stub frame is passed as the |
1270 // receiver parameter through the translation. It might be encoding | 1270 // receiver parameter through the translation. It might be encoding |
1271 // a captured object, patch the slot address for a captured object. | 1271 // a captured object, patch the slot address for a captured object. |
1272 if (i == 0 && deferred_objects_.length() > deferred_object_index) { | 1272 if (i == 0 && deferred_objects_.length() > deferred_object_index) { |
1273 ASSERT(!deferred_objects_[deferred_object_index].is_arguments()); | 1273 CHECK(!deferred_objects_[deferred_object_index].is_arguments()); |
1274 deferred_objects_[deferred_object_index].patch_slot_address(top_address); | 1274 deferred_objects_[deferred_object_index].patch_slot_address(top_address); |
1275 } | 1275 } |
1276 } | 1276 } |
1277 | 1277 |
1278 // Read caller's PC from the previous frame. | 1278 // Read caller's PC from the previous frame. |
1279 output_offset -= kPCOnStackSize; | 1279 output_offset -= kPCOnStackSize; |
1280 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); | 1280 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); |
1281 output_frame->SetCallerPc(output_offset, callers_pc); | 1281 output_frame->SetCallerPc(output_offset, callers_pc); |
1282 if (trace_scope_ != NULL) { | 1282 if (trace_scope_ != NULL) { |
1283 PrintF(trace_scope_->file(), | 1283 PrintF(trace_scope_->file(), |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1374 output_offset -= kPointerSize; | 1374 output_offset -= kPointerSize; |
1375 value = output_frame->GetFrameSlot(output_frame_size - kPointerSize); | 1375 value = output_frame->GetFrameSlot(output_frame_size - kPointerSize); |
1376 output_frame->SetFrameSlot(output_offset, value); | 1376 output_frame->SetFrameSlot(output_offset, value); |
1377 if (trace_scope_ != NULL) { | 1377 if (trace_scope_ != NULL) { |
1378 PrintF(trace_scope_->file(), | 1378 PrintF(trace_scope_->file(), |
1379 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1379 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
1380 V8PRIxPTR " ; allocated receiver\n", | 1380 V8PRIxPTR " ; allocated receiver\n", |
1381 top_address + output_offset, output_offset, value); | 1381 top_address + output_offset, output_offset, value); |
1382 } | 1382 } |
1383 | 1383 |
1384 ASSERT(0 == output_offset); | 1384 CHECK_EQ(0, output_offset); |
1385 | 1385 |
1386 intptr_t pc = reinterpret_cast<intptr_t>( | 1386 intptr_t pc = reinterpret_cast<intptr_t>( |
1387 construct_stub->instruction_start() + | 1387 construct_stub->instruction_start() + |
1388 isolate_->heap()->construct_stub_deopt_pc_offset()->value()); | 1388 isolate_->heap()->construct_stub_deopt_pc_offset()->value()); |
1389 output_frame->SetPc(pc); | 1389 output_frame->SetPc(pc); |
1390 if (FLAG_enable_ool_constant_pool) { | 1390 if (FLAG_enable_ool_constant_pool) { |
1391 intptr_t constant_pool_value = | 1391 intptr_t constant_pool_value = |
1392 reinterpret_cast<intptr_t>(construct_stub->constant_pool()); | 1392 reinterpret_cast<intptr_t>(construct_stub->constant_pool()); |
1393 output_frame->SetConstantPool(constant_pool_value); | 1393 output_frame->SetConstantPool(constant_pool_value); |
1394 } | 1394 } |
(...skipping 25 matching lines...) Expand all Loading... |
1420 (is_setter_stub_frame ? 1 : 0); | 1420 (is_setter_stub_frame ? 1 : 0); |
1421 unsigned fixed_frame_size = fixed_frame_entries * kPointerSize; | 1421 unsigned fixed_frame_size = fixed_frame_entries * kPointerSize; |
1422 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 1422 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
1423 | 1423 |
1424 // Allocate and store the output frame description. | 1424 // Allocate and store the output frame description. |
1425 FrameDescription* output_frame = | 1425 FrameDescription* output_frame = |
1426 new(output_frame_size) FrameDescription(output_frame_size, accessor); | 1426 new(output_frame_size) FrameDescription(output_frame_size, accessor); |
1427 output_frame->SetFrameType(StackFrame::INTERNAL); | 1427 output_frame->SetFrameType(StackFrame::INTERNAL); |
1428 | 1428 |
1429 // A frame for an accessor stub can not be the topmost or bottommost one. | 1429 // A frame for an accessor stub can not be the topmost or bottommost one. |
1430 ASSERT(frame_index > 0 && frame_index < output_count_ - 1); | 1430 CHECK(frame_index > 0 && frame_index < output_count_ - 1); |
1431 ASSERT(output_[frame_index] == NULL); | 1431 CHECK_EQ(output_[frame_index], NULL); |
1432 output_[frame_index] = output_frame; | 1432 output_[frame_index] = output_frame; |
1433 | 1433 |
1434 // The top address of the frame is computed from the previous frame's top and | 1434 // The top address of the frame is computed from the previous frame's top and |
1435 // this frame's size. | 1435 // this frame's size. |
1436 intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size; | 1436 intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
1437 output_frame->SetTop(top_address); | 1437 output_frame->SetTop(top_address); |
1438 | 1438 |
1439 unsigned output_offset = output_frame_size; | 1439 unsigned output_offset = output_frame_size; |
1440 | 1440 |
1441 // Read caller's PC from the previous frame. | 1441 // Read caller's PC from the previous frame. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1505 value = reinterpret_cast<intptr_t>(accessor_stub); | 1505 value = reinterpret_cast<intptr_t>(accessor_stub); |
1506 output_frame->SetFrameSlot(output_offset, value); | 1506 output_frame->SetFrameSlot(output_offset, value); |
1507 if (trace_scope_ != NULL) { | 1507 if (trace_scope_ != NULL) { |
1508 PrintF(trace_scope_->file(), | 1508 PrintF(trace_scope_->file(), |
1509 " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR | 1509 " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR |
1510 " ; code object\n", | 1510 " ; code object\n", |
1511 top_address + output_offset, output_offset, value); | 1511 top_address + output_offset, output_offset, value); |
1512 } | 1512 } |
1513 | 1513 |
1514 // Skip receiver. | 1514 // Skip receiver. |
1515 Translation::Opcode opcode = | 1515 DoTranslateObjectAndSkip(iterator); |
1516 static_cast<Translation::Opcode>(iterator->Next()); | |
1517 iterator->Skip(Translation::NumberOfOperandsFor(opcode)); | |
1518 | 1516 |
1519 if (is_setter_stub_frame) { | 1517 if (is_setter_stub_frame) { |
1520 // The implicit return value was part of the artificial setter stub | 1518 // The implicit return value was part of the artificial setter stub |
1521 // environment. | 1519 // environment. |
1522 output_offset -= kPointerSize; | 1520 output_offset -= kPointerSize; |
1523 DoTranslateCommand(iterator, frame_index, output_offset); | 1521 DoTranslateCommand(iterator, frame_index, output_offset); |
1524 } | 1522 } |
1525 | 1523 |
1526 ASSERT(0 == output_offset); | 1524 CHECK_EQ(output_offset, 0); |
1527 | 1525 |
1528 Smi* offset = is_setter_stub_frame ? | 1526 Smi* offset = is_setter_stub_frame ? |
1529 isolate_->heap()->setter_stub_deopt_pc_offset() : | 1527 isolate_->heap()->setter_stub_deopt_pc_offset() : |
1530 isolate_->heap()->getter_stub_deopt_pc_offset(); | 1528 isolate_->heap()->getter_stub_deopt_pc_offset(); |
1531 intptr_t pc = reinterpret_cast<intptr_t>( | 1529 intptr_t pc = reinterpret_cast<intptr_t>( |
1532 accessor_stub->instruction_start() + offset->value()); | 1530 accessor_stub->instruction_start() + offset->value()); |
1533 output_frame->SetPc(pc); | 1531 output_frame->SetPc(pc); |
1534 if (FLAG_enable_ool_constant_pool) { | 1532 if (FLAG_enable_ool_constant_pool) { |
1535 intptr_t constant_pool_value = | 1533 intptr_t constant_pool_value = |
1536 reinterpret_cast<intptr_t>(accessor_stub->constant_pool()); | 1534 reinterpret_cast<intptr_t>(accessor_stub->constant_pool()); |
(...skipping 29 matching lines...) Expand all Loading... |
1566 // and spilled to stack | .... | | 1564 // and spilled to stack | .... | |
1567 // +-------------------------+ | 1565 // +-------------------------+ |
1568 // | caller stack param n | | 1566 // | caller stack param n | |
1569 // +-------------------------+<-spreg | 1567 // +-------------------------+<-spreg |
1570 // reg = number of parameters | 1568 // reg = number of parameters |
1571 // reg = failure handler address | 1569 // reg = failure handler address |
1572 // reg = saved frame | 1570 // reg = saved frame |
1573 // reg = JSFunction context | 1571 // reg = JSFunction context |
1574 // | 1572 // |
1575 | 1573 |
1576 ASSERT(compiled_code_->is_crankshafted() && | 1574 CHECK(compiled_code_->is_crankshafted() && |
1577 compiled_code_->kind() != Code::OPTIMIZED_FUNCTION); | 1575 compiled_code_->kind() != Code::OPTIMIZED_FUNCTION); |
1578 int major_key = compiled_code_->major_key(); | 1576 int major_key = compiled_code_->major_key(); |
1579 CodeStubInterfaceDescriptor* descriptor = | 1577 CodeStubInterfaceDescriptor* descriptor = |
1580 isolate_->code_stub_interface_descriptor(major_key); | 1578 isolate_->code_stub_interface_descriptor(major_key); |
1581 | 1579 |
1582 // The output frame must have room for all pushed register parameters | 1580 // The output frame must have room for all pushed register parameters |
1583 // and the standard stack frame slots. Include space for an argument | 1581 // and the standard stack frame slots. Include space for an argument |
1584 // object to the callee and optionally the space to pass the argument | 1582 // object to the callee and optionally the space to pass the argument |
1585 // object to the stub failure handler. | 1583 // object to the stub failure handler. |
1586 ASSERT(descriptor->register_param_count_ >= 0); | 1584 CHECK_GE(descriptor->register_param_count_, 0); |
1587 int height_in_bytes = kPointerSize * descriptor->register_param_count_ + | 1585 int height_in_bytes = kPointerSize * descriptor->register_param_count_ + |
1588 sizeof(Arguments) + kPointerSize; | 1586 sizeof(Arguments) + kPointerSize; |
1589 int fixed_frame_size = StandardFrameConstants::kFixedFrameSize; | 1587 int fixed_frame_size = StandardFrameConstants::kFixedFrameSize; |
1590 int input_frame_size = input_->GetFrameSize(); | 1588 int input_frame_size = input_->GetFrameSize(); |
1591 int output_frame_size = height_in_bytes + fixed_frame_size; | 1589 int output_frame_size = height_in_bytes + fixed_frame_size; |
1592 if (trace_scope_ != NULL) { | 1590 if (trace_scope_ != NULL) { |
1593 PrintF(trace_scope_->file(), | 1591 PrintF(trace_scope_->file(), |
1594 " translating %s => StubFailureTrampolineStub, height=%d\n", | 1592 " translating %s => StubFailureTrampolineStub, height=%d\n", |
1595 CodeStub::MajorName(static_cast<CodeStub::Major>(major_key), false), | 1593 CodeStub::MajorName(static_cast<CodeStub::Major>(major_key), false), |
1596 height_in_bytes); | 1594 height_in_bytes); |
1597 } | 1595 } |
1598 | 1596 |
1599 // The stub failure trampoline is a single frame. | 1597 // The stub failure trampoline is a single frame. |
1600 FrameDescription* output_frame = | 1598 FrameDescription* output_frame = |
1601 new(output_frame_size) FrameDescription(output_frame_size, NULL); | 1599 new(output_frame_size) FrameDescription(output_frame_size, NULL); |
1602 output_frame->SetFrameType(StackFrame::STUB_FAILURE_TRAMPOLINE); | 1600 output_frame->SetFrameType(StackFrame::STUB_FAILURE_TRAMPOLINE); |
1603 ASSERT(frame_index == 0); | 1601 CHECK_EQ(frame_index, 0); |
1604 output_[frame_index] = output_frame; | 1602 output_[frame_index] = output_frame; |
1605 | 1603 |
1606 // The top address for the output frame can be computed from the input | 1604 // The top address for the output frame can be computed from the input |
1607 // frame pointer and the output frame's height. Subtract space for the | 1605 // frame pointer and the output frame's height. Subtract space for the |
1608 // context and function slots. | 1606 // context and function slots. |
1609 Register fp_reg = StubFailureTrampolineFrame::fp_register(); | 1607 Register fp_reg = StubFailureTrampolineFrame::fp_register(); |
1610 intptr_t top_address = input_->GetRegister(fp_reg.code()) - | 1608 intptr_t top_address = input_->GetRegister(fp_reg.code()) - |
1611 StandardFrameConstants::kFixedFrameSizeFromFp - height_in_bytes; | 1609 StandardFrameConstants::kFixedFrameSizeFromFp - height_in_bytes; |
1612 output_frame->SetTop(top_address); | 1610 output_frame->SetTop(top_address); |
1613 | 1611 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1651 } | 1649 } |
1652 } | 1650 } |
1653 | 1651 |
1654 // The context can be gotten from the input frame. | 1652 // The context can be gotten from the input frame. |
1655 Register context_reg = StubFailureTrampolineFrame::context_register(); | 1653 Register context_reg = StubFailureTrampolineFrame::context_register(); |
1656 input_frame_offset -= kPointerSize; | 1654 input_frame_offset -= kPointerSize; |
1657 value = input_->GetFrameSlot(input_frame_offset); | 1655 value = input_->GetFrameSlot(input_frame_offset); |
1658 output_frame->SetRegister(context_reg.code(), value); | 1656 output_frame->SetRegister(context_reg.code(), value); |
1659 output_frame_offset -= kPointerSize; | 1657 output_frame_offset -= kPointerSize; |
1660 output_frame->SetFrameSlot(output_frame_offset, value); | 1658 output_frame->SetFrameSlot(output_frame_offset, value); |
1661 ASSERT(reinterpret_cast<Object*>(value)->IsContext()); | 1659 CHECK(reinterpret_cast<Object*>(value)->IsContext()); |
1662 if (trace_scope_ != NULL) { | 1660 if (trace_scope_ != NULL) { |
1663 PrintF(trace_scope_->file(), | 1661 PrintF(trace_scope_->file(), |
1664 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1662 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
1665 V8PRIxPTR " ; context\n", | 1663 V8PRIxPTR " ; context\n", |
1666 top_address + output_frame_offset, output_frame_offset, value); | 1664 top_address + output_frame_offset, output_frame_offset, value); |
1667 } | 1665 } |
1668 | 1666 |
1669 // A marker value is used in place of the function. | 1667 // A marker value is used in place of the function. |
1670 output_frame_offset -= kPointerSize; | 1668 output_frame_offset -= kPointerSize; |
1671 value = reinterpret_cast<intptr_t>( | 1669 value = reinterpret_cast<intptr_t>( |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1729 int arguments_length_offset = -1; | 1727 int arguments_length_offset = -1; |
1730 for (int i = 0; i < descriptor->register_param_count_; ++i) { | 1728 for (int i = 0; i < descriptor->register_param_count_; ++i) { |
1731 output_frame_offset -= kPointerSize; | 1729 output_frame_offset -= kPointerSize; |
1732 DoTranslateCommand(iterator, 0, output_frame_offset); | 1730 DoTranslateCommand(iterator, 0, output_frame_offset); |
1733 | 1731 |
1734 if (!arg_count_known && descriptor->IsParameterCountRegister(i)) { | 1732 if (!arg_count_known && descriptor->IsParameterCountRegister(i)) { |
1735 arguments_length_offset = output_frame_offset; | 1733 arguments_length_offset = output_frame_offset; |
1736 } | 1734 } |
1737 } | 1735 } |
1738 | 1736 |
1739 ASSERT(0 == output_frame_offset); | 1737 CHECK_EQ(output_frame_offset, 0); |
1740 | 1738 |
1741 if (!arg_count_known) { | 1739 if (!arg_count_known) { |
1742 ASSERT(arguments_length_offset >= 0); | 1740 CHECK_GE(arguments_length_offset, 0); |
1743 // We know it's a smi because 1) the code stub guarantees the stack | 1741 // We know it's a smi because 1) the code stub guarantees the stack |
1744 // parameter count is in smi range, and 2) the DoTranslateCommand in the | 1742 // parameter count is in smi range, and 2) the DoTranslateCommand in the |
1745 // parameter loop above translated that to a tagged value. | 1743 // parameter loop above translated that to a tagged value. |
1746 Smi* smi_caller_arg_count = reinterpret_cast<Smi*>( | 1744 Smi* smi_caller_arg_count = reinterpret_cast<Smi*>( |
1747 output_frame->GetFrameSlot(arguments_length_offset)); | 1745 output_frame->GetFrameSlot(arguments_length_offset)); |
1748 caller_arg_count = smi_caller_arg_count->value(); | 1746 caller_arg_count = smi_caller_arg_count->value(); |
1749 output_frame->SetFrameSlot(length_frame_offset, caller_arg_count); | 1747 output_frame->SetFrameSlot(length_frame_offset, caller_arg_count); |
1750 if (trace_scope_ != NULL) { | 1748 if (trace_scope_ != NULL) { |
1751 PrintF(trace_scope_->file(), | 1749 PrintF(trace_scope_->file(), |
1752 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" | 1750 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1816 for (int i = 0; i < length; ++i) { | 1814 for (int i = 0; i < length; ++i) { |
1817 MaterializeNextValue(); | 1815 MaterializeNextValue(); |
1818 } | 1816 } |
1819 } else if (desc.is_arguments()) { | 1817 } else if (desc.is_arguments()) { |
1820 // Construct an arguments object and copy the parameters to a newly | 1818 // Construct an arguments object and copy the parameters to a newly |
1821 // allocated arguments object backing store. | 1819 // allocated arguments object backing store. |
1822 Handle<JSFunction> function = ArgumentsObjectFunction(object_index); | 1820 Handle<JSFunction> function = ArgumentsObjectFunction(object_index); |
1823 Handle<JSObject> arguments = | 1821 Handle<JSObject> arguments = |
1824 isolate_->factory()->NewArgumentsObject(function, length); | 1822 isolate_->factory()->NewArgumentsObject(function, length); |
1825 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length); | 1823 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length); |
1826 ASSERT(array->length() == length); | 1824 ASSERT_EQ(array->length(), length); |
1827 arguments->set_elements(*array); | 1825 arguments->set_elements(*array); |
1828 materialized_objects_->Add(arguments); | 1826 materialized_objects_->Add(arguments); |
1829 for (int i = 0; i < length; ++i) { | 1827 for (int i = 0; i < length; ++i) { |
1830 Handle<Object> value = MaterializeNextValue(); | 1828 Handle<Object> value = MaterializeNextValue(); |
1831 array->set(i, *value); | 1829 array->set(i, *value); |
1832 } | 1830 } |
1833 } else { | 1831 } else { |
1834 // Dispatch on the instance type of the object to be materialized. | 1832 // Dispatch on the instance type of the object to be materialized. |
1835 // We also need to make sure that the representation of all fields | 1833 // We also need to make sure that the representation of all fields |
1836 // in the given object are general enough to hold a tagged value. | 1834 // in the given object are general enough to hold a tagged value. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1882 Handle<Object> elements = MaterializeNextValue(); | 1880 Handle<Object> elements = MaterializeNextValue(); |
1883 Handle<Object> length = MaterializeNextValue(); | 1881 Handle<Object> length = MaterializeNextValue(); |
1884 object->set_properties(FixedArray::cast(*properties)); | 1882 object->set_properties(FixedArray::cast(*properties)); |
1885 object->set_elements(FixedArrayBase::cast(*elements)); | 1883 object->set_elements(FixedArrayBase::cast(*elements)); |
1886 object->set_length(*length); | 1884 object->set_length(*length); |
1887 break; | 1885 break; |
1888 } | 1886 } |
1889 default: | 1887 default: |
1890 PrintF(stderr, | 1888 PrintF(stderr, |
1891 "[couldn't handle instance type %d]\n", map->instance_type()); | 1889 "[couldn't handle instance type %d]\n", map->instance_type()); |
1892 UNREACHABLE(); | 1890 FATAL("Unsupported instance type"); |
1893 } | 1891 } |
1894 } | 1892 } |
1895 | 1893 |
1896 return materialized_objects_->at(object_index); | 1894 return materialized_objects_->at(object_index); |
1897 } | 1895 } |
1898 | 1896 |
1899 | 1897 |
1900 Handle<Object> Deoptimizer::MaterializeNextValue() { | 1898 Handle<Object> Deoptimizer::MaterializeNextValue() { |
1901 int value_index = materialization_value_index_++; | 1899 int value_index = materialization_value_index_++; |
1902 Handle<Object> value = materialized_values_->at(value_index); | 1900 Handle<Object> value = materialized_values_->at(value_index); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1976 | 1974 |
1977 while (materialization_object_index_ < deferred_objects_.length()) { | 1975 while (materialization_object_index_ < deferred_objects_.length()) { |
1978 int object_index = materialization_object_index_; | 1976 int object_index = materialization_object_index_; |
1979 ObjectMaterializationDescriptor descriptor = | 1977 ObjectMaterializationDescriptor descriptor = |
1980 deferred_objects_.at(object_index); | 1978 deferred_objects_.at(object_index); |
1981 | 1979 |
1982 // Find a previously materialized object by de-duplication or | 1980 // Find a previously materialized object by de-duplication or |
1983 // materialize a new instance of the object if necessary. Store | 1981 // materialize a new instance of the object if necessary. Store |
1984 // the materialized object into the frame slot. | 1982 // the materialized object into the frame slot. |
1985 Handle<Object> object = MaterializeNextHeapObject(); | 1983 Handle<Object> object = MaterializeNextHeapObject(); |
1986 Memory::Object_at(descriptor.slot_address()) = *object; | 1984 if (descriptor.slot_address() != NULL) { |
| 1985 Memory::Object_at(descriptor.slot_address()) = *object; |
| 1986 } |
1987 if (trace_scope_ != NULL) { | 1987 if (trace_scope_ != NULL) { |
1988 if (descriptor.is_arguments()) { | 1988 if (descriptor.is_arguments()) { |
1989 PrintF(trace_scope_->file(), | 1989 PrintF(trace_scope_->file(), |
1990 "Materialized %sarguments object of length %d for %p: ", | 1990 "Materialized %sarguments object of length %d for %p: ", |
1991 ArgumentsObjectIsAdapted(object_index) ? "(adapted) " : "", | 1991 ArgumentsObjectIsAdapted(object_index) ? "(adapted) " : "", |
1992 Handle<JSObject>::cast(object)->elements()->length(), | 1992 Handle<JSObject>::cast(object)->elements()->length(), |
1993 reinterpret_cast<void*>(descriptor.slot_address())); | 1993 reinterpret_cast<void*>(descriptor.slot_address())); |
1994 } else { | 1994 } else { |
1995 PrintF(trace_scope_->file(), | 1995 PrintF(trace_scope_->file(), |
1996 "Materialized captured object of size %d for %p: ", | 1996 "Materialized captured object of size %d for %p: ", |
1997 Handle<HeapObject>::cast(object)->Size(), | 1997 Handle<HeapObject>::cast(object)->Size(), |
1998 reinterpret_cast<void*>(descriptor.slot_address())); | 1998 reinterpret_cast<void*>(descriptor.slot_address())); |
1999 } | 1999 } |
2000 object->ShortPrint(trace_scope_->file()); | 2000 object->ShortPrint(trace_scope_->file()); |
2001 PrintF(trace_scope_->file(), "\n"); | 2001 PrintF(trace_scope_->file(), "\n"); |
2002 } | 2002 } |
2003 } | 2003 } |
2004 | 2004 |
2005 ASSERT(materialization_object_index_ == materialized_objects_->length()); | 2005 CHECK_EQ(materialization_object_index_, materialized_objects_->length()); |
2006 ASSERT(materialization_value_index_ == materialized_values_->length()); | 2006 CHECK_EQ(materialization_value_index_, materialized_values_->length()); |
2007 } | 2007 } |
2008 | 2008 |
2009 if (prev_materialized_count_ > 0) { | 2009 if (prev_materialized_count_ > 0) { |
2010 materialized_store->Remove(stack_fp_); | 2010 materialized_store->Remove(stack_fp_); |
2011 } | 2011 } |
2012 } | 2012 } |
2013 | 2013 |
2014 | 2014 |
2015 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( | 2015 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( |
2016 Address parameters_top, | 2016 Address parameters_top, |
2017 uint32_t parameters_size, | 2017 uint32_t parameters_size, |
2018 Address expressions_top, | 2018 Address expressions_top, |
2019 uint32_t expressions_size, | 2019 uint32_t expressions_size, |
2020 DeoptimizedFrameInfo* info) { | 2020 DeoptimizedFrameInfo* info) { |
2021 ASSERT_EQ(DEBUGGER, bailout_type_); | 2021 CHECK_EQ(DEBUGGER, bailout_type_); |
2022 Address parameters_bottom = parameters_top + parameters_size; | 2022 Address parameters_bottom = parameters_top + parameters_size; |
2023 Address expressions_bottom = expressions_top + expressions_size; | 2023 Address expressions_bottom = expressions_top + expressions_size; |
2024 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { | 2024 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { |
2025 HeapNumberMaterializationDescriptor<Address> d = deferred_heap_numbers_[i]; | 2025 HeapNumberMaterializationDescriptor<Address> d = deferred_heap_numbers_[i]; |
2026 | 2026 |
2027 // Check of the heap number to materialize actually belong to the frame | 2027 // Check of the heap number to materialize actually belong to the frame |
2028 // being extracted. | 2028 // being extracted. |
2029 Address slot = d.destination(); | 2029 Address slot = d.destination(); |
2030 if (parameters_top <= slot && slot < parameters_bottom) { | 2030 if (parameters_top <= slot && slot < parameters_bottom) { |
2031 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); | 2031 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2068 | 2068 |
2069 static const char* TraceValueType(bool is_smi) { | 2069 static const char* TraceValueType(bool is_smi) { |
2070 if (is_smi) { | 2070 if (is_smi) { |
2071 return "smi"; | 2071 return "smi"; |
2072 } | 2072 } |
2073 | 2073 |
2074 return "heap number"; | 2074 return "heap number"; |
2075 } | 2075 } |
2076 | 2076 |
2077 | 2077 |
| 2078 void Deoptimizer::DoTranslateObjectAndSkip(TranslationIterator* iterator) { |
| 2079 Translation::Opcode opcode = |
| 2080 static_cast<Translation::Opcode>(iterator->Next()); |
| 2081 |
| 2082 switch (opcode) { |
| 2083 case Translation::BEGIN: |
| 2084 case Translation::JS_FRAME: |
| 2085 case Translation::ARGUMENTS_ADAPTOR_FRAME: |
| 2086 case Translation::CONSTRUCT_STUB_FRAME: |
| 2087 case Translation::GETTER_STUB_FRAME: |
| 2088 case Translation::SETTER_STUB_FRAME: |
| 2089 case Translation::COMPILED_STUB_FRAME: { |
| 2090 FATAL("Unexpected frame start translation opcode"); |
| 2091 return; |
| 2092 } |
| 2093 |
| 2094 case Translation::REGISTER: |
| 2095 case Translation::INT32_REGISTER: |
| 2096 case Translation::UINT32_REGISTER: |
| 2097 case Translation::DOUBLE_REGISTER: |
| 2098 case Translation::STACK_SLOT: |
| 2099 case Translation::INT32_STACK_SLOT: |
| 2100 case Translation::UINT32_STACK_SLOT: |
| 2101 case Translation::DOUBLE_STACK_SLOT: |
| 2102 case Translation::LITERAL: { |
| 2103 // The value is not part of any materialized object, so we can ignore it. |
| 2104 iterator->Skip(Translation::NumberOfOperandsFor(opcode)); |
| 2105 return; |
| 2106 } |
| 2107 |
| 2108 case Translation::DUPLICATED_OBJECT: { |
| 2109 int object_index = iterator->Next(); |
| 2110 if (trace_scope_ != NULL) { |
| 2111 PrintF(trace_scope_->file(), " skipping object "); |
| 2112 PrintF(trace_scope_->file(), |
| 2113 " ; duplicate of object #%d\n", object_index); |
| 2114 } |
| 2115 AddObjectDuplication(0, object_index); |
| 2116 return; |
| 2117 } |
| 2118 |
| 2119 case Translation::ARGUMENTS_OBJECT: |
| 2120 case Translation::CAPTURED_OBJECT: { |
| 2121 int length = iterator->Next(); |
| 2122 bool is_args = opcode == Translation::ARGUMENTS_OBJECT; |
| 2123 if (trace_scope_ != NULL) { |
| 2124 PrintF(trace_scope_->file(), " skipping object "); |
| 2125 PrintF(trace_scope_->file(), |
| 2126 " ; object (length = %d, is_args = %d)\n", length, is_args); |
| 2127 } |
| 2128 |
| 2129 AddObjectStart(0, length, is_args); |
| 2130 |
| 2131 // We save the object values on the side and materialize the actual |
| 2132 // object after the deoptimized frame is built. |
| 2133 int object_index = deferred_objects_.length() - 1; |
| 2134 for (int i = 0; i < length; i++) { |
| 2135 DoTranslateObject(iterator, object_index, i); |
| 2136 } |
| 2137 return; |
| 2138 } |
| 2139 } |
| 2140 |
| 2141 FATAL("Unexpected translation opcode"); |
| 2142 } |
| 2143 |
| 2144 |
2078 void Deoptimizer::DoTranslateObject(TranslationIterator* iterator, | 2145 void Deoptimizer::DoTranslateObject(TranslationIterator* iterator, |
2079 int object_index, | 2146 int object_index, |
2080 int field_index) { | 2147 int field_index) { |
2081 disasm::NameConverter converter; | 2148 disasm::NameConverter converter; |
2082 Address object_slot = deferred_objects_[object_index].slot_address(); | 2149 Address object_slot = deferred_objects_[object_index].slot_address(); |
2083 | 2150 |
2084 Translation::Opcode opcode = | 2151 Translation::Opcode opcode = |
2085 static_cast<Translation::Opcode>(iterator->Next()); | 2152 static_cast<Translation::Opcode>(iterator->Next()); |
2086 | 2153 |
2087 switch (opcode) { | 2154 switch (opcode) { |
2088 case Translation::BEGIN: | 2155 case Translation::BEGIN: |
2089 case Translation::JS_FRAME: | 2156 case Translation::JS_FRAME: |
2090 case Translation::ARGUMENTS_ADAPTOR_FRAME: | 2157 case Translation::ARGUMENTS_ADAPTOR_FRAME: |
2091 case Translation::CONSTRUCT_STUB_FRAME: | 2158 case Translation::CONSTRUCT_STUB_FRAME: |
2092 case Translation::GETTER_STUB_FRAME: | 2159 case Translation::GETTER_STUB_FRAME: |
2093 case Translation::SETTER_STUB_FRAME: | 2160 case Translation::SETTER_STUB_FRAME: |
2094 case Translation::COMPILED_STUB_FRAME: | 2161 case Translation::COMPILED_STUB_FRAME: |
2095 UNREACHABLE(); | 2162 FATAL("Unexpected frame start translation opcode"); |
2096 return; | 2163 return; |
2097 | 2164 |
2098 case Translation::REGISTER: { | 2165 case Translation::REGISTER: { |
2099 int input_reg = iterator->Next(); | 2166 int input_reg = iterator->Next(); |
2100 intptr_t input_value = input_->GetRegister(input_reg); | 2167 intptr_t input_value = input_->GetRegister(input_reg); |
2101 if (trace_scope_ != NULL) { | 2168 if (trace_scope_ != NULL) { |
2102 PrintF(trace_scope_->file(), | 2169 PrintF(trace_scope_->file(), |
2103 " object @0x%08" V8PRIxPTR ": [field #%d] <- ", | 2170 " object @0x%08" V8PRIxPTR ": [field #%d] <- ", |
2104 reinterpret_cast<intptr_t>(object_slot), | 2171 reinterpret_cast<intptr_t>(object_slot), |
2105 field_index); | 2172 field_index); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2325 AddObjectTaggedValue(value); | 2392 AddObjectTaggedValue(value); |
2326 // We save the object values on the side and materialize the actual | 2393 // We save the object values on the side and materialize the actual |
2327 // object after the deoptimized frame is built. | 2394 // object after the deoptimized frame is built. |
2328 int object_index = deferred_objects_.length() - 1; | 2395 int object_index = deferred_objects_.length() - 1; |
2329 for (int i = 0; i < length; i++) { | 2396 for (int i = 0; i < length; i++) { |
2330 DoTranslateObject(iterator, object_index, i); | 2397 DoTranslateObject(iterator, object_index, i); |
2331 } | 2398 } |
2332 return; | 2399 return; |
2333 } | 2400 } |
2334 } | 2401 } |
| 2402 |
| 2403 FATAL("Unexpected translation opcode"); |
2335 } | 2404 } |
2336 | 2405 |
2337 | 2406 |
2338 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, | 2407 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, |
2339 int frame_index, | 2408 int frame_index, |
2340 unsigned output_offset) { | 2409 unsigned output_offset) { |
2341 disasm::NameConverter converter; | 2410 disasm::NameConverter converter; |
2342 // A GC-safe temporary placeholder that we can put in the output frame. | 2411 // A GC-safe temporary placeholder that we can put in the output frame. |
2343 const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0)); | 2412 const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0)); |
2344 | 2413 |
2345 Translation::Opcode opcode = | 2414 Translation::Opcode opcode = |
2346 static_cast<Translation::Opcode>(iterator->Next()); | 2415 static_cast<Translation::Opcode>(iterator->Next()); |
2347 | 2416 |
2348 switch (opcode) { | 2417 switch (opcode) { |
2349 case Translation::BEGIN: | 2418 case Translation::BEGIN: |
2350 case Translation::JS_FRAME: | 2419 case Translation::JS_FRAME: |
2351 case Translation::ARGUMENTS_ADAPTOR_FRAME: | 2420 case Translation::ARGUMENTS_ADAPTOR_FRAME: |
2352 case Translation::CONSTRUCT_STUB_FRAME: | 2421 case Translation::CONSTRUCT_STUB_FRAME: |
2353 case Translation::GETTER_STUB_FRAME: | 2422 case Translation::GETTER_STUB_FRAME: |
2354 case Translation::SETTER_STUB_FRAME: | 2423 case Translation::SETTER_STUB_FRAME: |
2355 case Translation::COMPILED_STUB_FRAME: | 2424 case Translation::COMPILED_STUB_FRAME: |
2356 UNREACHABLE(); | 2425 FATAL("Unexpected translation opcode"); |
2357 return; | 2426 return; |
2358 | 2427 |
2359 case Translation::REGISTER: { | 2428 case Translation::REGISTER: { |
2360 int input_reg = iterator->Next(); | 2429 int input_reg = iterator->Next(); |
2361 intptr_t input_value = input_->GetRegister(input_reg); | 2430 intptr_t input_value = input_->GetRegister(input_reg); |
2362 if (trace_scope_ != NULL) { | 2431 if (trace_scope_ != NULL) { |
2363 PrintF( | 2432 PrintF( |
2364 trace_scope_->file(), | 2433 trace_scope_->file(), |
2365 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s ", | 2434 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s ", |
2366 output_[frame_index]->GetTop() + output_offset, | 2435 output_[frame_index]->GetTop() + output_offset, |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2639 // pointer, function, context, and all the incoming arguments. | 2708 // pointer, function, context, and all the incoming arguments. |
2640 return ComputeIncomingArgumentSize(function) + | 2709 return ComputeIncomingArgumentSize(function) + |
2641 StandardFrameConstants::kFixedFrameSize; | 2710 StandardFrameConstants::kFixedFrameSize; |
2642 } | 2711 } |
2643 | 2712 |
2644 | 2713 |
2645 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { | 2714 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { |
2646 // The incoming arguments is the values for formal parameters and | 2715 // The incoming arguments is the values for formal parameters and |
2647 // the receiver. Every slot contains a pointer. | 2716 // the receiver. Every slot contains a pointer. |
2648 if (function->IsSmi()) { | 2717 if (function->IsSmi()) { |
2649 ASSERT(Smi::cast(function) == Smi::FromInt(StackFrame::STUB)); | 2718 CHECK_EQ(Smi::cast(function), Smi::FromInt(StackFrame::STUB)); |
2650 return 0; | 2719 return 0; |
2651 } | 2720 } |
2652 unsigned arguments = function->shared()->formal_parameter_count() + 1; | 2721 unsigned arguments = function->shared()->formal_parameter_count() + 1; |
2653 return arguments * kPointerSize; | 2722 return arguments * kPointerSize; |
2654 } | 2723 } |
2655 | 2724 |
2656 | 2725 |
2657 unsigned Deoptimizer::ComputeOutgoingArgumentSize() const { | 2726 unsigned Deoptimizer::ComputeOutgoingArgumentSize() const { |
2658 DeoptimizationInputData* data = DeoptimizationInputData::cast( | 2727 DeoptimizationInputData* data = DeoptimizationInputData::cast( |
2659 compiled_code_->deoptimization_data()); | 2728 compiled_code_->deoptimization_data()); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2704 } | 2773 } |
2705 | 2774 |
2706 | 2775 |
2707 void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate, | 2776 void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate, |
2708 BailoutType type, | 2777 BailoutType type, |
2709 int max_entry_id) { | 2778 int max_entry_id) { |
2710 // We cannot run this if the serializer is enabled because this will | 2779 // We cannot run this if the serializer is enabled because this will |
2711 // cause us to emit relocation information for the external | 2780 // cause us to emit relocation information for the external |
2712 // references. This is fine because the deoptimizer's code section | 2781 // references. This is fine because the deoptimizer's code section |
2713 // isn't meant to be serialized at all. | 2782 // isn't meant to be serialized at all. |
2714 ASSERT(type == EAGER || type == SOFT || type == LAZY); | 2783 CHECK(type == EAGER || type == SOFT || type == LAZY); |
2715 DeoptimizerData* data = isolate->deoptimizer_data(); | 2784 DeoptimizerData* data = isolate->deoptimizer_data(); |
2716 int entry_count = data->deopt_entry_code_entries_[type]; | 2785 int entry_count = data->deopt_entry_code_entries_[type]; |
2717 if (max_entry_id < entry_count) return; | 2786 if (max_entry_id < entry_count) return; |
2718 entry_count = Max(entry_count, Deoptimizer::kMinNumberOfEntries); | 2787 entry_count = Max(entry_count, Deoptimizer::kMinNumberOfEntries); |
2719 while (max_entry_id >= entry_count) entry_count *= 2; | 2788 while (max_entry_id >= entry_count) entry_count *= 2; |
2720 ASSERT(entry_count <= Deoptimizer::kMaxNumberOfEntries); | 2789 CHECK(entry_count <= Deoptimizer::kMaxNumberOfEntries); |
2721 | 2790 |
2722 MacroAssembler masm(isolate, NULL, 16 * KB); | 2791 MacroAssembler masm(isolate, NULL, 16 * KB); |
2723 masm.set_emit_debug_code(false); | 2792 masm.set_emit_debug_code(false); |
2724 GenerateDeoptimizationEntries(&masm, entry_count, type); | 2793 GenerateDeoptimizationEntries(&masm, entry_count, type); |
2725 CodeDesc desc; | 2794 CodeDesc desc; |
2726 masm.GetCode(&desc); | 2795 masm.GetCode(&desc); |
2727 ASSERT(!RelocInfo::RequiresRelocation(desc)); | 2796 ASSERT(!RelocInfo::RequiresRelocation(desc)); |
2728 | 2797 |
2729 MemoryChunk* chunk = data->deopt_entry_code_[type]; | 2798 MemoryChunk* chunk = data->deopt_entry_code_[type]; |
2730 ASSERT(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >= | 2799 CHECK(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >= |
2731 desc.instr_size); | 2800 desc.instr_size); |
2732 chunk->CommitArea(desc.instr_size); | 2801 chunk->CommitArea(desc.instr_size); |
2733 CopyBytes(chunk->area_start(), desc.buffer, | 2802 CopyBytes(chunk->area_start(), desc.buffer, |
2734 static_cast<size_t>(desc.instr_size)); | 2803 static_cast<size_t>(desc.instr_size)); |
2735 CPU::FlushICache(chunk->area_start(), desc.instr_size); | 2804 CPU::FlushICache(chunk->area_start(), desc.instr_size); |
2736 | 2805 |
2737 data->deopt_entry_code_entries_[type] = entry_count; | 2806 data->deopt_entry_code_entries_[type] = entry_count; |
2738 } | 2807 } |
2739 | 2808 |
2740 | 2809 |
2741 FrameDescription::FrameDescription(uint32_t frame_size, | 2810 FrameDescription::FrameDescription(uint32_t frame_size, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2788 case StackFrame::JAVA_SCRIPT: | 2857 case StackFrame::JAVA_SCRIPT: |
2789 return function_->shared()->formal_parameter_count(); | 2858 return function_->shared()->formal_parameter_count(); |
2790 case StackFrame::ARGUMENTS_ADAPTOR: { | 2859 case StackFrame::ARGUMENTS_ADAPTOR: { |
2791 // Last slot contains number of incomming arguments as a smi. | 2860 // Last slot contains number of incomming arguments as a smi. |
2792 // Can't use GetExpression(0) because it would cause infinite recursion. | 2861 // Can't use GetExpression(0) because it would cause infinite recursion. |
2793 return reinterpret_cast<Smi*>(*GetFrameSlotPointer(0))->value(); | 2862 return reinterpret_cast<Smi*>(*GetFrameSlotPointer(0))->value(); |
2794 } | 2863 } |
2795 case StackFrame::STUB: | 2864 case StackFrame::STUB: |
2796 return -1; // Minus receiver. | 2865 return -1; // Minus receiver. |
2797 default: | 2866 default: |
2798 UNREACHABLE(); | 2867 FATAL("Unexpected stack frame type"); |
2799 return 0; | 2868 return 0; |
2800 } | 2869 } |
2801 } | 2870 } |
2802 | 2871 |
2803 | 2872 |
2804 Object* FrameDescription::GetParameter(int index) { | 2873 Object* FrameDescription::GetParameter(int index) { |
2805 ASSERT(index >= 0); | 2874 CHECK_GE(index, 0); |
2806 ASSERT(index < ComputeParametersCount()); | 2875 CHECK_LT(index, ComputeParametersCount()); |
2807 // The slot indexes for incoming arguments are negative. | 2876 // The slot indexes for incoming arguments are negative. |
2808 unsigned offset = GetOffsetFromSlotIndex(index - ComputeParametersCount()); | 2877 unsigned offset = GetOffsetFromSlotIndex(index - ComputeParametersCount()); |
2809 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); | 2878 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); |
2810 } | 2879 } |
2811 | 2880 |
2812 | 2881 |
2813 unsigned FrameDescription::GetExpressionCount() { | 2882 unsigned FrameDescription::GetExpressionCount() { |
2814 ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_); | 2883 CHECK_EQ(StackFrame::JAVA_SCRIPT, type_); |
2815 unsigned size = GetFrameSize() - ComputeFixedSize(); | 2884 unsigned size = GetFrameSize() - ComputeFixedSize(); |
2816 return size / kPointerSize; | 2885 return size / kPointerSize; |
2817 } | 2886 } |
2818 | 2887 |
2819 | 2888 |
2820 Object* FrameDescription::GetExpression(int index) { | 2889 Object* FrameDescription::GetExpression(int index) { |
2821 ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_); | 2890 ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_); |
2822 unsigned offset = GetOffsetFromSlotIndex(index); | 2891 unsigned offset = GetOffsetFromSlotIndex(index); |
2823 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); | 2892 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); |
2824 } | 2893 } |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3006 case LITERAL: | 3075 case LITERAL: |
3007 case COMPILED_STUB_FRAME: | 3076 case COMPILED_STUB_FRAME: |
3008 return 1; | 3077 return 1; |
3009 case BEGIN: | 3078 case BEGIN: |
3010 case ARGUMENTS_ADAPTOR_FRAME: | 3079 case ARGUMENTS_ADAPTOR_FRAME: |
3011 case CONSTRUCT_STUB_FRAME: | 3080 case CONSTRUCT_STUB_FRAME: |
3012 return 2; | 3081 return 2; |
3013 case JS_FRAME: | 3082 case JS_FRAME: |
3014 return 3; | 3083 return 3; |
3015 } | 3084 } |
3016 UNREACHABLE(); | 3085 FATAL("Unexpected translation type"); |
3017 return -1; | 3086 return -1; |
3018 } | 3087 } |
3019 | 3088 |
3020 | 3089 |
3021 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) | 3090 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) |
3022 | 3091 |
3023 const char* Translation::StringFor(Opcode opcode) { | 3092 const char* Translation::StringFor(Opcode opcode) { |
3024 #define TRANSLATION_OPCODE_CASE(item) case item: return #item; | 3093 #define TRANSLATION_OPCODE_CASE(item) case item: return #item; |
3025 switch (opcode) { | 3094 switch (opcode) { |
3026 TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE) | 3095 TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE) |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3116 int formal_parameter_count) | 3185 int formal_parameter_count) |
3117 : current_slot_(0), args_length_(-1), first_slot_index_(-1) { | 3186 : current_slot_(0), args_length_(-1), first_slot_index_(-1) { |
3118 DisallowHeapAllocation no_gc; | 3187 DisallowHeapAllocation no_gc; |
3119 | 3188 |
3120 int deopt_index = Safepoint::kNoDeoptimizationIndex; | 3189 int deopt_index = Safepoint::kNoDeoptimizationIndex; |
3121 DeoptimizationInputData* data = | 3190 DeoptimizationInputData* data = |
3122 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); | 3191 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); |
3123 TranslationIterator it(data->TranslationByteArray(), | 3192 TranslationIterator it(data->TranslationByteArray(), |
3124 data->TranslationIndex(deopt_index)->value()); | 3193 data->TranslationIndex(deopt_index)->value()); |
3125 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | 3194 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
3126 ASSERT(opcode == Translation::BEGIN); | 3195 CHECK_EQ(opcode, Translation::BEGIN); |
3127 it.Next(); // Drop frame count. | 3196 it.Next(); // Drop frame count. |
3128 | 3197 |
3129 stack_frame_id_ = frame->fp(); | 3198 stack_frame_id_ = frame->fp(); |
3130 | 3199 |
3131 int jsframe_count = it.Next(); | 3200 int jsframe_count = it.Next(); |
3132 USE(jsframe_count); | 3201 CHECK_GT(jsframe_count, inlined_jsframe_index); |
3133 ASSERT(jsframe_count > inlined_jsframe_index); | |
3134 int jsframes_to_skip = inlined_jsframe_index; | 3202 int jsframes_to_skip = inlined_jsframe_index; |
3135 int number_of_slots = -1; // Number of slots inside our frame (yet unknown) | 3203 int number_of_slots = -1; // Number of slots inside our frame (yet unknown) |
3136 bool should_deopt = false; | 3204 bool should_deopt = false; |
3137 while (number_of_slots != 0) { | 3205 while (number_of_slots != 0) { |
3138 opcode = static_cast<Translation::Opcode>(it.Next()); | 3206 opcode = static_cast<Translation::Opcode>(it.Next()); |
3139 bool processed = false; | 3207 bool processed = false; |
3140 if (opcode == Translation::ARGUMENTS_ADAPTOR_FRAME) { | 3208 if (opcode == Translation::ARGUMENTS_ADAPTOR_FRAME) { |
3141 if (jsframes_to_skip == 0) { | 3209 if (jsframes_to_skip == 0) { |
3142 ASSERT(Translation::NumberOfOperandsFor(opcode) == 2); | 3210 CHECK_EQ(Translation::NumberOfOperandsFor(opcode), 2); |
3143 | 3211 |
3144 it.Skip(1); // literal id | 3212 it.Skip(1); // literal id |
3145 int height = it.Next(); | 3213 int height = it.Next(); |
3146 | 3214 |
3147 // Skip the translation command for the receiver. | 3215 // Skip the translation command for the receiver. |
3148 it.Skip(Translation::NumberOfOperandsFor( | 3216 it.Skip(Translation::NumberOfOperandsFor( |
3149 static_cast<Translation::Opcode>(it.Next()))); | 3217 static_cast<Translation::Opcode>(it.Next()))); |
3150 | 3218 |
3151 // We reached the arguments adaptor frame corresponding to the | 3219 // We reached the arguments adaptor frame corresponding to the |
3152 // inlined function in question. Number of arguments is height - 1. | 3220 // inlined function in question. Number of arguments is height - 1. |
(...skipping 26 matching lines...) Expand all Loading... |
3179 opcode != Translation::GETTER_STUB_FRAME && | 3247 opcode != Translation::GETTER_STUB_FRAME && |
3180 opcode != Translation::SETTER_STUB_FRAME && | 3248 opcode != Translation::SETTER_STUB_FRAME && |
3181 opcode != Translation::COMPILED_STUB_FRAME) { | 3249 opcode != Translation::COMPILED_STUB_FRAME) { |
3182 slot_refs_.Add(ComputeSlotForNextArgument(opcode, &it, data, frame)); | 3250 slot_refs_.Add(ComputeSlotForNextArgument(opcode, &it, data, frame)); |
3183 | 3251 |
3184 if (first_slot_index_ >= 0) { | 3252 if (first_slot_index_ >= 0) { |
3185 // We have found the beginning of our frame -> make sure we count | 3253 // We have found the beginning of our frame -> make sure we count |
3186 // the nested slots of captured objects | 3254 // the nested slots of captured objects |
3187 number_of_slots--; | 3255 number_of_slots--; |
3188 SlotRef& slot = slot_refs_.last(); | 3256 SlotRef& slot = slot_refs_.last(); |
3189 ASSERT(slot.Representation() != SlotRef::ARGUMENTS_OBJECT); | 3257 CHECK_NE(slot.Representation(), SlotRef::ARGUMENTS_OBJECT); |
3190 number_of_slots += slot.GetChildrenCount(); | 3258 number_of_slots += slot.GetChildrenCount(); |
3191 if (slot.Representation() == SlotRef::DEFERRED_OBJECT || | 3259 if (slot.Representation() == SlotRef::DEFERRED_OBJECT || |
3192 slot.Representation() == SlotRef::DUPLICATE_OBJECT) { | 3260 slot.Representation() == SlotRef::DUPLICATE_OBJECT) { |
3193 should_deopt = true; | 3261 should_deopt = true; |
3194 } | 3262 } |
3195 } | 3263 } |
3196 | 3264 |
3197 processed = true; | 3265 processed = true; |
3198 } | 3266 } |
3199 if (!processed) { | 3267 if (!processed) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3253 previously_materialized_objects_ = materialized_store->Get(stack_frame_id_); | 3321 previously_materialized_objects_ = materialized_store->Get(stack_frame_id_); |
3254 prev_materialized_count_ = previously_materialized_objects_.is_null() | 3322 prev_materialized_count_ = previously_materialized_objects_.is_null() |
3255 ? 0 : previously_materialized_objects_->length(); | 3323 ? 0 : previously_materialized_objects_->length(); |
3256 | 3324 |
3257 // Skip any materialized objects of the inlined "parent" frames. | 3325 // Skip any materialized objects of the inlined "parent" frames. |
3258 // (Note that we still need to materialize them because they might be | 3326 // (Note that we still need to materialize them because they might be |
3259 // referred to as duplicated objects.) | 3327 // referred to as duplicated objects.) |
3260 while (current_slot_ < first_slot_index_) { | 3328 while (current_slot_ < first_slot_index_) { |
3261 GetNext(isolate, 0); | 3329 GetNext(isolate, 0); |
3262 } | 3330 } |
3263 ASSERT(current_slot_ == first_slot_index_); | 3331 CHECK_EQ(current_slot_, first_slot_index_); |
3264 } | 3332 } |
3265 | 3333 |
3266 | 3334 |
3267 Handle<Object> SlotRefValueBuilder::GetPreviouslyMaterialized( | 3335 Handle<Object> SlotRefValueBuilder::GetPreviouslyMaterialized( |
3268 Isolate* isolate, int length) { | 3336 Isolate* isolate, int length) { |
3269 int object_index = materialized_objects_.length(); | 3337 int object_index = materialized_objects_.length(); |
3270 Handle<Object> return_value = Handle<Object>( | 3338 Handle<Object> return_value = Handle<Object>( |
3271 previously_materialized_objects_->get(object_index), isolate); | 3339 previously_materialized_objects_->get(object_index), isolate); |
3272 materialized_objects_.Add(return_value); | 3340 materialized_objects_.Add(return_value); |
3273 | 3341 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3315 materialized_objects_.Add(isolate->factory()->undefined_value()); | 3383 materialized_objects_.Add(isolate->factory()->undefined_value()); |
3316 int length = slot.GetChildrenCount(); | 3384 int length = slot.GetChildrenCount(); |
3317 for (int i = 0; i < length; ++i) { | 3385 for (int i = 0; i < length; ++i) { |
3318 // We don't need the argument, just ignore it | 3386 // We don't need the argument, just ignore it |
3319 GetNext(isolate, lvl + 1); | 3387 GetNext(isolate, lvl + 1); |
3320 } | 3388 } |
3321 return isolate->factory()->undefined_value(); | 3389 return isolate->factory()->undefined_value(); |
3322 } | 3390 } |
3323 case SlotRef::DEFERRED_OBJECT: { | 3391 case SlotRef::DEFERRED_OBJECT: { |
3324 int length = slot.GetChildrenCount(); | 3392 int length = slot.GetChildrenCount(); |
3325 ASSERT(slot_refs_[current_slot_].Representation() == SlotRef::LITERAL || | 3393 CHECK(slot_refs_[current_slot_].Representation() == SlotRef::LITERAL || |
3326 slot_refs_[current_slot_].Representation() == SlotRef::TAGGED); | 3394 slot_refs_[current_slot_].Representation() == SlotRef::TAGGED); |
3327 | 3395 |
3328 int object_index = materialized_objects_.length(); | 3396 int object_index = materialized_objects_.length(); |
3329 if (object_index < prev_materialized_count_) { | 3397 if (object_index < prev_materialized_count_) { |
3330 return GetPreviouslyMaterialized(isolate, length); | 3398 return GetPreviouslyMaterialized(isolate, length); |
3331 } | 3399 } |
3332 | 3400 |
3333 Handle<Object> map_object = slot_refs_[current_slot_].GetValue(isolate); | 3401 Handle<Object> map_object = slot_refs_[current_slot_].GetValue(isolate); |
3334 Handle<Map> map = Map::GeneralizeAllFieldRepresentations( | 3402 Handle<Map> map = Map::GeneralizeAllFieldRepresentations( |
3335 Handle<Map>::cast(map_object)); | 3403 Handle<Map>::cast(map_object)); |
3336 current_slot_++; | 3404 current_slot_++; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3377 object->set_length(*length); | 3445 object->set_length(*length); |
3378 return object; | 3446 return object; |
3379 } | 3447 } |
3380 default: | 3448 default: |
3381 PrintF(stderr, | 3449 PrintF(stderr, |
3382 "[couldn't handle instance type %d]\n", map->instance_type()); | 3450 "[couldn't handle instance type %d]\n", map->instance_type()); |
3383 UNREACHABLE(); | 3451 UNREACHABLE(); |
3384 break; | 3452 break; |
3385 } | 3453 } |
3386 UNREACHABLE(); | 3454 UNREACHABLE(); |
| 3455 break; |
3387 } | 3456 } |
3388 | 3457 |
3389 case SlotRef::DUPLICATE_OBJECT: { | 3458 case SlotRef::DUPLICATE_OBJECT: { |
3390 int object_index = slot.DuplicateObjectId(); | 3459 int object_index = slot.DuplicateObjectId(); |
3391 Handle<Object> object = materialized_objects_[object_index]; | 3460 Handle<Object> object = materialized_objects_[object_index]; |
3392 materialized_objects_.Add(object); | 3461 materialized_objects_.Add(object); |
3393 return object; | 3462 return object; |
3394 } | 3463 } |
3395 default: | 3464 default: |
3396 UNREACHABLE(); | 3465 UNREACHABLE(); |
3397 break; | 3466 break; |
3398 } | 3467 } |
3399 | 3468 |
3400 FATAL("We should never get here - unexpected deopt slot kind."); | 3469 FATAL("We should never get here - unexpected deopt slot kind."); |
3401 return Handle<Object>::null(); | 3470 return Handle<Object>::null(); |
3402 } | 3471 } |
3403 | 3472 |
3404 | 3473 |
3405 void SlotRefValueBuilder::Finish(Isolate* isolate) { | 3474 void SlotRefValueBuilder::Finish(Isolate* isolate) { |
3406 // We should have processed all the slots | 3475 // We should have processed all the slots |
3407 ASSERT(slot_refs_.length() == current_slot_); | 3476 CHECK_EQ(slot_refs_.length(), current_slot_); |
3408 | 3477 |
3409 if (materialized_objects_.length() > prev_materialized_count_) { | 3478 if (materialized_objects_.length() > prev_materialized_count_) { |
3410 // We have materialized some new objects, so we have to store them | 3479 // We have materialized some new objects, so we have to store them |
3411 // to prevent duplicate materialization | 3480 // to prevent duplicate materialization |
3412 Handle<FixedArray> array = isolate->factory()->NewFixedArray( | 3481 Handle<FixedArray> array = isolate->factory()->NewFixedArray( |
3413 materialized_objects_.length()); | 3482 materialized_objects_.length()); |
3414 for (int i = 0; i < materialized_objects_.length(); i++) { | 3483 for (int i = 0; i < materialized_objects_.length(); i++) { |
3415 array->set(i, *(materialized_objects_.at(i))); | 3484 array->set(i, *(materialized_objects_.at(i))); |
3416 } | 3485 } |
3417 isolate->materialized_object_store()->Set(stack_frame_id_, array); | 3486 isolate->materialized_object_store()->Set(stack_frame_id_, array); |
3418 } | 3487 } |
3419 } | 3488 } |
3420 | 3489 |
3421 | 3490 |
3422 Handle<FixedArray> MaterializedObjectStore::Get(Address fp) { | 3491 Handle<FixedArray> MaterializedObjectStore::Get(Address fp) { |
3423 int index = StackIdToIndex(fp); | 3492 int index = StackIdToIndex(fp); |
3424 if (index == -1) { | 3493 if (index == -1) { |
3425 return Handle<FixedArray>::null(); | 3494 return Handle<FixedArray>::null(); |
3426 } | 3495 } |
3427 Handle<FixedArray> array = GetStackEntries(); | 3496 Handle<FixedArray> array = GetStackEntries(); |
3428 ASSERT(array->length() > index); | 3497 CHECK_GT(array->length(), index); |
3429 return Handle<FixedArray>::cast(Handle<Object>(array->get(index), | 3498 return Handle<FixedArray>::cast(Handle<Object>(array->get(index), |
3430 isolate())); | 3499 isolate())); |
3431 } | 3500 } |
3432 | 3501 |
3433 | 3502 |
3434 void MaterializedObjectStore::Set(Address fp, | 3503 void MaterializedObjectStore::Set(Address fp, |
3435 Handle<FixedArray> materialized_objects) { | 3504 Handle<FixedArray> materialized_objects) { |
3436 int index = StackIdToIndex(fp); | 3505 int index = StackIdToIndex(fp); |
3437 if (index == -1) { | 3506 if (index == -1) { |
3438 index = frame_fps_.length(); | 3507 index = frame_fps_.length(); |
3439 frame_fps_.Add(fp); | 3508 frame_fps_.Add(fp); |
3440 } | 3509 } |
3441 | 3510 |
3442 Handle<FixedArray> array = EnsureStackEntries(index + 1); | 3511 Handle<FixedArray> array = EnsureStackEntries(index + 1); |
3443 array->set(index, *materialized_objects); | 3512 array->set(index, *materialized_objects); |
3444 } | 3513 } |
3445 | 3514 |
3446 | 3515 |
3447 void MaterializedObjectStore::Remove(Address fp) { | 3516 void MaterializedObjectStore::Remove(Address fp) { |
3448 int index = StackIdToIndex(fp); | 3517 int index = StackIdToIndex(fp); |
3449 ASSERT(index >= 0); | 3518 CHECK_GE(index, 0); |
3450 | 3519 |
3451 frame_fps_.Remove(index); | 3520 frame_fps_.Remove(index); |
3452 Handle<FixedArray> array = GetStackEntries(); | 3521 Handle<FixedArray> array = GetStackEntries(); |
3453 ASSERT(array->length() > index); | 3522 CHECK_LT(index, array->length()); |
3454 for (int i = index; i < frame_fps_.length(); i++) { | 3523 for (int i = index; i < frame_fps_.length(); i++) { |
3455 array->set(i, array->get(i + 1)); | 3524 array->set(i, array->get(i + 1)); |
3456 } | 3525 } |
3457 array->set(frame_fps_.length(), isolate()->heap()->undefined_value()); | 3526 array->set(frame_fps_.length(), isolate()->heap()->undefined_value()); |
3458 } | 3527 } |
3459 | 3528 |
3460 | 3529 |
3461 int MaterializedObjectStore::StackIdToIndex(Address fp) { | 3530 int MaterializedObjectStore::StackIdToIndex(Address fp) { |
3462 for (int i = 0; i < frame_fps_.length(); i++) { | 3531 for (int i = 0; i < frame_fps_.length(); i++) { |
3463 if (frame_fps_[i] == fp) { | 3532 if (frame_fps_[i] == fp) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3510 Address pc = reinterpret_cast<Address>(output_frame->GetPc()); | 3579 Address pc = reinterpret_cast<Address>(output_frame->GetPc()); |
3511 Code* code = Code::cast(deoptimizer->isolate()->FindCodeObject(pc)); | 3580 Code* code = Code::cast(deoptimizer->isolate()->FindCodeObject(pc)); |
3512 source_position_ = code->SourcePosition(pc); | 3581 source_position_ = code->SourcePosition(pc); |
3513 | 3582 |
3514 for (int i = 0; i < expression_count_; i++) { | 3583 for (int i = 0; i < expression_count_; i++) { |
3515 SetExpression(i, output_frame->GetExpression(i)); | 3584 SetExpression(i, output_frame->GetExpression(i)); |
3516 } | 3585 } |
3517 | 3586 |
3518 if (has_arguments_adaptor) { | 3587 if (has_arguments_adaptor) { |
3519 output_frame = deoptimizer->output_[frame_index - 1]; | 3588 output_frame = deoptimizer->output_[frame_index - 1]; |
3520 ASSERT(output_frame->GetFrameType() == StackFrame::ARGUMENTS_ADAPTOR); | 3589 CHECK_EQ(output_frame->GetFrameType(), StackFrame::ARGUMENTS_ADAPTOR); |
3521 } | 3590 } |
3522 | 3591 |
3523 parameters_count_ = output_frame->ComputeParametersCount(); | 3592 parameters_count_ = output_frame->ComputeParametersCount(); |
3524 parameters_ = new Object*[parameters_count_]; | 3593 parameters_ = new Object*[parameters_count_]; |
3525 for (int i = 0; i < parameters_count_; i++) { | 3594 for (int i = 0; i < parameters_count_; i++) { |
3526 SetParameter(i, output_frame->GetParameter(i)); | 3595 SetParameter(i, output_frame->GetParameter(i)); |
3527 } | 3596 } |
3528 } | 3597 } |
3529 | 3598 |
3530 | 3599 |
3531 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() { | 3600 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() { |
3532 delete[] expression_stack_; | 3601 delete[] expression_stack_; |
3533 delete[] parameters_; | 3602 delete[] parameters_; |
3534 } | 3603 } |
3535 | 3604 |
3536 | 3605 |
3537 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { | 3606 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { |
3538 v->VisitPointer(BitCast<Object**>(&function_)); | 3607 v->VisitPointer(BitCast<Object**>(&function_)); |
3539 v->VisitPointers(parameters_, parameters_ + parameters_count_); | 3608 v->VisitPointers(parameters_, parameters_ + parameters_count_); |
3540 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); | 3609 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); |
3541 } | 3610 } |
3542 | 3611 |
3543 } } // namespace v8::internal | 3612 } } // namespace v8::internal |
OLD | NEW |