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