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 30 matching lines...) Expand all Loading... |
41 return kCallInstructionSizeInWords * Assembler::kInstrSize; | 41 return kCallInstructionSizeInWords * Assembler::kInstrSize; |
42 } | 42 } |
43 | 43 |
44 | 44 |
45 void Deoptimizer::DeoptimizeFunction(JSFunction* function) { | 45 void Deoptimizer::DeoptimizeFunction(JSFunction* function) { |
46 HandleScope scope; | 46 HandleScope scope; |
47 AssertNoAllocation no_allocation; | 47 AssertNoAllocation no_allocation; |
48 | 48 |
49 if (!function->IsOptimized()) return; | 49 if (!function->IsOptimized()) return; |
50 | 50 |
| 51 // The optimized code is going to be patched, so we cannot use it |
| 52 // any more. Play safe and reset the whole cache. |
| 53 function->shared()->ClearOptimizedCodeMap(); |
| 54 |
51 // Get the optimized code. | 55 // Get the optimized code. |
52 Code* code = function->code(); | 56 Code* code = function->code(); |
53 Address code_start_address = code->instruction_start(); | 57 Address code_start_address = code->instruction_start(); |
54 | 58 |
55 // Invalidate the relocation information, as it will become invalid by the | 59 // Invalidate the relocation information, as it will become invalid by the |
56 // code patching below, and is not needed any more. | 60 // code patching below, and is not needed any more. |
57 code->InvalidateRelocation(); | 61 code->InvalidateRelocation(); |
58 | 62 |
59 // For each LLazyBailout instruction insert a call to the corresponding | 63 // For each LLazyBailout instruction insert a call to the corresponding |
60 // deoptimization entry. | 64 // deoptimization entry. |
(...skipping 28 matching lines...) Expand all Loading... |
89 DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code); | 93 DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code); |
90 DeoptimizerData* data = isolate->deoptimizer_data(); | 94 DeoptimizerData* data = isolate->deoptimizer_data(); |
91 node->set_next(data->deoptimizing_code_list_); | 95 node->set_next(data->deoptimizing_code_list_); |
92 data->deoptimizing_code_list_ = node; | 96 data->deoptimizing_code_list_ = node; |
93 | 97 |
94 // We might be in the middle of incremental marking with compaction. | 98 // We might be in the middle of incremental marking with compaction. |
95 // Tell collector to treat this code object in a special way and | 99 // Tell collector to treat this code object in a special way and |
96 // ignore all slots that might have been recorded on it. | 100 // ignore all slots that might have been recorded on it. |
97 isolate->heap()->mark_compact_collector()->InvalidateCode(code); | 101 isolate->heap()->mark_compact_collector()->InvalidateCode(code); |
98 | 102 |
99 // Set the code for the function to non-optimized version. | 103 // Iterate over all the functions which share the same code object |
100 function->ReplaceCode(function->shared()->code()); | 104 // and make them use unoptimized version. |
| 105 Context* context = function->context()->global_context(); |
| 106 Object* element = context->get(Context::OPTIMIZED_FUNCTIONS_LIST); |
| 107 SharedFunctionInfo* shared = function->shared(); |
| 108 while (!element->IsUndefined()) { |
| 109 JSFunction* func = JSFunction::cast(element); |
| 110 // Grab element before code replacement as ReplaceCode alters the list. |
| 111 element = func->next_function_link(); |
| 112 if (func->code() == code) { |
| 113 func->ReplaceCode(shared->code()); |
| 114 } |
| 115 } |
101 | 116 |
102 if (FLAG_trace_deopt) { | 117 if (FLAG_trace_deopt) { |
103 PrintF("[forced deoptimization: "); | 118 PrintF("[forced deoptimization: "); |
104 function->PrintName(); | 119 function->PrintName(); |
105 PrintF(" / %x]\n", reinterpret_cast<uint32_t>(function)); | 120 PrintF(" / %x]\n", reinterpret_cast<uint32_t>(function)); |
106 #ifdef DEBUG | 121 #ifdef DEBUG |
107 if (FLAG_print_code) { | 122 if (FLAG_print_code) { |
108 code->PrintLn(); | 123 code->PrintLn(); |
109 } | 124 } |
110 #endif | 125 #endif |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 iterator.Skip(1); // Drop JS frame count. | 237 iterator.Skip(1); // Drop JS frame count. |
223 ASSERT(count == 1); | 238 ASSERT(count == 1); |
224 USE(count); | 239 USE(count); |
225 | 240 |
226 opcode = static_cast<Translation::Opcode>(iterator.Next()); | 241 opcode = static_cast<Translation::Opcode>(iterator.Next()); |
227 USE(opcode); | 242 USE(opcode); |
228 ASSERT(Translation::JS_FRAME == opcode); | 243 ASSERT(Translation::JS_FRAME == opcode); |
229 unsigned node_id = iterator.Next(); | 244 unsigned node_id = iterator.Next(); |
230 USE(node_id); | 245 USE(node_id); |
231 ASSERT(node_id == ast_id); | 246 ASSERT(node_id == ast_id); |
232 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator.Next())); | 247 int closure_id = iterator.Next(); |
233 USE(function); | 248 USE(closure_id); |
234 ASSERT(function == function_); | 249 ASSERT_EQ(Translation::kSelfLiteralId, closure_id); |
235 unsigned height = iterator.Next(); | 250 unsigned height = iterator.Next(); |
236 unsigned height_in_bytes = height * kPointerSize; | 251 unsigned height_in_bytes = height * kPointerSize; |
237 USE(height_in_bytes); | 252 USE(height_in_bytes); |
238 | 253 |
239 unsigned fixed_size = ComputeFixedSize(function_); | 254 unsigned fixed_size = ComputeFixedSize(function_); |
240 unsigned input_frame_size = input_->GetFrameSize(); | 255 unsigned input_frame_size = input_->GetFrameSize(); |
241 ASSERT(fixed_size + height_in_bytes == input_frame_size); | 256 ASSERT(fixed_size + height_in_bytes == input_frame_size); |
242 | 257 |
243 unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize; | 258 unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize; |
244 unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); | 259 unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 optimized_code_->entry() + pc_offset); | 350 optimized_code_->entry() + pc_offset); |
336 output_[0]->SetPc(pc); | 351 output_[0]->SetPc(pc); |
337 } | 352 } |
338 Code* continuation = isolate_->builtins()->builtin(Builtins::kNotifyOSR); | 353 Code* continuation = isolate_->builtins()->builtin(Builtins::kNotifyOSR); |
339 output_[0]->SetContinuation( | 354 output_[0]->SetContinuation( |
340 reinterpret_cast<uint32_t>(continuation->entry())); | 355 reinterpret_cast<uint32_t>(continuation->entry())); |
341 | 356 |
342 if (FLAG_trace_osr) { | 357 if (FLAG_trace_osr) { |
343 PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", | 358 PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", |
344 ok ? "finished" : "aborted", | 359 ok ? "finished" : "aborted", |
345 reinterpret_cast<intptr_t>(function)); | 360 reinterpret_cast<intptr_t>(function_)); |
346 function->PrintName(); | 361 function_->PrintName(); |
347 PrintF(" => pc=0x%0x]\n", output_[0]->GetPc()); | 362 PrintF(" => pc=0x%0x]\n", output_[0]->GetPc()); |
348 } | 363 } |
349 } | 364 } |
350 | 365 |
351 | 366 |
352 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, | 367 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, |
353 int frame_index) { | 368 int frame_index) { |
354 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 369 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
355 unsigned height = iterator->Next(); | 370 unsigned height = iterator->Next(); |
356 unsigned height_in_bytes = height * kPointerSize; | 371 unsigned height_in_bytes = height * kPointerSize; |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 output_frame->SetPc(pc); | 581 output_frame->SetPc(pc); |
567 } | 582 } |
568 | 583 |
569 | 584 |
570 // This code is very similar to ia32/arm code, but relies on register names | 585 // This code is very similar to ia32/arm code, but relies on register names |
571 // (fp, sp) and how the frame is laid out. | 586 // (fp, sp) and how the frame is laid out. |
572 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, | 587 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, |
573 int frame_index) { | 588 int frame_index) { |
574 // Read the ast node id, function, and frame height for this output frame. | 589 // Read the ast node id, function, and frame height for this output frame. |
575 int node_id = iterator->Next(); | 590 int node_id = iterator->Next(); |
576 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 591 JSFunction* function; |
| 592 if (frame_index != 0) { |
| 593 function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
| 594 } else { |
| 595 int closure_id = iterator->Next(); |
| 596 USE(closure_id); |
| 597 ASSERT_EQ(Translation::kSelfLiteralId, closure_id); |
| 598 function = function_; |
| 599 } |
577 unsigned height = iterator->Next(); | 600 unsigned height = iterator->Next(); |
578 unsigned height_in_bytes = height * kPointerSize; | 601 unsigned height_in_bytes = height * kPointerSize; |
579 if (FLAG_trace_deopt) { | 602 if (FLAG_trace_deopt) { |
580 PrintF(" translating "); | 603 PrintF(" translating "); |
581 function->PrintName(); | 604 function->PrintName(); |
582 PrintF(" => node=%d, height=%d\n", node_id, height_in_bytes); | 605 PrintF(" => node=%d, height=%d\n", node_id, height_in_bytes); |
583 } | 606 } |
584 | 607 |
585 // The 'fixed' part of the frame consists of the incoming parameters and | 608 // The 'fixed' part of the frame consists of the incoming parameters and |
586 // the part described by JavaScriptFrameConstants. | 609 // the part described by JavaScriptFrameConstants. |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
992 } | 1015 } |
993 | 1016 |
994 ASSERT_EQ(masm()->SizeOfCodeGeneratedSince(&table_start), | 1017 ASSERT_EQ(masm()->SizeOfCodeGeneratedSince(&table_start), |
995 count() * table_entry_size_); | 1018 count() * table_entry_size_); |
996 } | 1019 } |
997 | 1020 |
998 #undef __ | 1021 #undef __ |
999 | 1022 |
1000 | 1023 |
1001 } } // namespace v8::internal | 1024 } } // namespace v8::internal |
OLD | NEW |