| 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 |