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 22 matching lines...) Expand all Loading... |
33 #include "disasm.h" | 33 #include "disasm.h" |
34 #include "full-codegen.h" | 34 #include "full-codegen.h" |
35 #include "global-handles.h" | 35 #include "global-handles.h" |
36 #include "macro-assembler.h" | 36 #include "macro-assembler.h" |
37 #include "prettyprinter.h" | 37 #include "prettyprinter.h" |
38 | 38 |
39 | 39 |
40 namespace v8 { | 40 namespace v8 { |
41 namespace internal { | 41 namespace internal { |
42 | 42 |
43 DeoptimizerData::DeoptimizerData() { | 43 static MemoryChunk* AllocateCodeChunk(MemoryAllocator* allocator) { |
44 eager_deoptimization_entry_code_entries_ = -1; | 44 return allocator->AllocateChunk(Deoptimizer::GetMaxDeoptTableSize(), |
45 lazy_deoptimization_entry_code_entries_ = -1; | 45 OS::CommitPageSize(), |
46 size_t deopt_table_size = Deoptimizer::GetMaxDeoptTableSize(); | 46 EXECUTABLE, |
47 MemoryAllocator* allocator = Isolate::Current()->memory_allocator(); | 47 NULL); |
48 size_t initial_commit_size = OS::CommitPageSize(); | |
49 eager_deoptimization_entry_code_ = | |
50 allocator->AllocateChunk(deopt_table_size, | |
51 initial_commit_size, | |
52 EXECUTABLE, | |
53 NULL); | |
54 lazy_deoptimization_entry_code_ = | |
55 allocator->AllocateChunk(deopt_table_size, | |
56 initial_commit_size, | |
57 EXECUTABLE, | |
58 NULL); | |
59 current_ = NULL; | |
60 deoptimizing_code_list_ = NULL; | |
61 #ifdef ENABLE_DEBUGGER_SUPPORT | |
62 deoptimized_frame_info_ = NULL; | |
63 #endif | |
64 } | 48 } |
65 | 49 |
66 | 50 |
| 51 DeoptimizerData::DeoptimizerData(MemoryAllocator* allocator) |
| 52 : allocator_(allocator), |
| 53 eager_deoptimization_entry_code_entries_(-1), |
| 54 lazy_deoptimization_entry_code_entries_(-1), |
| 55 eager_deoptimization_entry_code_(AllocateCodeChunk(allocator)), |
| 56 lazy_deoptimization_entry_code_(AllocateCodeChunk(allocator)), |
| 57 current_(NULL), |
| 58 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 59 deoptimized_frame_info_(NULL), |
| 60 #endif |
| 61 deoptimizing_code_list_(NULL) { } |
| 62 |
| 63 |
67 DeoptimizerData::~DeoptimizerData() { | 64 DeoptimizerData::~DeoptimizerData() { |
68 Isolate::Current()->memory_allocator()->Free( | 65 allocator_->Free(eager_deoptimization_entry_code_); |
69 eager_deoptimization_entry_code_); | |
70 eager_deoptimization_entry_code_ = NULL; | 66 eager_deoptimization_entry_code_ = NULL; |
71 Isolate::Current()->memory_allocator()->Free( | 67 allocator_->Free(lazy_deoptimization_entry_code_); |
72 lazy_deoptimization_entry_code_); | |
73 lazy_deoptimization_entry_code_ = NULL; | 68 lazy_deoptimization_entry_code_ = NULL; |
74 | 69 |
75 DeoptimizingCodeListNode* current = deoptimizing_code_list_; | 70 DeoptimizingCodeListNode* current = deoptimizing_code_list_; |
76 while (current != NULL) { | 71 while (current != NULL) { |
77 DeoptimizingCodeListNode* prev = current; | 72 DeoptimizingCodeListNode* prev = current; |
78 current = current->next(); | 73 current = current->next(); |
79 delete prev; | 74 delete prev; |
80 } | 75 } |
81 deoptimizing_code_list_ = NULL; | 76 deoptimizing_code_list_ = NULL; |
82 } | 77 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 | 117 |
123 | 118 |
124 // We rely on this function not causing a GC. It is called from generated code | 119 // We rely on this function not causing a GC. It is called from generated code |
125 // without having a real stack frame in place. | 120 // without having a real stack frame in place. |
126 Deoptimizer* Deoptimizer::New(JSFunction* function, | 121 Deoptimizer* Deoptimizer::New(JSFunction* function, |
127 BailoutType type, | 122 BailoutType type, |
128 unsigned bailout_id, | 123 unsigned bailout_id, |
129 Address from, | 124 Address from, |
130 int fp_to_sp_delta, | 125 int fp_to_sp_delta, |
131 Isolate* isolate) { | 126 Isolate* isolate) { |
132 ASSERT(isolate == Isolate::Current()); | |
133 Deoptimizer* deoptimizer = new Deoptimizer(isolate, | 127 Deoptimizer* deoptimizer = new Deoptimizer(isolate, |
134 function, | 128 function, |
135 type, | 129 type, |
136 bailout_id, | 130 bailout_id, |
137 from, | 131 from, |
138 fp_to_sp_delta, | 132 fp_to_sp_delta, |
139 NULL); | 133 NULL); |
140 ASSERT(isolate->deoptimizer_data()->current_ == NULL); | 134 ASSERT(isolate->deoptimizer_data()->current_ == NULL); |
141 isolate->deoptimizer_data()->current_ = deoptimizer; | 135 isolate->deoptimizer_data()->current_ = deoptimizer; |
142 return deoptimizer; | 136 return deoptimizer; |
143 } | 137 } |
144 | 138 |
145 | 139 |
146 // No larger than 2K on all platforms | 140 // No larger than 2K on all platforms |
147 static const int kDeoptTableMaxEpilogueCodeSize = 2 * KB; | 141 static const int kDeoptTableMaxEpilogueCodeSize = 2 * KB; |
148 | 142 |
149 | 143 |
150 size_t Deoptimizer::GetMaxDeoptTableSize() { | 144 size_t Deoptimizer::GetMaxDeoptTableSize() { |
151 int entries_size = | 145 int entries_size = |
152 Deoptimizer::kMaxNumberOfEntries * Deoptimizer::table_entry_size_; | 146 Deoptimizer::kMaxNumberOfEntries * Deoptimizer::table_entry_size_; |
153 int commit_page_size = static_cast<int>(OS::CommitPageSize()); | 147 int commit_page_size = static_cast<int>(OS::CommitPageSize()); |
154 int page_count = ((kDeoptTableMaxEpilogueCodeSize + entries_size - 1) / | 148 int page_count = ((kDeoptTableMaxEpilogueCodeSize + entries_size - 1) / |
155 commit_page_size) + 1; | 149 commit_page_size) + 1; |
156 return static_cast<size_t>(commit_page_size * page_count); | 150 return static_cast<size_t>(commit_page_size * page_count); |
157 } | 151 } |
158 | 152 |
159 | 153 |
160 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { | 154 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { |
161 ASSERT(isolate == Isolate::Current()); | |
162 Deoptimizer* result = isolate->deoptimizer_data()->current_; | 155 Deoptimizer* result = isolate->deoptimizer_data()->current_; |
163 ASSERT(result != NULL); | 156 ASSERT(result != NULL); |
164 result->DeleteFrameDescriptions(); | 157 result->DeleteFrameDescriptions(); |
165 isolate->deoptimizer_data()->current_ = NULL; | 158 isolate->deoptimizer_data()->current_ = NULL; |
166 return result; | 159 return result; |
167 } | 160 } |
168 | 161 |
169 | 162 |
170 int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) { | 163 int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) { |
171 if (jsframe_index == 0) return 0; | 164 if (jsframe_index == 0) return 0; |
172 | 165 |
173 int frame_index = 0; | 166 int frame_index = 0; |
174 while (jsframe_index >= 0) { | 167 while (jsframe_index >= 0) { |
175 FrameDescription* frame = output_[frame_index]; | 168 FrameDescription* frame = output_[frame_index]; |
176 if (frame->GetFrameType() == StackFrame::JAVA_SCRIPT) { | 169 if (frame->GetFrameType() == StackFrame::JAVA_SCRIPT) { |
177 jsframe_index--; | 170 jsframe_index--; |
178 } | 171 } |
179 frame_index++; | 172 frame_index++; |
180 } | 173 } |
181 | 174 |
182 return frame_index - 1; | 175 return frame_index - 1; |
183 } | 176 } |
184 | 177 |
185 | 178 |
186 #ifdef ENABLE_DEBUGGER_SUPPORT | 179 #ifdef ENABLE_DEBUGGER_SUPPORT |
187 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( | 180 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( |
188 JavaScriptFrame* frame, | 181 JavaScriptFrame* frame, |
189 int jsframe_index, | 182 int jsframe_index, |
190 Isolate* isolate) { | 183 Isolate* isolate) { |
191 ASSERT(isolate == Isolate::Current()); | |
192 ASSERT(frame->is_optimized()); | 184 ASSERT(frame->is_optimized()); |
193 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL); | 185 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL); |
194 | 186 |
195 // Get the function and code from the frame. | 187 // Get the function and code from the frame. |
196 JSFunction* function = JSFunction::cast(frame->function()); | 188 JSFunction* function = JSFunction::cast(frame->function()); |
197 Code* code = frame->LookupCode(); | 189 Code* code = frame->LookupCode(); |
198 | 190 |
199 // Locate the deoptimization point in the code. As we are at a call the | 191 // Locate the deoptimization point in the code. As we are at a call the |
200 // return address must be at a place in the code with deoptimization support. | 192 // return address must be at a place in the code with deoptimization support. |
201 SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc()); | 193 SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc()); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 | 259 |
268 // Finished using the deoptimizer instance. | 260 // Finished using the deoptimizer instance. |
269 delete deoptimizer; | 261 delete deoptimizer; |
270 | 262 |
271 return info; | 263 return info; |
272 } | 264 } |
273 | 265 |
274 | 266 |
275 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, | 267 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, |
276 Isolate* isolate) { | 268 Isolate* isolate) { |
277 ASSERT(isolate == Isolate::Current()); | |
278 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == info); | 269 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == info); |
279 delete info; | 270 delete info; |
280 isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL; | 271 isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL; |
281 } | 272 } |
282 #endif | 273 #endif |
283 | 274 |
284 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, | 275 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, |
285 int count, | 276 int count, |
286 BailoutType type) { | 277 BailoutType type) { |
287 TableEntryGenerator generator(masm, type, count); | 278 TableEntryGenerator generator(masm, type, count); |
(...skipping 24 matching lines...) Expand all Loading... |
312 // Run through the snapshot of optimized functions and visit them. | 303 // Run through the snapshot of optimized functions and visit them. |
313 for (int i = 0; i < snapshot.length(); ++i) { | 304 for (int i = 0; i < snapshot.length(); ++i) { |
314 visitor->VisitFunction(snapshot.at(i)); | 305 visitor->VisitFunction(snapshot.at(i)); |
315 } | 306 } |
316 | 307 |
317 visitor->LeaveContext(context); | 308 visitor->LeaveContext(context); |
318 } | 309 } |
319 | 310 |
320 | 311 |
321 void Deoptimizer::VisitAllOptimizedFunctions( | 312 void Deoptimizer::VisitAllOptimizedFunctions( |
| 313 Isolate* isolate, |
322 OptimizedFunctionVisitor* visitor) { | 314 OptimizedFunctionVisitor* visitor) { |
323 AssertNoAllocation no_allocation; | 315 AssertNoAllocation no_allocation; |
324 | 316 |
325 // Run through the list of all native contexts and deoptimize. | 317 // Run through the list of all native contexts and deoptimize. |
326 Object* context = Isolate::Current()->heap()->native_contexts_list(); | 318 Object* context = isolate->heap()->native_contexts_list(); |
327 while (!context->IsUndefined()) { | 319 while (!context->IsUndefined()) { |
328 VisitAllOptimizedFunctionsForContext(Context::cast(context), visitor); | 320 VisitAllOptimizedFunctionsForContext(Context::cast(context), visitor); |
329 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); | 321 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); |
330 } | 322 } |
331 } | 323 } |
332 | 324 |
333 | 325 |
334 // Removes the functions selected by the given filter from the optimized | 326 // Removes the functions selected by the given filter from the optimized |
335 // function list of the given context and partitions the removed functions | 327 // function list of the given context and partitions the removed functions |
336 // into one or more lists such that all functions in a list share the same | 328 // into one or more lists such that all functions in a list share the same |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 public: | 379 public: |
388 explicit DeoptimizeWithMatchingCodeFilter(Code* code) : code_(code) {} | 380 explicit DeoptimizeWithMatchingCodeFilter(Code* code) : code_(code) {} |
389 virtual bool TakeFunction(JSFunction* function) { | 381 virtual bool TakeFunction(JSFunction* function) { |
390 return function->code() == code_; | 382 return function->code() == code_; |
391 } | 383 } |
392 private: | 384 private: |
393 Code* code_; | 385 Code* code_; |
394 }; | 386 }; |
395 | 387 |
396 | 388 |
397 void Deoptimizer::DeoptimizeAll() { | 389 void Deoptimizer::DeoptimizeAll(Isolate* isolate) { |
398 AssertNoAllocation no_allocation; | 390 AssertNoAllocation no_allocation; |
399 | 391 |
400 if (FLAG_trace_deopt) { | 392 if (FLAG_trace_deopt) { |
401 PrintF("[deoptimize all contexts]\n"); | 393 PrintF("[deoptimize all contexts]\n"); |
402 } | 394 } |
403 | 395 |
404 DeoptimizeAllFilter filter; | 396 DeoptimizeAllFilter filter; |
405 DeoptimizeAllFunctionsWith(&filter); | 397 DeoptimizeAllFunctionsWith(isolate, &filter); |
406 } | 398 } |
407 | 399 |
408 | 400 |
409 void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) { | 401 void Deoptimizer::DeoptimizeGlobalObject(JSObject* object) { |
410 AssertNoAllocation no_allocation; | 402 AssertNoAllocation no_allocation; |
411 DeoptimizeAllFilter filter; | 403 DeoptimizeAllFilter filter; |
412 if (object->IsJSGlobalProxy()) { | 404 if (object->IsJSGlobalProxy()) { |
413 Object* proto = object->GetPrototype(); | 405 Object* proto = object->GetPrototype(); |
414 ASSERT(proto->IsJSGlobalObject()); | 406 ASSERT(proto->IsJSGlobalObject()); |
415 DeoptimizeAllFunctionsForContext( | 407 DeoptimizeAllFunctionsForContext( |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 ZoneList<Code*> codes(1, zone); | 441 ZoneList<Code*> codes(1, zone); |
450 PartitionOptimizedFunctions(context, filter, &codes, zone, undefined); | 442 PartitionOptimizedFunctions(context, filter, &codes, zone, undefined); |
451 for (int i = 0; i < codes.length(); ++i) { | 443 for (int i = 0; i < codes.length(); ++i) { |
452 DeoptimizeFunctionWithPreparedFunctionList( | 444 DeoptimizeFunctionWithPreparedFunctionList( |
453 JSFunction::cast(codes.at(i)->deoptimizing_functions())); | 445 JSFunction::cast(codes.at(i)->deoptimizing_functions())); |
454 codes.at(i)->set_deoptimizing_functions(undefined); | 446 codes.at(i)->set_deoptimizing_functions(undefined); |
455 } | 447 } |
456 } | 448 } |
457 | 449 |
458 | 450 |
459 void Deoptimizer::DeoptimizeAllFunctionsWith(OptimizedFunctionFilter* filter) { | 451 void Deoptimizer::DeoptimizeAllFunctionsWith(Isolate* isolate, |
| 452 OptimizedFunctionFilter* filter) { |
460 AssertNoAllocation no_allocation; | 453 AssertNoAllocation no_allocation; |
461 | 454 |
462 // Run through the list of all native contexts and deoptimize. | 455 // Run through the list of all native contexts and deoptimize. |
463 Object* context = Isolate::Current()->heap()->native_contexts_list(); | 456 Object* context = isolate->heap()->native_contexts_list(); |
464 while (!context->IsUndefined()) { | 457 while (!context->IsUndefined()) { |
465 DeoptimizeAllFunctionsForContext(Context::cast(context), filter); | 458 DeoptimizeAllFunctionsForContext(Context::cast(context), filter); |
466 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); | 459 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); |
467 } | 460 } |
468 } | 461 } |
469 | 462 |
470 | 463 |
471 void Deoptimizer::HandleWeakDeoptimizedCode(v8::Isolate* isolate, | 464 void Deoptimizer::HandleWeakDeoptimizedCode(v8::Isolate* isolate, |
472 v8::Persistent<v8::Value> obj, | 465 v8::Persistent<v8::Value> obj, |
473 void* parameter) { | 466 void* parameter) { |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 ASSERT(!HEAP->allow_allocation(true)); | 626 ASSERT(!HEAP->allow_allocation(true)); |
634 } | 627 } |
635 | 628 |
636 | 629 |
637 Address Deoptimizer::GetDeoptimizationEntry(Isolate* isolate, | 630 Address Deoptimizer::GetDeoptimizationEntry(Isolate* isolate, |
638 int id, | 631 int id, |
639 BailoutType type, | 632 BailoutType type, |
640 GetEntryMode mode) { | 633 GetEntryMode mode) { |
641 ASSERT(id >= 0); | 634 ASSERT(id >= 0); |
642 if (id >= kMaxNumberOfEntries) return NULL; | 635 if (id >= kMaxNumberOfEntries) return NULL; |
643 MemoryChunk* base = NULL; | |
644 if (mode == ENSURE_ENTRY_CODE) { | 636 if (mode == ENSURE_ENTRY_CODE) { |
645 EnsureCodeForDeoptimizationEntry(isolate, type, id); | 637 EnsureCodeForDeoptimizationEntry(isolate, type, id); |
646 } else { | 638 } else { |
647 ASSERT(mode == CALCULATE_ENTRY_ADDRESS); | 639 ASSERT(mode == CALCULATE_ENTRY_ADDRESS); |
648 } | 640 } |
649 DeoptimizerData* data = isolate->deoptimizer_data(); | 641 DeoptimizerData* data = isolate->deoptimizer_data(); |
650 if (type == EAGER) { | 642 MemoryChunk* base = (type == EAGER) |
651 base = data->eager_deoptimization_entry_code_; | 643 ? data->eager_deoptimization_entry_code_ |
652 } else { | 644 : data->lazy_deoptimization_entry_code_; |
653 base = data->lazy_deoptimization_entry_code_; | |
654 } | |
655 return base->area_start() + (id * table_entry_size_); | 645 return base->area_start() + (id * table_entry_size_); |
656 } | 646 } |
657 | 647 |
658 | 648 |
659 int Deoptimizer::GetDeoptimizationId(Address addr, BailoutType type) { | 649 int Deoptimizer::GetDeoptimizationId(Isolate* isolate, |
660 MemoryChunk* base = NULL; | 650 Address addr, |
661 DeoptimizerData* data = Isolate::Current()->deoptimizer_data(); | 651 BailoutType type) { |
662 if (type == EAGER) { | 652 DeoptimizerData* data = isolate->deoptimizer_data(); |
663 base = data->eager_deoptimization_entry_code_; | 653 MemoryChunk* base = (type == EAGER) |
664 } else { | 654 ? data->eager_deoptimization_entry_code_ |
665 base = data->lazy_deoptimization_entry_code_; | 655 : data->lazy_deoptimization_entry_code_; |
666 } | |
667 Address start = base->area_start(); | 656 Address start = base->area_start(); |
668 if (base == NULL || | 657 if (base == NULL || |
669 addr < start || | 658 addr < start || |
670 addr >= start + (kMaxNumberOfEntries * table_entry_size_)) { | 659 addr >= start + (kMaxNumberOfEntries * table_entry_size_)) { |
671 return kNotDeoptimizationEntry; | 660 return kNotDeoptimizationEntry; |
672 } | 661 } |
673 ASSERT_EQ(0, | 662 ASSERT_EQ(0, |
674 static_cast<int>(addr - start) % table_entry_size_); | 663 static_cast<int>(addr - start) % table_entry_size_); |
675 return static_cast<int>(addr - start) / table_entry_size_; | 664 return static_cast<int>(addr - start) / table_entry_size_; |
676 } | 665 } |
(...skipping 1451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2128 while (max_entry_id >= entry_count) entry_count *= 2; | 2117 while (max_entry_id >= entry_count) entry_count *= 2; |
2129 ASSERT(entry_count <= Deoptimizer::kMaxNumberOfEntries); | 2118 ASSERT(entry_count <= Deoptimizer::kMaxNumberOfEntries); |
2130 | 2119 |
2131 MacroAssembler masm(isolate, NULL, 16 * KB); | 2120 MacroAssembler masm(isolate, NULL, 16 * KB); |
2132 masm.set_emit_debug_code(false); | 2121 masm.set_emit_debug_code(false); |
2133 GenerateDeoptimizationEntries(&masm, entry_count, type); | 2122 GenerateDeoptimizationEntries(&masm, entry_count, type); |
2134 CodeDesc desc; | 2123 CodeDesc desc; |
2135 masm.GetCode(&desc); | 2124 masm.GetCode(&desc); |
2136 ASSERT(!RelocInfo::RequiresRelocation(desc)); | 2125 ASSERT(!RelocInfo::RequiresRelocation(desc)); |
2137 | 2126 |
2138 MemoryChunk* chunk = type == EAGER | 2127 MemoryChunk* chunk = (type == EAGER) |
2139 ? data->eager_deoptimization_entry_code_ | 2128 ? data->eager_deoptimization_entry_code_ |
2140 : data->lazy_deoptimization_entry_code_; | 2129 : data->lazy_deoptimization_entry_code_; |
2141 ASSERT(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >= | 2130 ASSERT(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >= |
2142 desc.instr_size); | 2131 desc.instr_size); |
2143 chunk->CommitArea(desc.instr_size); | 2132 chunk->CommitArea(desc.instr_size); |
2144 memcpy(chunk->area_start(), desc.buffer, desc.instr_size); | 2133 memcpy(chunk->area_start(), desc.buffer, desc.instr_size); |
2145 CPU::FlushICache(chunk->area_start(), desc.instr_size); | 2134 CPU::FlushICache(chunk->area_start(), desc.instr_size); |
2146 | 2135 |
2147 if (type == EAGER) { | 2136 if (type == EAGER) { |
2148 data->eager_deoptimization_entry_code_entries_ = entry_count; | 2137 data->eager_deoptimization_entry_code_entries_ = entry_count; |
2149 } else { | 2138 } else { |
2150 data->lazy_deoptimization_entry_code_entries_ = entry_count; | 2139 data->lazy_deoptimization_entry_code_entries_ = entry_count; |
2151 } | 2140 } |
2152 } | 2141 } |
2153 | 2142 |
2154 | 2143 |
2155 void Deoptimizer::ReplaceCodeForRelatedFunctions(JSFunction* function, | 2144 void Deoptimizer::ReplaceCodeForRelatedFunctions(JSFunction* function, |
2156 Code* code) { | 2145 Code* code) { |
2157 SharedFunctionInfo* shared = function->shared(); | 2146 SharedFunctionInfo* shared = function->shared(); |
2158 Object* undefined = Isolate::Current()->heap()->undefined_value(); | 2147 Object* undefined = function->GetHeap()->undefined_value(); |
2159 Object* current = function; | 2148 Object* current = function; |
2160 | 2149 |
2161 while (current != undefined) { | 2150 while (current != undefined) { |
2162 JSFunction* func = JSFunction::cast(current); | 2151 JSFunction* func = JSFunction::cast(current); |
2163 current = func->next_function_link(); | 2152 current = func->next_function_link(); |
2164 func->set_code(shared->code()); | 2153 func->set_code(shared->code()); |
2165 func->set_next_function_link(undefined); | 2154 func->set_next_function_link(undefined); |
2166 } | 2155 } |
2167 } | 2156 } |
2168 | 2157 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2274 bits |= (next >> 1) << i; | 2263 bits |= (next >> 1) << i; |
2275 if ((next & 1) == 0) break; | 2264 if ((next & 1) == 0) break; |
2276 } | 2265 } |
2277 // The bits encode the sign in the least significant bit. | 2266 // The bits encode the sign in the least significant bit. |
2278 bool is_negative = (bits & 1) == 1; | 2267 bool is_negative = (bits & 1) == 1; |
2279 int32_t result = bits >> 1; | 2268 int32_t result = bits >> 1; |
2280 return is_negative ? -result : result; | 2269 return is_negative ? -result : result; |
2281 } | 2270 } |
2282 | 2271 |
2283 | 2272 |
2284 Handle<ByteArray> TranslationBuffer::CreateByteArray() { | 2273 Handle<ByteArray> TranslationBuffer::CreateByteArray(Factory* factory) { |
2285 int length = contents_.length(); | 2274 int length = contents_.length(); |
2286 Handle<ByteArray> result = | 2275 Handle<ByteArray> result = factory->NewByteArray(length, TENURED); |
2287 Isolate::Current()->factory()->NewByteArray(length, TENURED); | |
2288 memcpy(result->GetDataStartAddress(), contents_.ToVector().start(), length); | 2276 memcpy(result->GetDataStartAddress(), contents_.ToVector().start(), length); |
2289 return result; | 2277 return result; |
2290 } | 2278 } |
2291 | 2279 |
2292 | 2280 |
2293 void Translation::BeginConstructStubFrame(int literal_id, unsigned height) { | 2281 void Translation::BeginConstructStubFrame(int literal_id, unsigned height) { |
2294 buffer_->Add(CONSTRUCT_STUB_FRAME, zone()); | 2282 buffer_->Add(CONSTRUCT_STUB_FRAME, zone()); |
2295 buffer_->Add(literal_id, zone()); | 2283 buffer_->Add(literal_id, zone()); |
2296 buffer_->Add(height, zone()); | 2284 buffer_->Add(height, zone()); |
2297 } | 2285 } |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2472 return "DUPLICATE"; | 2460 return "DUPLICATE"; |
2473 } | 2461 } |
2474 UNREACHABLE(); | 2462 UNREACHABLE(); |
2475 return ""; | 2463 return ""; |
2476 } | 2464 } |
2477 | 2465 |
2478 #endif | 2466 #endif |
2479 | 2467 |
2480 | 2468 |
2481 DeoptimizingCodeListNode::DeoptimizingCodeListNode(Code* code): next_(NULL) { | 2469 DeoptimizingCodeListNode::DeoptimizingCodeListNode(Code* code): next_(NULL) { |
2482 GlobalHandles* global_handles = Isolate::Current()->global_handles(); | 2470 GlobalHandles* global_handles = code->GetIsolate()->global_handles(); |
2483 // Globalize the code object and make it weak. | 2471 // Globalize the code object and make it weak. |
2484 code_ = Handle<Code>::cast(global_handles->Create(code)); | 2472 code_ = Handle<Code>::cast(global_handles->Create(code)); |
2485 global_handles->MakeWeak(reinterpret_cast<Object**>(code_.location()), | 2473 global_handles->MakeWeak(reinterpret_cast<Object**>(code_.location()), |
2486 this, | 2474 this, |
2487 NULL, | 2475 NULL, |
2488 Deoptimizer::HandleWeakDeoptimizedCode); | 2476 Deoptimizer::HandleWeakDeoptimizedCode); |
2489 } | 2477 } |
2490 | 2478 |
2491 | 2479 |
2492 DeoptimizingCodeListNode::~DeoptimizingCodeListNode() { | 2480 DeoptimizingCodeListNode::~DeoptimizingCodeListNode() { |
2493 GlobalHandles* global_handles = Isolate::Current()->global_handles(); | 2481 GlobalHandles* global_handles = code_->GetIsolate()->global_handles(); |
2494 global_handles->Destroy(reinterpret_cast<Object**>(code_.location())); | 2482 global_handles->Destroy(reinterpret_cast<Object**>(code_.location())); |
2495 } | 2483 } |
2496 | 2484 |
2497 | 2485 |
2498 // We can't intermix stack decoding and allocations because | 2486 // We can't intermix stack decoding and allocations because |
2499 // deoptimization infrastracture is not GC safe. | 2487 // deoptimization infrastracture is not GC safe. |
2500 // Thus we build a temporary structure in malloced space. | 2488 // Thus we build a temporary structure in malloced space. |
2501 SlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator, | 2489 SlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator, |
2502 DeoptimizationInputData* data, | 2490 DeoptimizationInputData* data, |
2503 JavaScriptFrame* frame) { | 2491 JavaScriptFrame* frame) { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2649 int frame_index, | 2637 int frame_index, |
2650 bool has_arguments_adaptor, | 2638 bool has_arguments_adaptor, |
2651 bool has_construct_stub) { | 2639 bool has_construct_stub) { |
2652 FrameDescription* output_frame = deoptimizer->output_[frame_index]; | 2640 FrameDescription* output_frame = deoptimizer->output_[frame_index]; |
2653 function_ = output_frame->GetFunction(); | 2641 function_ = output_frame->GetFunction(); |
2654 has_construct_stub_ = has_construct_stub; | 2642 has_construct_stub_ = has_construct_stub; |
2655 expression_count_ = output_frame->GetExpressionCount(); | 2643 expression_count_ = output_frame->GetExpressionCount(); |
2656 expression_stack_ = new Object*[expression_count_]; | 2644 expression_stack_ = new Object*[expression_count_]; |
2657 // Get the source position using the unoptimized code. | 2645 // Get the source position using the unoptimized code. |
2658 Address pc = reinterpret_cast<Address>(output_frame->GetPc()); | 2646 Address pc = reinterpret_cast<Address>(output_frame->GetPc()); |
2659 Code* code = Code::cast(Isolate::Current()->heap()->FindCodeObject(pc)); | 2647 Code* code = Code::cast(deoptimizer->isolate()->heap()->FindCodeObject(pc)); |
2660 source_position_ = code->SourcePosition(pc); | 2648 source_position_ = code->SourcePosition(pc); |
2661 | 2649 |
2662 for (int i = 0; i < expression_count_; i++) { | 2650 for (int i = 0; i < expression_count_; i++) { |
2663 SetExpression(i, output_frame->GetExpression(i)); | 2651 SetExpression(i, output_frame->GetExpression(i)); |
2664 } | 2652 } |
2665 | 2653 |
2666 if (has_arguments_adaptor) { | 2654 if (has_arguments_adaptor) { |
2667 output_frame = deoptimizer->output_[frame_index - 1]; | 2655 output_frame = deoptimizer->output_[frame_index - 1]; |
2668 ASSERT(output_frame->GetFrameType() == StackFrame::ARGUMENTS_ADAPTOR); | 2656 ASSERT(output_frame->GetFrameType() == StackFrame::ARGUMENTS_ADAPTOR); |
2669 } | 2657 } |
(...skipping 14 matching lines...) Expand all Loading... |
2684 | 2672 |
2685 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { | 2673 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { |
2686 v->VisitPointer(BitCast<Object**>(&function_)); | 2674 v->VisitPointer(BitCast<Object**>(&function_)); |
2687 v->VisitPointers(parameters_, parameters_ + parameters_count_); | 2675 v->VisitPointers(parameters_, parameters_ + parameters_count_); |
2688 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); | 2676 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); |
2689 } | 2677 } |
2690 | 2678 |
2691 #endif // ENABLE_DEBUGGER_SUPPORT | 2679 #endif // ENABLE_DEBUGGER_SUPPORT |
2692 | 2680 |
2693 } } // namespace v8::internal | 2681 } } // namespace v8::internal |
OLD | NEW |