| OLD | NEW |
| 1 // Copyright 2010 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 37 | 37 |
| 38 | 38 |
| 39 namespace v8 { | 39 namespace v8 { |
| 40 namespace internal { | 40 namespace internal { |
| 41 | 41 |
| 42 DeoptimizerData::DeoptimizerData() { | 42 DeoptimizerData::DeoptimizerData() { |
| 43 eager_deoptimization_entry_code_ = NULL; | 43 eager_deoptimization_entry_code_ = NULL; |
| 44 lazy_deoptimization_entry_code_ = NULL; | 44 lazy_deoptimization_entry_code_ = NULL; |
| 45 current_ = NULL; | 45 current_ = NULL; |
| 46 deoptimizing_code_list_ = NULL; | 46 deoptimizing_code_list_ = NULL; |
| 47 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 48 deoptimized_frame_info_ = NULL; |
| 49 #endif |
| 47 } | 50 } |
| 48 | 51 |
| 49 | 52 |
| 50 DeoptimizerData::~DeoptimizerData() { | 53 DeoptimizerData::~DeoptimizerData() { |
| 51 if (eager_deoptimization_entry_code_ != NULL) { | 54 if (eager_deoptimization_entry_code_ != NULL) { |
| 52 Isolate::Current()->memory_allocator()->Free( | 55 Isolate::Current()->memory_allocator()->Free( |
| 53 eager_deoptimization_entry_code_); | 56 eager_deoptimization_entry_code_); |
| 54 eager_deoptimization_entry_code_ = NULL; | 57 eager_deoptimization_entry_code_ = NULL; |
| 55 } | 58 } |
| 56 if (lazy_deoptimization_entry_code_ != NULL) { | 59 if (lazy_deoptimization_entry_code_ != NULL) { |
| 57 Isolate::Current()->memory_allocator()->Free( | 60 Isolate::Current()->memory_allocator()->Free( |
| 58 lazy_deoptimization_entry_code_); | 61 lazy_deoptimization_entry_code_); |
| 59 lazy_deoptimization_entry_code_ = NULL; | 62 lazy_deoptimization_entry_code_ = NULL; |
| 60 } | 63 } |
| 61 } | 64 } |
| 62 | 65 |
| 66 |
| 67 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 68 void DeoptimizerData::Iterate(ObjectVisitor* v) { |
| 69 if (deoptimized_frame_info_ != NULL) { |
| 70 deoptimized_frame_info_->Iterate(v); |
| 71 } |
| 72 } |
| 73 #endif |
| 74 |
| 75 |
| 63 Deoptimizer* Deoptimizer::New(JSFunction* function, | 76 Deoptimizer* Deoptimizer::New(JSFunction* function, |
| 64 BailoutType type, | 77 BailoutType type, |
| 65 unsigned bailout_id, | 78 unsigned bailout_id, |
| 66 Address from, | 79 Address from, |
| 67 int fp_to_sp_delta, | 80 int fp_to_sp_delta, |
| 68 Isolate* isolate) { | 81 Isolate* isolate) { |
| 69 ASSERT(isolate == Isolate::Current()); | 82 ASSERT(isolate == Isolate::Current()); |
| 70 Deoptimizer* deoptimizer = new Deoptimizer(isolate, | 83 Deoptimizer* deoptimizer = new Deoptimizer(isolate, |
| 71 function, | 84 function, |
| 72 type, | 85 type, |
| 73 bailout_id, | 86 bailout_id, |
| 74 from, | 87 from, |
| 75 fp_to_sp_delta); | 88 fp_to_sp_delta, |
| 89 NULL); |
| 76 ASSERT(isolate->deoptimizer_data()->current_ == NULL); | 90 ASSERT(isolate->deoptimizer_data()->current_ == NULL); |
| 77 isolate->deoptimizer_data()->current_ = deoptimizer; | 91 isolate->deoptimizer_data()->current_ = deoptimizer; |
| 78 return deoptimizer; | 92 return deoptimizer; |
| 79 } | 93 } |
| 80 | 94 |
| 81 | 95 |
| 82 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { | 96 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { |
| 83 ASSERT(isolate == Isolate::Current()); | 97 ASSERT(isolate == Isolate::Current()); |
| 84 Deoptimizer* result = isolate->deoptimizer_data()->current_; | 98 Deoptimizer* result = isolate->deoptimizer_data()->current_; |
| 85 ASSERT(result != NULL); | 99 ASSERT(result != NULL); |
| 86 result->DeleteFrameDescriptions(); | 100 result->DeleteFrameDescriptions(); |
| 87 isolate->deoptimizer_data()->current_ = NULL; | 101 isolate->deoptimizer_data()->current_ = NULL; |
| 88 return result; | 102 return result; |
| 89 } | 103 } |
| 90 | 104 |
| 105 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 106 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( |
| 107 JavaScriptFrame* frame, |
| 108 int frame_index, |
| 109 Isolate* isolate) { |
| 110 ASSERT(isolate == Isolate::Current()); |
| 111 ASSERT(frame->is_optimized()); |
| 112 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL); |
| 113 |
| 114 // Get the function and code from the frame. |
| 115 JSFunction* function = JSFunction::cast(frame->function()); |
| 116 Code* code = frame->LookupCode(); |
| 117 Address code_start_address = code->instruction_start(); |
| 118 |
| 119 // Locate the deoptimization point in the code. As we are at a call the |
| 120 // return address must be at a place in the code with deoptimization support. |
| 121 int deoptimization_index = Safepoint::kNoDeoptimizationIndex; |
| 122 // Scope this as the safe point constructor will disallow allocation. |
| 123 { |
| 124 SafepointTable table(code); |
| 125 for (unsigned i = 0; i < table.length(); ++i) { |
| 126 Address address = code_start_address + table.GetPcOffset(i); |
| 127 if (address == frame->pc()) { |
| 128 SafepointEntry safepoint_entry = table.GetEntry(i); |
| 129 ASSERT(safepoint_entry.deoptimization_index() != |
| 130 Safepoint::kNoDeoptimizationIndex); |
| 131 deoptimization_index = safepoint_entry.deoptimization_index(); |
| 132 break; |
| 133 } |
| 134 } |
| 135 } |
| 136 ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex); |
| 137 |
| 138 // Always use the actual stack slots when calculating the fp to sp |
| 139 // delta adding two for the function and context. |
| 140 unsigned stack_slots = code->stack_slots(); |
| 141 unsigned fp_to_sp_delta = ((stack_slots + 2) * kPointerSize); |
| 142 |
| 143 Deoptimizer* deoptimizer = new Deoptimizer(isolate, |
| 144 function, |
| 145 Deoptimizer::DEBUGGER, |
| 146 deoptimization_index, |
| 147 frame->pc(), |
| 148 fp_to_sp_delta, |
| 149 code); |
| 150 Address tos = frame->fp() - fp_to_sp_delta; |
| 151 deoptimizer->FillInputFrame(tos, frame); |
| 152 |
| 153 // Calculate the output frames. |
| 154 Deoptimizer::ComputeOutputFrames(deoptimizer); |
| 155 |
| 156 // Create the GC safe output frame information and register it for GC |
| 157 // handling. |
| 158 ASSERT_LT(frame_index, deoptimizer->output_count()); |
| 159 DeoptimizedFrameInfo* info = |
| 160 new DeoptimizedFrameInfo(deoptimizer, frame_index); |
| 161 isolate->deoptimizer_data()->deoptimized_frame_info_ = info; |
| 162 |
| 163 // Get the "simulated" top and size for the requested frame. |
| 164 Address top = |
| 165 reinterpret_cast<Address>(deoptimizer->output_[frame_index]->GetTop()); |
| 166 uint32_t size = deoptimizer->output_[frame_index]->GetFrameSize(); |
| 167 |
| 168 // Done with the GC-unsafe frame descriptions. This re-enables allocation. |
| 169 deoptimizer->DeleteFrameDescriptions(); |
| 170 |
| 171 // Allocate a heap number for the doubles belonging to this frame. |
| 172 deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame( |
| 173 top, size, info); |
| 174 |
| 175 // Finished using the deoptimizer instance. |
| 176 delete deoptimizer; |
| 177 |
| 178 return info; |
| 179 } |
| 180 |
| 181 |
| 182 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, |
| 183 Isolate* isolate) { |
| 184 ASSERT(isolate == Isolate::Current()); |
| 185 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == info); |
| 186 delete info; |
| 187 isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL; |
| 188 } |
| 189 #endif |
| 91 | 190 |
| 92 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, | 191 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, |
| 93 int count, | 192 int count, |
| 94 BailoutType type) { | 193 BailoutType type) { |
| 95 TableEntryGenerator generator(masm, type, count); | 194 TableEntryGenerator generator(masm, type, count); |
| 96 generator.Generate(); | 195 generator.Generate(); |
| 97 } | 196 } |
| 98 | 197 |
| 99 | 198 |
| 100 class DeoptimizingVisitor : public OptimizedFunctionVisitor { | 199 class DeoptimizingVisitor : public OptimizedFunctionVisitor { |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) { | 303 void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) { |
| 205 deoptimizer->DoComputeOutputFrames(); | 304 deoptimizer->DoComputeOutputFrames(); |
| 206 } | 305 } |
| 207 | 306 |
| 208 | 307 |
| 209 Deoptimizer::Deoptimizer(Isolate* isolate, | 308 Deoptimizer::Deoptimizer(Isolate* isolate, |
| 210 JSFunction* function, | 309 JSFunction* function, |
| 211 BailoutType type, | 310 BailoutType type, |
| 212 unsigned bailout_id, | 311 unsigned bailout_id, |
| 213 Address from, | 312 Address from, |
| 214 int fp_to_sp_delta) | 313 int fp_to_sp_delta, |
| 314 Code* optimized_code) |
| 215 : isolate_(isolate), | 315 : isolate_(isolate), |
| 216 function_(function), | 316 function_(function), |
| 217 bailout_id_(bailout_id), | 317 bailout_id_(bailout_id), |
| 218 bailout_type_(type), | 318 bailout_type_(type), |
| 219 from_(from), | 319 from_(from), |
| 220 fp_to_sp_delta_(fp_to_sp_delta), | 320 fp_to_sp_delta_(fp_to_sp_delta), |
| 321 input_(NULL), |
| 221 output_count_(0), | 322 output_count_(0), |
| 222 output_(NULL), | 323 output_(NULL), |
| 223 deferred_heap_numbers_(0) { | 324 deferred_heap_numbers_(0) { |
| 224 if (FLAG_trace_deopt && type != OSR) { | 325 if (FLAG_trace_deopt && type != OSR) { |
| 225 PrintF("**** DEOPT: "); | 326 if (type == DEBUGGER) { |
| 327 PrintF("**** DEOPT FOR DEBUGGER: "); |
| 328 } else { |
| 329 PrintF("**** DEOPT: "); |
| 330 } |
| 226 function->PrintName(); | 331 function->PrintName(); |
| 227 PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n", | 332 PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n", |
| 228 bailout_id, | 333 bailout_id, |
| 229 reinterpret_cast<intptr_t>(from), | 334 reinterpret_cast<intptr_t>(from), |
| 230 fp_to_sp_delta - (2 * kPointerSize)); | 335 fp_to_sp_delta - (2 * kPointerSize)); |
| 231 } else if (FLAG_trace_osr && type == OSR) { | 336 } else if (FLAG_trace_osr && type == OSR) { |
| 232 PrintF("**** OSR: "); | 337 PrintF("**** OSR: "); |
| 233 function->PrintName(); | 338 function->PrintName(); |
| 234 PrintF(" at ast id #%u, address 0x%" V8PRIxPTR ", frame size %d\n", | 339 PrintF(" at ast id #%u, address 0x%" V8PRIxPTR ", frame size %d\n", |
| 235 bailout_id, | 340 bailout_id, |
| 236 reinterpret_cast<intptr_t>(from), | 341 reinterpret_cast<intptr_t>(from), |
| 237 fp_to_sp_delta - (2 * kPointerSize)); | 342 fp_to_sp_delta - (2 * kPointerSize)); |
| 238 } | 343 } |
| 239 // Find the optimized code. | 344 // Find the optimized code. |
| 240 if (type == EAGER) { | 345 if (type == EAGER) { |
| 241 ASSERT(from == NULL); | 346 ASSERT(from == NULL); |
| 242 optimized_code_ = function_->code(); | 347 optimized_code_ = function_->code(); |
| 243 } else if (type == LAZY) { | 348 } else if (type == LAZY) { |
| 244 optimized_code_ = FindDeoptimizingCodeFromAddress(from); | 349 optimized_code_ = FindDeoptimizingCodeFromAddress(from); |
| 245 ASSERT(optimized_code_ != NULL); | 350 ASSERT(optimized_code_ != NULL); |
| 246 } else if (type == OSR) { | 351 } else if (type == OSR) { |
| 247 // The function has already been optimized and we're transitioning | 352 // The function has already been optimized and we're transitioning |
| 248 // from the unoptimized shared version to the optimized one in the | 353 // from the unoptimized shared version to the optimized one in the |
| 249 // function. The return address (from) points to unoptimized code. | 354 // function. The return address (from) points to unoptimized code. |
| 250 optimized_code_ = function_->code(); | 355 optimized_code_ = function_->code(); |
| 251 ASSERT(optimized_code_->kind() == Code::OPTIMIZED_FUNCTION); | 356 ASSERT(optimized_code_->kind() == Code::OPTIMIZED_FUNCTION); |
| 252 ASSERT(!optimized_code_->contains(from)); | 357 ASSERT(!optimized_code_->contains(from)); |
| 358 } else if (type == DEBUGGER) { |
| 359 optimized_code_ = optimized_code; |
| 360 ASSERT(optimized_code_->contains(from)); |
| 253 } | 361 } |
| 254 ASSERT(HEAP->allow_allocation(false)); | 362 ASSERT(HEAP->allow_allocation(false)); |
| 255 unsigned size = ComputeInputFrameSize(); | 363 unsigned size = ComputeInputFrameSize(); |
| 256 input_ = new(size) FrameDescription(size, function); | 364 input_ = new(size) FrameDescription(size, function); |
| 365 #ifdef DEBUG |
| 366 input_->SetKind(Code::OPTIMIZED_FUNCTION); |
| 367 #endif |
| 257 } | 368 } |
| 258 | 369 |
| 259 | 370 |
| 260 Deoptimizer::~Deoptimizer() { | 371 Deoptimizer::~Deoptimizer() { |
| 261 ASSERT(input_ == NULL && output_ == NULL); | 372 ASSERT(input_ == NULL && output_ == NULL); |
| 262 } | 373 } |
| 263 | 374 |
| 264 | 375 |
| 265 void Deoptimizer::DeleteFrameDescriptions() { | 376 void Deoptimizer::DeleteFrameDescriptions() { |
| 266 delete input_; | 377 delete input_; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 output_[index]->GetPc(), | 523 output_[index]->GetPc(), |
| 413 FullCodeGenerator::State2String( | 524 FullCodeGenerator::State2String( |
| 414 static_cast<FullCodeGenerator::State>( | 525 static_cast<FullCodeGenerator::State>( |
| 415 output_[index]->GetState()->value())), | 526 output_[index]->GetState()->value())), |
| 416 ms); | 527 ms); |
| 417 } | 528 } |
| 418 } | 529 } |
| 419 | 530 |
| 420 | 531 |
| 421 void Deoptimizer::MaterializeHeapNumbers() { | 532 void Deoptimizer::MaterializeHeapNumbers() { |
| 533 ASSERT_NE(DEBUGGER, bailout_type_); |
| 422 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { | 534 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { |
| 423 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; | 535 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; |
| 424 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); | 536 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); |
| 425 if (FLAG_trace_deopt) { | 537 if (FLAG_trace_deopt) { |
| 426 PrintF("Materializing a new heap number %p [%e] in slot %p\n", | 538 PrintF("Materializing a new heap number %p [%e] in slot %p\n", |
| 427 reinterpret_cast<void*>(*num), | 539 reinterpret_cast<void*>(*num), |
| 428 d.value(), | 540 d.value(), |
| 429 d.slot_address()); | 541 d.slot_address()); |
| 430 } | 542 } |
| 431 | 543 |
| 432 Memory::Object_at(d.slot_address()) = *num; | 544 Memory::Object_at(d.slot_address()) = *num; |
| 433 } | 545 } |
| 434 } | 546 } |
| 435 | 547 |
| 436 | 548 |
| 549 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 550 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( |
| 551 Address top, uint32_t size, DeoptimizedFrameInfo* info) { |
| 552 ASSERT_EQ(DEBUGGER, bailout_type_); |
| 553 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { |
| 554 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; |
| 555 |
| 556 // Check of the heap number to materialize actually belong to the frame |
| 557 // being extracted. |
| 558 Address slot = d.slot_address(); |
| 559 if (top <= slot && slot < top + size) { |
| 560 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); |
| 561 // Calculate the index with the botton of the expression stack |
| 562 // at index 0, and the fixed part (including incoming arguments) |
| 563 // at negative indexes. |
| 564 int index = static_cast<int>( |
| 565 info->expression_count_ - (slot - top) / kPointerSize - 1); |
| 566 if (FLAG_trace_deopt) { |
| 567 PrintF("Materializing a new heap number %p [%e] in slot %p" |
| 568 "for stack index %d\n", |
| 569 reinterpret_cast<void*>(*num), |
| 570 d.value(), |
| 571 d.slot_address(), |
| 572 index); |
| 573 } |
| 574 if (index >=0) { |
| 575 info->SetExpression(index, *num); |
| 576 } else { |
| 577 // Calculate parameter index subtracting one for the receiver. |
| 578 int parameter_index = |
| 579 index + |
| 580 static_cast<int>(size) / kPointerSize - |
| 581 info->expression_count_ - 1; |
| 582 info->SetParameter(parameter_index, *num); |
| 583 } |
| 584 } |
| 585 } |
| 586 } |
| 587 #endif |
| 588 |
| 589 |
| 437 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, | 590 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, |
| 438 int frame_index, | 591 int frame_index, |
| 439 unsigned output_offset) { | 592 unsigned output_offset) { |
| 440 disasm::NameConverter converter; | 593 disasm::NameConverter converter; |
| 441 // A GC-safe temporary placeholder that we can put in the output frame. | 594 // A GC-safe temporary placeholder that we can put in the output frame. |
| 442 const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0)); | 595 const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0)); |
| 443 | 596 |
| 444 // Ignore commands marked as duplicate and act on the first non-duplicate. | 597 // Ignore commands marked as duplicate and act on the first non-duplicate. |
| 445 Translation::Opcode opcode = | 598 Translation::Opcode opcode = |
| 446 static_cast<Translation::Opcode>(iterator->Next()); | 599 static_cast<Translation::Opcode>(iterator->Next()); |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 902 masm.set_emit_debug_code(false); | 1055 masm.set_emit_debug_code(false); |
| 903 GenerateDeoptimizationEntries(&masm, kNumberOfEntries, type); | 1056 GenerateDeoptimizationEntries(&masm, kNumberOfEntries, type); |
| 904 CodeDesc desc; | 1057 CodeDesc desc; |
| 905 masm.GetCode(&desc); | 1058 masm.GetCode(&desc); |
| 906 ASSERT(desc.reloc_size == 0); | 1059 ASSERT(desc.reloc_size == 0); |
| 907 | 1060 |
| 908 MemoryChunk* chunk = | 1061 MemoryChunk* chunk = |
| 909 Isolate::Current()->memory_allocator()->AllocateChunk(desc.instr_size, | 1062 Isolate::Current()->memory_allocator()->AllocateChunk(desc.instr_size, |
| 910 EXECUTABLE, | 1063 EXECUTABLE, |
| 911 NULL); | 1064 NULL); |
| 1065 if (chunk == NULL) { |
| 1066 V8::FatalProcessOutOfMemory("Not enough memory for deoptimization table"); |
| 1067 } |
| 912 memcpy(chunk->body(), desc.buffer, desc.instr_size); | 1068 memcpy(chunk->body(), desc.buffer, desc.instr_size); |
| 913 CPU::FlushICache(chunk->body(), desc.instr_size); | 1069 CPU::FlushICache(chunk->body(), desc.instr_size); |
| 914 return chunk; | 1070 return chunk; |
| 915 } | 1071 } |
| 916 | 1072 |
| 917 | 1073 |
| 918 Code* Deoptimizer::FindDeoptimizingCodeFromAddress(Address addr) { | 1074 Code* Deoptimizer::FindDeoptimizingCodeFromAddress(Address addr) { |
| 919 DeoptimizingCodeListNode* node = | 1075 DeoptimizingCodeListNode* node = |
| 920 Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_; | 1076 Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_; |
| 921 while (node != NULL) { | 1077 while (node != NULL) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 970 SetFrameSlot(o, kZapUint32); | 1126 SetFrameSlot(o, kZapUint32); |
| 971 } | 1127 } |
| 972 } | 1128 } |
| 973 | 1129 |
| 974 | 1130 |
| 975 unsigned FrameDescription::GetOffsetFromSlotIndex(Deoptimizer* deoptimizer, | 1131 unsigned FrameDescription::GetOffsetFromSlotIndex(Deoptimizer* deoptimizer, |
| 976 int slot_index) { | 1132 int slot_index) { |
| 977 if (slot_index >= 0) { | 1133 if (slot_index >= 0) { |
| 978 // Local or spill slots. Skip the fixed part of the frame | 1134 // Local or spill slots. Skip the fixed part of the frame |
| 979 // including all arguments. | 1135 // including all arguments. |
| 980 unsigned base = static_cast<unsigned>( | 1136 unsigned base = |
| 981 GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction())); | 1137 GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction()); |
| 982 return base - ((slot_index + 1) * kPointerSize); | 1138 return base - ((slot_index + 1) * kPointerSize); |
| 983 } else { | 1139 } else { |
| 984 // Incoming parameter. | 1140 // Incoming parameter. |
| 985 unsigned base = static_cast<unsigned>(GetFrameSize() - | 1141 unsigned base = GetFrameSize() - |
| 986 deoptimizer->ComputeIncomingArgumentSize(GetFunction())); | 1142 deoptimizer->ComputeIncomingArgumentSize(GetFunction()); |
| 987 return base - ((slot_index + 1) * kPointerSize); | 1143 return base - ((slot_index + 1) * kPointerSize); |
| 988 } | 1144 } |
| 989 } | 1145 } |
| 990 | 1146 |
| 991 | 1147 |
| 1148 int FrameDescription::ComputeParametersCount() { |
| 1149 return function_->shared()->formal_parameter_count(); |
| 1150 } |
| 1151 |
| 1152 |
| 1153 Object* FrameDescription::GetParameter(Deoptimizer* deoptimizer, int index) { |
| 1154 ASSERT_EQ(Code::FUNCTION, kind_); |
| 1155 ASSERT(index >= 0); |
| 1156 ASSERT(index < ComputeParametersCount()); |
| 1157 // The slot indexes for incoming arguments are negative. |
| 1158 unsigned offset = GetOffsetFromSlotIndex(deoptimizer, |
| 1159 index - ComputeParametersCount()); |
| 1160 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); |
| 1161 } |
| 1162 |
| 1163 |
| 1164 unsigned FrameDescription::GetExpressionCount(Deoptimizer* deoptimizer) { |
| 1165 ASSERT_EQ(Code::FUNCTION, kind_); |
| 1166 unsigned size = GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction()); |
| 1167 return size / kPointerSize; |
| 1168 } |
| 1169 |
| 1170 |
| 1171 Object* FrameDescription::GetExpression(Deoptimizer* deoptimizer, int index) { |
| 1172 ASSERT_EQ(Code::FUNCTION, kind_); |
| 1173 unsigned offset = GetOffsetFromSlotIndex(deoptimizer, index); |
| 1174 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); |
| 1175 } |
| 1176 |
| 1177 |
| 992 void TranslationBuffer::Add(int32_t value) { | 1178 void TranslationBuffer::Add(int32_t value) { |
| 993 // Encode the sign bit in the least significant bit. | 1179 // Encode the sign bit in the least significant bit. |
| 994 bool is_negative = (value < 0); | 1180 bool is_negative = (value < 0); |
| 995 uint32_t bits = ((is_negative ? -value : value) << 1) | | 1181 uint32_t bits = ((is_negative ? -value : value) << 1) | |
| 996 static_cast<int32_t>(is_negative); | 1182 static_cast<int32_t>(is_negative); |
| 997 // Encode the individual bytes using the least significant bit of | 1183 // Encode the individual bytes using the least significant bit of |
| 998 // each byte to indicate whether or not more bytes follow. | 1184 // each byte to indicate whether or not more bytes follow. |
| 999 do { | 1185 do { |
| 1000 uint32_t next = bits >> 7; | 1186 uint32_t next = bits >> 7; |
| 1001 contents_.Add(((bits << 1) & 0xFF) | (next != 0)); | 1187 contents_.Add(((bits << 1) & 0xFF) | (next != 0)); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1105 case LITERAL: | 1291 case LITERAL: |
| 1106 return 1; | 1292 return 1; |
| 1107 case FRAME: | 1293 case FRAME: |
| 1108 return 3; | 1294 return 3; |
| 1109 } | 1295 } |
| 1110 UNREACHABLE(); | 1296 UNREACHABLE(); |
| 1111 return -1; | 1297 return -1; |
| 1112 } | 1298 } |
| 1113 | 1299 |
| 1114 | 1300 |
| 1115 #ifdef OBJECT_PRINT | 1301 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) |
| 1116 | 1302 |
| 1117 const char* Translation::StringFor(Opcode opcode) { | 1303 const char* Translation::StringFor(Opcode opcode) { |
| 1118 switch (opcode) { | 1304 switch (opcode) { |
| 1119 case BEGIN: | 1305 case BEGIN: |
| 1120 return "BEGIN"; | 1306 return "BEGIN"; |
| 1121 case FRAME: | 1307 case FRAME: |
| 1122 return "FRAME"; | 1308 return "FRAME"; |
| 1123 case REGISTER: | 1309 case REGISTER: |
| 1124 return "REGISTER"; | 1310 return "REGISTER"; |
| 1125 case INT32_REGISTER: | 1311 case INT32_REGISTER: |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1254 return; | 1440 return; |
| 1255 } | 1441 } |
| 1256 frames_to_skip--; | 1442 frames_to_skip--; |
| 1257 } | 1443 } |
| 1258 } | 1444 } |
| 1259 | 1445 |
| 1260 UNREACHABLE(); | 1446 UNREACHABLE(); |
| 1261 } | 1447 } |
| 1262 | 1448 |
| 1263 | 1449 |
| 1450 DeoptimizedFrameInfo::DeoptimizedFrameInfo( |
| 1451 Deoptimizer* deoptimizer, int frame_index) { |
| 1452 FrameDescription* output_frame = deoptimizer->output_[frame_index]; |
| 1453 SetFunction(output_frame->GetFunction()); |
| 1454 expression_count_ = output_frame->GetExpressionCount(deoptimizer); |
| 1455 parameters_count_ = output_frame->ComputeParametersCount(); |
| 1456 parameters_ = new Object*[parameters_count_]; |
| 1457 for (int i = 0; i < parameters_count_; i++) { |
| 1458 SetParameter(i, output_frame->GetParameter(deoptimizer, i)); |
| 1459 } |
| 1460 expression_stack_ = new Object*[expression_count_]; |
| 1461 for (int i = 0; i < expression_count_; i++) { |
| 1462 SetExpression(i, output_frame->GetExpression(deoptimizer, i)); |
| 1463 } |
| 1464 } |
| 1465 |
| 1466 |
| 1467 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() { |
| 1468 delete[] expression_stack_; |
| 1469 delete[] parameters_; |
| 1470 } |
| 1471 |
| 1472 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { |
| 1473 v->VisitPointer(reinterpret_cast<Object**>(&function_)); |
| 1474 v->VisitPointers(parameters_, parameters_ + parameters_count_); |
| 1475 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); |
| 1476 } |
| 1477 |
| 1478 |
| 1264 } } // namespace v8::internal | 1479 } } // namespace v8::internal |
| OLD | NEW |