OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/deoptimizer.h" | 5 #include "src/deoptimizer.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/ast/prettyprinter.h" | 8 #include "src/ast/prettyprinter.h" |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/disasm.h" | 10 #include "src/disasm.h" |
(...skipping 18 matching lines...) Expand all Loading... |
29 NOT_EXECUTABLE, | 29 NOT_EXECUTABLE, |
30 #else | 30 #else |
31 EXECUTABLE, | 31 EXECUTABLE, |
32 #endif | 32 #endif |
33 NULL); | 33 NULL); |
34 } | 34 } |
35 | 35 |
36 | 36 |
37 DeoptimizerData::DeoptimizerData(MemoryAllocator* allocator) | 37 DeoptimizerData::DeoptimizerData(MemoryAllocator* allocator) |
38 : allocator_(allocator), | 38 : allocator_(allocator), |
39 deoptimized_frame_info_(NULL), | |
40 current_(NULL) { | 39 current_(NULL) { |
41 for (int i = 0; i < Deoptimizer::kBailoutTypesWithCodeEntry; ++i) { | 40 for (int i = 0; i < Deoptimizer::kBailoutTypesWithCodeEntry; ++i) { |
42 deopt_entry_code_entries_[i] = -1; | 41 deopt_entry_code_entries_[i] = -1; |
43 deopt_entry_code_[i] = AllocateCodeChunk(allocator); | 42 deopt_entry_code_[i] = AllocateCodeChunk(allocator); |
44 } | 43 } |
45 } | 44 } |
46 | 45 |
47 | 46 |
48 DeoptimizerData::~DeoptimizerData() { | 47 DeoptimizerData::~DeoptimizerData() { |
49 for (int i = 0; i < Deoptimizer::kBailoutTypesWithCodeEntry; ++i) { | 48 for (int i = 0; i < Deoptimizer::kBailoutTypesWithCodeEntry; ++i) { |
50 allocator_->Free(deopt_entry_code_[i]); | 49 allocator_->Free(deopt_entry_code_[i]); |
51 deopt_entry_code_[i] = NULL; | 50 deopt_entry_code_[i] = NULL; |
52 } | 51 } |
53 } | 52 } |
54 | 53 |
55 | 54 |
56 void DeoptimizerData::Iterate(ObjectVisitor* v) { | |
57 if (deoptimized_frame_info_ != NULL) { | |
58 deoptimized_frame_info_->Iterate(v); | |
59 } | |
60 } | |
61 | |
62 | |
63 Code* Deoptimizer::FindDeoptimizingCode(Address addr) { | 55 Code* Deoptimizer::FindDeoptimizingCode(Address addr) { |
64 if (function_->IsHeapObject()) { | 56 if (function_->IsHeapObject()) { |
65 // Search all deoptimizing code in the native context of the function. | 57 // Search all deoptimizing code in the native context of the function. |
66 Context* native_context = function_->context()->native_context(); | 58 Context* native_context = function_->context()->native_context(); |
67 Object* element = native_context->DeoptimizedCodeListHead(); | 59 Object* element = native_context->DeoptimizedCodeListHead(); |
68 while (!element->IsUndefined()) { | 60 while (!element->IsUndefined()) { |
69 Code* code = Code::cast(element); | 61 Code* code = Code::cast(element); |
70 CHECK(code->kind() == Code::OPTIMIZED_FUNCTION); | 62 CHECK(code->kind() == Code::OPTIMIZED_FUNCTION); |
71 if (code->contains(addr)) return code; | 63 if (code->contains(addr)) return code; |
72 element = code->next_code_link(); | 64 element = code->next_code_link(); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 | 126 |
135 return frame_index - 1; | 127 return frame_index - 1; |
136 } | 128 } |
137 | 129 |
138 | 130 |
139 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( | 131 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( |
140 JavaScriptFrame* frame, | 132 JavaScriptFrame* frame, |
141 int jsframe_index, | 133 int jsframe_index, |
142 Isolate* isolate) { | 134 Isolate* isolate) { |
143 CHECK(frame->is_optimized()); | 135 CHECK(frame->is_optimized()); |
144 CHECK(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL); | |
145 | 136 |
146 // Get the function and code from the frame. | 137 // Get the function and code from the frame. |
147 JSFunction* function = frame->function(); | 138 JSFunction* function = frame->function(); |
148 Code* code = frame->LookupCode(); | 139 Code* code = frame->LookupCode(); |
149 | 140 |
150 // Locate the deoptimization point in the code. As we are at a call the | 141 // Locate the deoptimization point in the code. As we are at a call the |
151 // return address must be at a place in the code with deoptimization support. | 142 // return address must be at a place in the code with deoptimization support. |
152 SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc()); | 143 SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc()); |
153 int deoptimization_index = safepoint_entry.deoptimization_index(); | 144 int deoptimization_index = safepoint_entry.deoptimization_index(); |
154 CHECK_NE(deoptimization_index, Safepoint::kNoDeoptimizationIndex); | 145 CHECK_NE(deoptimization_index, Safepoint::kNoDeoptimizationIndex); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 int construct_offset = has_arguments_adaptor ? 2 : 1; | 181 int construct_offset = has_arguments_adaptor ? 2 : 1; |
191 bool has_construct_stub = | 182 bool has_construct_stub = |
192 frame_index >= construct_offset && | 183 frame_index >= construct_offset && |
193 deoptimizer->output_[frame_index - construct_offset]->GetFrameType() == | 184 deoptimizer->output_[frame_index - construct_offset]->GetFrameType() == |
194 StackFrame::CONSTRUCT; | 185 StackFrame::CONSTRUCT; |
195 | 186 |
196 DeoptimizedFrameInfo* info = new DeoptimizedFrameInfo(deoptimizer, | 187 DeoptimizedFrameInfo* info = new DeoptimizedFrameInfo(deoptimizer, |
197 frame_index, | 188 frame_index, |
198 has_arguments_adaptor, | 189 has_arguments_adaptor, |
199 has_construct_stub); | 190 has_construct_stub); |
200 isolate->deoptimizer_data()->deoptimized_frame_info_ = info; | |
201 | 191 |
202 // Done with the GC-unsafe frame descriptions. This re-enables allocation. | 192 // Done with the GC-unsafe frame descriptions. This re-enables allocation. |
203 deoptimizer->DeleteFrameDescriptions(); | 193 deoptimizer->DeleteFrameDescriptions(); |
204 | 194 |
205 // Allocate a heap number for the doubles belonging to this frame. | 195 // Allocate a heap number for the doubles belonging to this frame. |
206 deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame( | 196 deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame( |
207 frame_index, info->parameters_count(), info->expression_count(), info); | 197 frame_index, info->parameters_count(), info->expression_count(), info); |
208 | 198 |
209 // Finished using the deoptimizer instance. | 199 // Finished using the deoptimizer instance. |
210 delete deoptimizer; | 200 delete deoptimizer; |
211 | 201 |
212 return info; | 202 return info; |
213 } | 203 } |
214 | 204 |
215 | 205 |
216 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, | 206 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, |
217 Isolate* isolate) { | 207 Isolate* isolate) { |
218 CHECK_EQ(isolate->deoptimizer_data()->deoptimized_frame_info_, info); | |
219 delete info; | 208 delete info; |
220 isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL; | |
221 } | 209 } |
222 | 210 |
223 | 211 |
224 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, | 212 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, |
225 int count, | 213 int count, |
226 BailoutType type) { | 214 BailoutType type) { |
227 TableEntryGenerator generator(masm, type, count); | 215 TableEntryGenerator generator(masm, type, count); |
228 generator.Generate(); | 216 generator.Generate(); |
229 } | 217 } |
230 | 218 |
(...skipping 1682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1913 } | 1901 } |
1914 } else { | 1902 } else { |
1915 CHECK_EQ(frame_arg_count, parameter_count); | 1903 CHECK_EQ(frame_arg_count, parameter_count); |
1916 } | 1904 } |
1917 | 1905 |
1918 TranslatedFrame::iterator arg_iter = argument_frame->begin(); | 1906 TranslatedFrame::iterator arg_iter = argument_frame->begin(); |
1919 arg_iter++; // Skip the function. | 1907 arg_iter++; // Skip the function. |
1920 arg_iter++; // Skip the receiver. | 1908 arg_iter++; // Skip the receiver. |
1921 for (int i = 0; i < parameter_count; i++, arg_iter++) { | 1909 for (int i = 0; i < parameter_count; i++, arg_iter++) { |
1922 if (!arg_iter->IsMaterializedObject()) { | 1910 if (!arg_iter->IsMaterializedObject()) { |
1923 info->SetParameter(i, *(arg_iter->GetValue())); | 1911 info->SetParameter(i, arg_iter->GetValue()); |
1924 } | 1912 } |
1925 } | 1913 } |
1926 | 1914 |
1927 TranslatedFrame::iterator iter = frame->begin(); | 1915 TranslatedFrame::iterator iter = frame->begin(); |
1928 // Skip the function, receiver, context and arguments. | 1916 // Skip the function, receiver, context and arguments. |
1929 for (int i = 0; i < frame_arg_count + 3; i++, iter++) { | 1917 for (int i = 0; i < frame_arg_count + 3; i++, iter++) { |
1930 } | 1918 } |
1931 | 1919 |
1932 for (int i = 0; i < expression_count; i++, iter++) { | 1920 for (int i = 0; i < expression_count; i++, iter++) { |
1933 if (!iter->IsMaterializedObject()) { | 1921 if (!iter->IsMaterializedObject()) { |
1934 info->SetExpression(i, *(iter->GetValue())); | 1922 info->SetExpression(i, iter->GetValue()); |
1935 } | 1923 } |
1936 } | 1924 } |
1937 } | 1925 } |
1938 | 1926 |
1939 | 1927 |
1940 void Deoptimizer::WriteTranslatedValueToOutput( | 1928 void Deoptimizer::WriteTranslatedValueToOutput( |
1941 TranslatedFrame::iterator* iterator, int* input_index, int frame_index, | 1929 TranslatedFrame::iterator* iterator, int* input_index, int frame_index, |
1942 unsigned output_offset, const char* debug_hint_string, | 1930 unsigned output_offset, const char* debug_hint_string, |
1943 Address output_address_for_materialization) { | 1931 Address output_address_for_materialization) { |
1944 Object* value = (*iterator)->GetRawValue(); | 1932 Object* value = (*iterator)->GetRawValue(); |
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2501 isolate()->heap()->SetRootMaterializedObjects(*new_array); | 2489 isolate()->heap()->SetRootMaterializedObjects(*new_array); |
2502 return new_array; | 2490 return new_array; |
2503 } | 2491 } |
2504 | 2492 |
2505 | 2493 |
2506 DeoptimizedFrameInfo::DeoptimizedFrameInfo(Deoptimizer* deoptimizer, | 2494 DeoptimizedFrameInfo::DeoptimizedFrameInfo(Deoptimizer* deoptimizer, |
2507 int frame_index, | 2495 int frame_index, |
2508 bool has_arguments_adaptor, | 2496 bool has_arguments_adaptor, |
2509 bool has_construct_stub) { | 2497 bool has_construct_stub) { |
2510 FrameDescription* output_frame = deoptimizer->output_[frame_index]; | 2498 FrameDescription* output_frame = deoptimizer->output_[frame_index]; |
2511 function_ = output_frame->GetFunction(); | 2499 function_ = |
2512 context_ = reinterpret_cast<Object*>(output_frame->GetContext()); | 2500 Handle<JSFunction>(output_frame->GetFunction(), deoptimizer->isolate()); |
| 2501 context_ = |
| 2502 Handle<Object>(reinterpret_cast<Object*>(output_frame->GetContext()), |
| 2503 deoptimizer->isolate()); |
2513 has_construct_stub_ = has_construct_stub; | 2504 has_construct_stub_ = has_construct_stub; |
2514 expression_count_ = output_frame->GetExpressionCount(); | 2505 expression_stack_.resize( |
2515 expression_stack_ = new Object* [expression_count_]; | 2506 static_cast<size_t>(output_frame->GetExpressionCount())); |
2516 // Get the source position using the unoptimized code. | 2507 // Get the source position using the unoptimized code. |
2517 Address pc = reinterpret_cast<Address>(output_frame->GetPc()); | 2508 Address pc = reinterpret_cast<Address>(output_frame->GetPc()); |
2518 Code* code = Code::cast(deoptimizer->isolate()->FindCodeObject(pc)); | 2509 Code* code = Code::cast(deoptimizer->isolate()->FindCodeObject(pc)); |
2519 int offset = static_cast<int>(pc - code->instruction_start()); | 2510 int offset = static_cast<int>(pc - code->instruction_start()); |
2520 source_position_ = code->SourcePosition(offset); | 2511 source_position_ = code->SourcePosition(offset); |
2521 | 2512 |
2522 for (int i = 0; i < expression_count_; i++) { | 2513 for (int i = 0; i < static_cast<int>(expression_count()); i++) { |
2523 Object* value = output_frame->GetExpression(i); | 2514 Object* value = output_frame->GetExpression(i); |
2524 // Replace materialization markers with the undefined value. | 2515 // Replace materialization markers with the undefined value. |
2525 if (value == deoptimizer->isolate()->heap()->arguments_marker()) { | 2516 if (value == deoptimizer->isolate()->heap()->arguments_marker()) { |
2526 value = deoptimizer->isolate()->heap()->undefined_value(); | 2517 value = deoptimizer->isolate()->heap()->undefined_value(); |
2527 } | 2518 } |
2528 SetExpression(i, value); | 2519 SetExpression(i, Handle<Object>(value, deoptimizer->isolate())); |
2529 } | 2520 } |
2530 | 2521 |
2531 if (has_arguments_adaptor) { | 2522 if (has_arguments_adaptor) { |
2532 output_frame = deoptimizer->output_[frame_index - 1]; | 2523 output_frame = deoptimizer->output_[frame_index - 1]; |
2533 CHECK_EQ(output_frame->GetFrameType(), StackFrame::ARGUMENTS_ADAPTOR); | 2524 CHECK_EQ(output_frame->GetFrameType(), StackFrame::ARGUMENTS_ADAPTOR); |
2534 } | 2525 } |
2535 | 2526 |
2536 parameters_count_ = output_frame->ComputeParametersCount(); | 2527 parameters_.resize( |
2537 parameters_ = new Object* [parameters_count_]; | 2528 static_cast<size_t>(output_frame->ComputeParametersCount())); |
2538 for (int i = 0; i < parameters_count_; i++) { | 2529 for (int i = 0; i < output_frame->ComputeParametersCount(); i++) { |
2539 Object* value = output_frame->GetParameter(i); | 2530 Object* value = output_frame->GetParameter(i); |
2540 // Replace materialization markers with the undefined value. | 2531 // Replace materialization markers with the undefined value. |
2541 if (value == deoptimizer->isolate()->heap()->arguments_marker()) { | 2532 if (value == deoptimizer->isolate()->heap()->arguments_marker()) { |
2542 value = deoptimizer->isolate()->heap()->undefined_value(); | 2533 value = deoptimizer->isolate()->heap()->undefined_value(); |
2543 } | 2534 } |
2544 SetParameter(i, value); | 2535 SetParameter(i, Handle<Object>(value, deoptimizer->isolate())); |
2545 } | 2536 } |
2546 } | 2537 } |
2547 | 2538 |
2548 | 2539 |
2549 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() { | |
2550 delete[] expression_stack_; | |
2551 delete[] parameters_; | |
2552 } | |
2553 | |
2554 | |
2555 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { | |
2556 v->VisitPointer(bit_cast<Object**>(&function_)); | |
2557 v->VisitPointer(&context_); | |
2558 v->VisitPointers(parameters_, parameters_ + parameters_count_); | |
2559 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); | |
2560 } | |
2561 | |
2562 | |
2563 const char* Deoptimizer::GetDeoptReason(DeoptReason deopt_reason) { | 2540 const char* Deoptimizer::GetDeoptReason(DeoptReason deopt_reason) { |
2564 DCHECK(deopt_reason < kLastDeoptReason); | 2541 DCHECK(deopt_reason < kLastDeoptReason); |
2565 #define DEOPT_MESSAGES_TEXTS(C, T) T, | 2542 #define DEOPT_MESSAGES_TEXTS(C, T) T, |
2566 static const char* deopt_messages_[] = { | 2543 static const char* deopt_messages_[] = { |
2567 DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_TEXTS)}; | 2544 DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_TEXTS)}; |
2568 #undef DEOPT_MESSAGES_TEXTS | 2545 #undef DEOPT_MESSAGES_TEXTS |
2569 return deopt_messages_[deopt_reason]; | 2546 return deopt_messages_[deopt_reason]; |
2570 } | 2547 } |
2571 | 2548 |
2572 | 2549 |
(...skipping 1135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3708 DCHECK(value_info->IsMaterializedObject()); | 3685 DCHECK(value_info->IsMaterializedObject()); |
3709 | 3686 |
3710 value_info->value_ = | 3687 value_info->value_ = |
3711 Handle<Object>(previously_materialized_objects->get(i), isolate_); | 3688 Handle<Object>(previously_materialized_objects->get(i), isolate_); |
3712 } | 3689 } |
3713 } | 3690 } |
3714 } | 3691 } |
3715 | 3692 |
3716 } // namespace internal | 3693 } // namespace internal |
3717 } // namespace v8 | 3694 } // namespace v8 |
OLD | NEW |