OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 } | 127 } |
128 // Replace relocation information on the code object. | 128 // Replace relocation information on the code object. |
129 code->set_relocation_info(*new_reloc); | 129 code->set_relocation_info(*new_reloc); |
130 } | 130 } |
131 } | 131 } |
132 | 132 |
133 | 133 |
134 void Deoptimizer::DeoptimizeFunction(JSFunction* function) { | 134 void Deoptimizer::DeoptimizeFunction(JSFunction* function) { |
135 if (!function->IsOptimized()) return; | 135 if (!function->IsOptimized()) return; |
136 | 136 |
| 137 // The optimized code is going to be patched, so we cannot use it |
| 138 // any more. Play safe and reset the whole cache. |
| 139 function->shared()->set_optimized_code_map(Smi::FromInt(0)); |
| 140 |
137 Isolate* isolate = function->GetIsolate(); | 141 Isolate* isolate = function->GetIsolate(); |
138 HandleScope scope(isolate); | 142 HandleScope scope(isolate); |
139 AssertNoAllocation no_allocation; | 143 AssertNoAllocation no_allocation; |
140 | 144 |
141 // Get the optimized code. | 145 // Get the optimized code. |
142 Code* code = function->code(); | 146 Code* code = function->code(); |
143 Address code_start_address = code->instruction_start(); | 147 Address code_start_address = code->instruction_start(); |
144 | 148 |
145 // We will overwrite the code's relocation info in-place. Relocation info | 149 // We will overwrite the code's relocation info in-place. Relocation info |
146 // is written backward. The relocation info is the payload of a byte | 150 // is written backward. The relocation info is the payload of a byte |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 ASSERT(junk_address <= reloc_end_address); | 202 ASSERT(junk_address <= reloc_end_address); |
199 isolate->heap()->CreateFillerObjectAt(junk_address, | 203 isolate->heap()->CreateFillerObjectAt(junk_address, |
200 reloc_end_address - junk_address); | 204 reloc_end_address - junk_address); |
201 | 205 |
202 // Add the deoptimizing code to the list. | 206 // Add the deoptimizing code to the list. |
203 DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code); | 207 DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code); |
204 DeoptimizerData* data = isolate->deoptimizer_data(); | 208 DeoptimizerData* data = isolate->deoptimizer_data(); |
205 node->set_next(data->deoptimizing_code_list_); | 209 node->set_next(data->deoptimizing_code_list_); |
206 data->deoptimizing_code_list_ = node; | 210 data->deoptimizing_code_list_ = node; |
207 | 211 |
208 // Set the code for the function to non-optimized version. | 212 // Iterate over all the functions which share the same code object |
209 function->ReplaceCode(function->shared()->code()); | 213 // and make them use unoptimized version. |
| 214 Context* context = function->context()->global_context(); |
| 215 Object* element = context->get(Context::OPTIMIZED_FUNCTIONS_LIST); |
| 216 SharedFunctionInfo* shared = function->shared(); |
| 217 while (!element->IsUndefined()) { |
| 218 JSFunction* func = JSFunction::cast(element); |
| 219 // Grab element before code replacement as ReplaceCode alters the list. |
| 220 element = func->next_function_link(); |
| 221 if (func->shared() == shared) { |
| 222 func->ReplaceCode(shared->code()); |
| 223 } |
| 224 } |
210 | 225 |
211 if (FLAG_trace_deopt) { | 226 if (FLAG_trace_deopt) { |
212 PrintF("[forced deoptimization: "); | 227 PrintF("[forced deoptimization: "); |
213 function->PrintName(); | 228 function->PrintName(); |
214 PrintF(" / %x]\n", reinterpret_cast<uint32_t>(function)); | 229 PrintF(" / %x]\n", reinterpret_cast<uint32_t>(function)); |
215 #ifdef DEBUG | 230 #ifdef DEBUG |
216 if (FLAG_print_code) { | 231 if (FLAG_print_code) { |
217 code->PrintLn(); | 232 code->PrintLn(); |
218 } | 233 } |
219 #endif | 234 #endif |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 int count = iterator.Next(); | 324 int count = iterator.Next(); |
310 ASSERT(count == 1); | 325 ASSERT(count == 1); |
311 USE(count); | 326 USE(count); |
312 | 327 |
313 opcode = static_cast<Translation::Opcode>(iterator.Next()); | 328 opcode = static_cast<Translation::Opcode>(iterator.Next()); |
314 USE(opcode); | 329 USE(opcode); |
315 ASSERT(Translation::FRAME == opcode); | 330 ASSERT(Translation::FRAME == opcode); |
316 unsigned node_id = iterator.Next(); | 331 unsigned node_id = iterator.Next(); |
317 USE(node_id); | 332 USE(node_id); |
318 ASSERT(node_id == ast_id); | 333 ASSERT(node_id == ast_id); |
319 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator.Next())); | 334 int closure_id = iterator.Next(); |
320 USE(function); | 335 USE(closure_id); |
321 ASSERT(function == function_); | 336 ASSERT_EQ(Translation::kSelfLiteralId, closure_id); |
322 unsigned height = iterator.Next(); | 337 unsigned height = iterator.Next(); |
323 unsigned height_in_bytes = height * kPointerSize; | 338 unsigned height_in_bytes = height * kPointerSize; |
324 USE(height_in_bytes); | 339 USE(height_in_bytes); |
325 | 340 |
326 unsigned fixed_size = ComputeFixedSize(function_); | 341 unsigned fixed_size = ComputeFixedSize(function_); |
327 unsigned input_frame_size = input_->GetFrameSize(); | 342 unsigned input_frame_size = input_->GetFrameSize(); |
328 ASSERT(fixed_size + height_in_bytes == input_frame_size); | 343 ASSERT(fixed_size + height_in_bytes == input_frame_size); |
329 | 344 |
330 unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize; | 345 unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize; |
331 unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); | 346 unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 // Setup the frame pointer and the context pointer. | 429 // Setup the frame pointer and the context pointer. |
415 output_[0]->SetRegister(ebp.code(), input_->GetRegister(ebp.code())); | 430 output_[0]->SetRegister(ebp.code(), input_->GetRegister(ebp.code())); |
416 output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code())); | 431 output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code())); |
417 | 432 |
418 unsigned pc_offset = data->OsrPcOffset()->value(); | 433 unsigned pc_offset = data->OsrPcOffset()->value(); |
419 uint32_t pc = reinterpret_cast<uint32_t>( | 434 uint32_t pc = reinterpret_cast<uint32_t>( |
420 optimized_code_->entry() + pc_offset); | 435 optimized_code_->entry() + pc_offset); |
421 output_[0]->SetPc(pc); | 436 output_[0]->SetPc(pc); |
422 } | 437 } |
423 Code* continuation = | 438 Code* continuation = |
424 function->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR); | 439 function_->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR); |
425 output_[0]->SetContinuation( | 440 output_[0]->SetContinuation( |
426 reinterpret_cast<uint32_t>(continuation->entry())); | 441 reinterpret_cast<uint32_t>(continuation->entry())); |
427 | 442 |
428 if (FLAG_trace_osr) { | 443 if (FLAG_trace_osr) { |
429 PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", | 444 PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", |
430 ok ? "finished" : "aborted", | 445 ok ? "finished" : "aborted", |
431 reinterpret_cast<intptr_t>(function)); | 446 reinterpret_cast<intptr_t>(function_)); |
432 function->PrintName(); | 447 function_->PrintName(); |
433 PrintF(" => pc=0x%0x]\n", output_[0]->GetPc()); | 448 PrintF(" => pc=0x%0x]\n", output_[0]->GetPc()); |
434 } | 449 } |
435 } | 450 } |
436 | 451 |
437 | 452 |
438 void Deoptimizer::DoComputeFrame(TranslationIterator* iterator, | 453 void Deoptimizer::DoComputeFrame(TranslationIterator* iterator, |
439 int frame_index) { | 454 int frame_index) { |
440 // Read the ast node id, function, and frame height for this output frame. | 455 // Read the ast node id, function, and frame height for this output frame. |
441 Translation::Opcode opcode = | 456 Translation::Opcode opcode = |
442 static_cast<Translation::Opcode>(iterator->Next()); | 457 static_cast<Translation::Opcode>(iterator->Next()); |
443 USE(opcode); | 458 USE(opcode); |
444 ASSERT(Translation::FRAME == opcode); | 459 ASSERT(Translation::FRAME == opcode); |
445 int node_id = iterator->Next(); | 460 int node_id = iterator->Next(); |
446 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 461 JSFunction* function; |
| 462 if (frame_index != 0) { |
| 463 function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
| 464 } else { |
| 465 int closure_id = iterator->Next(); |
| 466 USE(closure_id); |
| 467 ASSERT_EQ(Translation::kSelfLiteralId, closure_id); |
| 468 function = function_; |
| 469 } |
447 unsigned height = iterator->Next(); | 470 unsigned height = iterator->Next(); |
448 unsigned height_in_bytes = height * kPointerSize; | 471 unsigned height_in_bytes = height * kPointerSize; |
449 if (FLAG_trace_deopt) { | 472 if (FLAG_trace_deopt) { |
450 PrintF(" translating "); | 473 PrintF(" translating "); |
451 function->PrintName(); | 474 function->PrintName(); |
452 PrintF(" => node=%d, height=%d\n", node_id, height_in_bytes); | 475 PrintF(" => node=%d, height=%d\n", node_id, height_in_bytes); |
453 } | 476 } |
454 | 477 |
455 // The 'fixed' part of the frame consists of the incoming parameters and | 478 // The 'fixed' part of the frame consists of the incoming parameters and |
456 // the part described by JavaScriptFrameConstants. | 479 // the part described by JavaScriptFrameConstants. |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 } | 788 } |
766 __ bind(&done); | 789 __ bind(&done); |
767 } | 790 } |
768 | 791 |
769 #undef __ | 792 #undef __ |
770 | 793 |
771 | 794 |
772 } } // namespace v8::internal | 795 } } // namespace v8::internal |
773 | 796 |
774 #endif // V8_TARGET_ARCH_IA32 | 797 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |