Chromium Code Reviews| 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 26 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 eager_deoptimization_entry_code_->Free(EXECUTABLE); | 55 eager_deoptimization_entry_code_->Free(EXECUTABLE); |
| 53 eager_deoptimization_entry_code_ = NULL; | 56 eager_deoptimization_entry_code_ = NULL; |
| 54 } | 57 } |
| 55 if (lazy_deoptimization_entry_code_ != NULL) { | 58 if (lazy_deoptimization_entry_code_ != NULL) { |
| 56 lazy_deoptimization_entry_code_->Free(EXECUTABLE); | 59 lazy_deoptimization_entry_code_->Free(EXECUTABLE); |
| 57 lazy_deoptimization_entry_code_ = NULL; | 60 lazy_deoptimization_entry_code_ = NULL; |
| 58 } | 61 } |
| 59 } | 62 } |
| 60 | 63 |
| 64 | |
| 65 #ifdef ENABLE_DEBUGGER_SUPPORT | |
| 66 void DeoptimizerData::Iterate(ObjectVisitor* v) { | |
| 67 if (deoptimized_frame_info_ != NULL) { | |
| 68 deoptimized_frame_info_->Iterate(v); | |
| 69 } | |
| 70 } | |
| 71 #endif | |
| 72 | |
| 73 | |
| 61 Deoptimizer* Deoptimizer::New(JSFunction* function, | 74 Deoptimizer* Deoptimizer::New(JSFunction* function, |
| 62 BailoutType type, | 75 BailoutType type, |
| 63 unsigned bailout_id, | 76 unsigned bailout_id, |
| 64 Address from, | 77 Address from, |
| 65 int fp_to_sp_delta, | 78 int fp_to_sp_delta, |
| 66 Isolate* isolate) { | 79 Isolate* isolate) { |
| 67 ASSERT(isolate == Isolate::Current()); | 80 ASSERT(isolate == Isolate::Current()); |
| 68 Deoptimizer* deoptimizer = new Deoptimizer(isolate, | 81 Deoptimizer* deoptimizer = new Deoptimizer(isolate, |
| 69 function, | 82 function, |
| 70 type, | 83 type, |
| 71 bailout_id, | 84 bailout_id, |
| 72 from, | 85 from, |
| 73 fp_to_sp_delta); | 86 fp_to_sp_delta, |
| 87 NULL); | |
| 74 ASSERT(isolate->deoptimizer_data()->current_ == NULL); | 88 ASSERT(isolate->deoptimizer_data()->current_ == NULL); |
| 75 isolate->deoptimizer_data()->current_ = deoptimizer; | 89 isolate->deoptimizer_data()->current_ = deoptimizer; |
| 76 return deoptimizer; | 90 return deoptimizer; |
| 77 } | 91 } |
| 78 | 92 |
| 79 | 93 |
| 80 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { | 94 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { |
| 81 ASSERT(isolate == Isolate::Current()); | 95 ASSERT(isolate == Isolate::Current()); |
| 82 Deoptimizer* result = isolate->deoptimizer_data()->current_; | 96 Deoptimizer* result = isolate->deoptimizer_data()->current_; |
| 83 ASSERT(result != NULL); | 97 ASSERT(result != NULL); |
| 84 result->DeleteFrameDescriptions(); | 98 result->DeleteFrameDescriptions(); |
| 85 isolate->deoptimizer_data()->current_ = NULL; | 99 isolate->deoptimizer_data()->current_ = NULL; |
| 86 return result; | 100 return result; |
| 87 } | 101 } |
| 88 | 102 |
| 103 #ifdef ENABLE_DEBUGGER_SUPPORT | |
| 104 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( | |
| 105 JavaScriptFrame* frame, | |
| 106 int frame_index, | |
| 107 Isolate* isolate) { | |
| 108 ASSERT(isolate == Isolate::Current()); | |
| 109 ASSERT(frame->is_optimized()); | |
| 110 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL); | |
| 111 | |
| 112 // Get the function and code from the frame. | |
| 113 JSFunction* function = JSFunction::cast(frame->function()); | |
| 114 Code* code = frame->LookupCode(); | |
| 115 Address code_start_address = code->instruction_start(); | |
| 116 | |
| 117 // Locate the deoptimization point in the code. As we are at a call the | |
| 118 // return address must be at a place in the code with deoptimization support. | |
| 119 int deoptimization_index = Safepoint::kNoDeoptimizationIndex; | |
| 120 // Scope this as the safe point constructor will disallow allocation. | |
| 121 { | |
| 122 SafepointTable table(code); | |
| 123 for (unsigned i = 0; i < table.length(); ++i) { | |
| 124 Address address = code_start_address + table.GetPcOffset(i); | |
| 125 if (address == frame->pc()) { | |
| 126 SafepointEntry safepoint_entry = table.GetEntry(i); | |
| 127 ASSERT(safepoint_entry.deoptimization_index() != | |
| 128 Safepoint::kNoDeoptimizationIndex); | |
| 129 deoptimization_index = safepoint_entry.deoptimization_index(); | |
| 130 break; | |
| 131 } | |
| 132 } | |
| 133 } | |
| 134 ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex); | |
| 135 | |
| 136 // Always use the actual stack slots when calculating the fp to sp | |
| 137 // delta adding two for the function and context. | |
| 138 unsigned stack_slots = code->stack_slots(); | |
| 139 unsigned fp_to_sp_delta = ((stack_slots + 2) * kPointerSize); | |
| 140 | |
| 141 Deoptimizer* deoptimizer = new Deoptimizer(isolate, | |
| 142 function, | |
| 143 Deoptimizer::DEBUGGER, | |
| 144 deoptimization_index, | |
| 145 frame->pc(), | |
| 146 fp_to_sp_delta, | |
| 147 code); | |
| 148 Address tos = frame->fp() - fp_to_sp_delta; | |
| 149 deoptimizer->FillInputFrame(tos, frame); | |
| 150 | |
| 151 // Calculate the output frames. | |
| 152 Deoptimizer::ComputeOutputFrames(deoptimizer); | |
| 153 | |
| 154 // Create the GC safe output frame information and register it for GC | |
| 155 // handling. | |
| 156 ASSERT_LT(frame_index, deoptimizer->output_count()); | |
| 157 DeoptimizedFrameInfo* info = | |
| 158 new DeoptimizedFrameInfo(deoptimizer, frame_index); | |
| 159 isolate->deoptimizer_data()->deoptimized_frame_info_ = info; | |
| 160 | |
| 161 // Get the "simulated" top and size for the requested frame. | |
| 162 Address top = | |
| 163 reinterpret_cast<Address>(deoptimizer->output_[frame_index]->GetTop()); | |
| 164 intptr_t size = | |
| 165 deoptimizer->output_[frame_index]->GetFrameSize() / kPointerSize; | |
| 166 | |
| 167 // Done with the GC-unsafe frame descriptions. This re-enables allocation. | |
| 168 deoptimizer->DeleteFrameDescriptions(); | |
| 169 | |
|
fschneider
2011/06/29 10:47:35
Maybe put the GC-unsafe part inside an AssertNoAll
Søren Thygesen Gjesse
2011/06/29 12:42:10
The already happens due to the Deoptimizer constru
| |
| 170 // Allocate a heap number for the doubles belonging to this frame. | |
| 171 deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame( | |
| 172 top, size, info); | |
| 173 | |
|
fschneider
2011/06/29 10:47:35
Don't you have to de-allocate the deoptimizer? Or
Søren Thygesen Gjesse
2011/06/29 12:42:10
Good catch! Of cause.
| |
| 174 return info; | |
| 175 } | |
| 176 | |
| 177 | |
| 178 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, | |
| 179 Isolate* isolate) { | |
| 180 ASSERT(isolate == Isolate::Current()); | |
| 181 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == info); | |
| 182 delete info; | |
| 183 isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL; | |
| 184 } | |
| 185 #endif | |
| 89 | 186 |
| 90 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, | 187 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, |
| 91 int count, | 188 int count, |
| 92 BailoutType type) { | 189 BailoutType type) { |
| 93 TableEntryGenerator generator(masm, type, count); | 190 TableEntryGenerator generator(masm, type, count); |
| 94 generator.Generate(); | 191 generator.Generate(); |
| 95 } | 192 } |
| 96 | 193 |
| 97 | 194 |
| 98 class DeoptimizingVisitor : public OptimizedFunctionVisitor { | 195 class DeoptimizingVisitor : public OptimizedFunctionVisitor { |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 202 void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) { | 299 void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) { |
| 203 deoptimizer->DoComputeOutputFrames(); | 300 deoptimizer->DoComputeOutputFrames(); |
| 204 } | 301 } |
| 205 | 302 |
| 206 | 303 |
| 207 Deoptimizer::Deoptimizer(Isolate* isolate, | 304 Deoptimizer::Deoptimizer(Isolate* isolate, |
| 208 JSFunction* function, | 305 JSFunction* function, |
| 209 BailoutType type, | 306 BailoutType type, |
| 210 unsigned bailout_id, | 307 unsigned bailout_id, |
| 211 Address from, | 308 Address from, |
| 212 int fp_to_sp_delta) | 309 int fp_to_sp_delta, |
| 310 Code* optimized_code) | |
| 213 : isolate_(isolate), | 311 : isolate_(isolate), |
| 214 function_(function), | 312 function_(function), |
| 215 bailout_id_(bailout_id), | 313 bailout_id_(bailout_id), |
| 216 bailout_type_(type), | 314 bailout_type_(type), |
| 217 from_(from), | 315 from_(from), |
| 218 fp_to_sp_delta_(fp_to_sp_delta), | 316 fp_to_sp_delta_(fp_to_sp_delta), |
| 317 input_(NULL), | |
| 219 output_count_(0), | 318 output_count_(0), |
| 220 output_(NULL), | 319 output_(NULL), |
| 221 deferred_heap_numbers_(0) { | 320 deferred_heap_numbers_(0) { |
| 222 if (FLAG_trace_deopt && type != OSR) { | 321 if (FLAG_trace_deopt && type != OSR) { |
| 223 PrintF("**** DEOPT: "); | 322 if (type == DEBUGGER) { |
| 323 PrintF("**** DEOPT FOR DEBUGGER: "); | |
| 324 } else { | |
| 325 PrintF("**** DEOPT: "); | |
| 326 } | |
| 224 function->PrintName(); | 327 function->PrintName(); |
| 225 PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n", | 328 PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n", |
| 226 bailout_id, | 329 bailout_id, |
| 227 reinterpret_cast<intptr_t>(from), | 330 reinterpret_cast<intptr_t>(from), |
| 228 fp_to_sp_delta - (2 * kPointerSize)); | 331 fp_to_sp_delta - (2 * kPointerSize)); |
| 229 } else if (FLAG_trace_osr && type == OSR) { | 332 } else if (FLAG_trace_osr && type == OSR) { |
| 230 PrintF("**** OSR: "); | 333 PrintF("**** OSR: "); |
| 231 function->PrintName(); | 334 function->PrintName(); |
| 232 PrintF(" at ast id #%u, address 0x%" V8PRIxPTR ", frame size %d\n", | 335 PrintF(" at ast id #%u, address 0x%" V8PRIxPTR ", frame size %d\n", |
| 233 bailout_id, | 336 bailout_id, |
| 234 reinterpret_cast<intptr_t>(from), | 337 reinterpret_cast<intptr_t>(from), |
| 235 fp_to_sp_delta - (2 * kPointerSize)); | 338 fp_to_sp_delta - (2 * kPointerSize)); |
| 236 } | 339 } |
| 237 // Find the optimized code. | 340 // Find the optimized code. |
| 238 if (type == EAGER) { | 341 if (type == EAGER) { |
| 239 ASSERT(from == NULL); | 342 ASSERT(from == NULL); |
| 240 optimized_code_ = function_->code(); | 343 optimized_code_ = function_->code(); |
| 241 } else if (type == LAZY) { | 344 } else if (type == LAZY) { |
| 242 optimized_code_ = FindDeoptimizingCodeFromAddress(from); | 345 optimized_code_ = FindDeoptimizingCodeFromAddress(from); |
| 243 ASSERT(optimized_code_ != NULL); | 346 ASSERT(optimized_code_ != NULL); |
| 244 } else if (type == OSR) { | 347 } else if (type == OSR) { |
| 245 // The function has already been optimized and we're transitioning | 348 // The function has already been optimized and we're transitioning |
| 246 // from the unoptimized shared version to the optimized one in the | 349 // from the unoptimized shared version to the optimized one in the |
| 247 // function. The return address (from) points to unoptimized code. | 350 // function. The return address (from) points to unoptimized code. |
| 248 optimized_code_ = function_->code(); | 351 optimized_code_ = function_->code(); |
| 249 ASSERT(optimized_code_->kind() == Code::OPTIMIZED_FUNCTION); | 352 ASSERT(optimized_code_->kind() == Code::OPTIMIZED_FUNCTION); |
| 250 ASSERT(!optimized_code_->contains(from)); | 353 ASSERT(!optimized_code_->contains(from)); |
| 354 } else if (type == DEBUGGER) { | |
| 355 optimized_code_ = optimized_code; | |
| 356 ASSERT(optimized_code_->contains(from)); | |
| 251 } | 357 } |
| 252 ASSERT(HEAP->allow_allocation(false)); | 358 ASSERT(HEAP->allow_allocation(false)); |
| 253 unsigned size = ComputeInputFrameSize(); | 359 unsigned size = ComputeInputFrameSize(); |
| 254 input_ = new(size) FrameDescription(size, function); | 360 input_ = new(size) FrameDescription(size, function); |
| 361 #ifdef DEBUG | |
| 362 input_->SetKind(Code::OPTIMIZED_FUNCTION); | |
| 363 #endif | |
| 255 } | 364 } |
| 256 | 365 |
| 257 | 366 |
| 258 Deoptimizer::~Deoptimizer() { | 367 Deoptimizer::~Deoptimizer() { |
| 259 ASSERT(input_ == NULL && output_ == NULL); | 368 ASSERT(input_ == NULL && output_ == NULL); |
| 260 } | 369 } |
| 261 | 370 |
| 262 | 371 |
| 263 void Deoptimizer::DeleteFrameDescriptions() { | 372 void Deoptimizer::DeleteFrameDescriptions() { |
| 264 delete input_; | 373 delete input_; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 410 output_[index]->GetPc(), | 519 output_[index]->GetPc(), |
| 411 FullCodeGenerator::State2String( | 520 FullCodeGenerator::State2String( |
| 412 static_cast<FullCodeGenerator::State>( | 521 static_cast<FullCodeGenerator::State>( |
| 413 output_[index]->GetState()->value())), | 522 output_[index]->GetState()->value())), |
| 414 ms); | 523 ms); |
| 415 } | 524 } |
| 416 } | 525 } |
| 417 | 526 |
| 418 | 527 |
| 419 void Deoptimizer::MaterializeHeapNumbers() { | 528 void Deoptimizer::MaterializeHeapNumbers() { |
| 529 ASSERT_NE(DEBUGGER, bailout_type_); | |
| 420 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { | 530 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { |
| 421 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; | 531 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; |
| 422 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); | 532 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); |
| 423 if (FLAG_trace_deopt) { | 533 if (FLAG_trace_deopt) { |
| 424 PrintF("Materializing a new heap number %p [%e] in slot %p\n", | 534 PrintF("Materializing a new heap number %p [%e] in slot %p\n", |
| 425 reinterpret_cast<void*>(*num), | 535 reinterpret_cast<void*>(*num), |
| 426 d.value(), | 536 d.value(), |
| 427 d.slot_address()); | 537 d.slot_address()); |
| 428 } | 538 } |
| 429 | 539 |
| 430 Memory::Object_at(d.slot_address()) = *num; | 540 Memory::Object_at(d.slot_address()) = *num; |
| 431 } | 541 } |
| 432 } | 542 } |
| 433 | 543 |
| 434 | 544 |
| 545 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( | |
| 546 Address top, intptr_t size, DeoptimizedFrameInfo* info) { | |
| 547 ASSERT_EQ(DEBUGGER, bailout_type_); | |
| 548 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { | |
| 549 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; | |
| 550 | |
| 551 // Check of the heap number to materialize actually belongd to the frame | |
|
fschneider
2011/06/29 10:47:35
Check that the heap number to materialize actually
Søren Thygesen Gjesse
2011/06/29 12:42:10
Done.
| |
| 552 // being extracted. | |
| 553 Address slot = d.slot_address(); | |
| 554 if (top <= slot && slot < top + size) { | |
| 555 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); | |
| 556 if (FLAG_trace_deopt) { | |
| 557 PrintF("Materializing a new heap number %p [%e] in slot %p\n", | |
| 558 reinterpret_cast<void*>(*num), | |
| 559 d.value(), | |
| 560 d.slot_address()); | |
| 561 } | |
| 562 int expression_index = | |
| 563 info->expression_count_ - (slot - top) / kPointerSize - 1; | |
| 564 PrintF("Materializing a new heap number %p [%e] in index %d\n", | |
|
fschneider
2011/06/29 10:47:35
Remove duplicate PrintF, maybe add the expression
Søren Thygesen Gjesse
2011/06/29 12:42:10
Done.
| |
| 565 reinterpret_cast<void*>(*num), | |
| 566 d.value(), | |
| 567 expression_index); | |
| 568 info->SetExpression(expression_index, *num); | |
| 569 } | |
| 570 } | |
| 571 } | |
| 572 | |
| 573 | |
| 435 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, | 574 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, |
| 436 int frame_index, | 575 int frame_index, |
| 437 unsigned output_offset) { | 576 unsigned output_offset) { |
| 438 disasm::NameConverter converter; | 577 disasm::NameConverter converter; |
| 439 // A GC-safe temporary placeholder that we can put in the output frame. | 578 // A GC-safe temporary placeholder that we can put in the output frame. |
| 440 const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0)); | 579 const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0)); |
| 441 | 580 |
| 442 // Ignore commands marked as duplicate and act on the first non-duplicate. | 581 // Ignore commands marked as duplicate and act on the first non-duplicate. |
| 443 Translation::Opcode opcode = | 582 Translation::Opcode opcode = |
| 444 static_cast<Translation::Opcode>(iterator->Next()); | 583 static_cast<Translation::Opcode>(iterator->Next()); |
| (...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 977 return base - ((slot_index + 1) * kPointerSize); | 1116 return base - ((slot_index + 1) * kPointerSize); |
| 978 } else { | 1117 } else { |
| 979 // Incoming parameter. | 1118 // Incoming parameter. |
| 980 unsigned base = static_cast<unsigned>(GetFrameSize() - | 1119 unsigned base = static_cast<unsigned>(GetFrameSize() - |
| 981 deoptimizer->ComputeIncomingArgumentSize(GetFunction())); | 1120 deoptimizer->ComputeIncomingArgumentSize(GetFunction())); |
| 982 return base - ((slot_index + 1) * kPointerSize); | 1121 return base - ((slot_index + 1) * kPointerSize); |
| 983 } | 1122 } |
| 984 } | 1123 } |
| 985 | 1124 |
| 986 | 1125 |
| 1126 unsigned FrameDescription::GetExpressionCount(Deoptimizer* deoptimizer) { | |
| 1127 ASSERT_EQ(Code::FUNCTION, kind_); | |
| 1128 return (GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction())) | |
| 1129 / kPointerSize; | |
| 1130 } | |
| 1131 | |
| 1132 | |
| 1133 Object* FrameDescription::GetExpression(Deoptimizer* deoptimizer, int index) { | |
| 1134 ASSERT_EQ(Code::FUNCTION, kind_); | |
| 1135 unsigned offset = GetOffsetFromSlotIndex(deoptimizer, index); | |
| 1136 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); | |
| 1137 } | |
| 1138 | |
| 1139 | |
| 987 void TranslationBuffer::Add(int32_t value) { | 1140 void TranslationBuffer::Add(int32_t value) { |
| 988 // Encode the sign bit in the least significant bit. | 1141 // Encode the sign bit in the least significant bit. |
| 989 bool is_negative = (value < 0); | 1142 bool is_negative = (value < 0); |
| 990 uint32_t bits = ((is_negative ? -value : value) << 1) | | 1143 uint32_t bits = ((is_negative ? -value : value) << 1) | |
| 991 static_cast<int32_t>(is_negative); | 1144 static_cast<int32_t>(is_negative); |
| 992 // Encode the individual bytes using the least significant bit of | 1145 // Encode the individual bytes using the least significant bit of |
| 993 // each byte to indicate whether or not more bytes follow. | 1146 // each byte to indicate whether or not more bytes follow. |
| 994 do { | 1147 do { |
| 995 uint32_t next = bits >> 7; | 1148 uint32_t next = bits >> 7; |
| 996 contents_.Add(((bits << 1) & 0xFF) | (next != 0)); | 1149 contents_.Add(((bits << 1) & 0xFF) | (next != 0)); |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1249 return; | 1402 return; |
| 1250 } | 1403 } |
| 1251 frames_to_skip--; | 1404 frames_to_skip--; |
| 1252 } | 1405 } |
| 1253 } | 1406 } |
| 1254 | 1407 |
| 1255 UNREACHABLE(); | 1408 UNREACHABLE(); |
| 1256 } | 1409 } |
| 1257 | 1410 |
| 1258 | 1411 |
| 1412 DeoptimizedFrameInfo::DeoptimizedFrameInfo( | |
| 1413 Deoptimizer* deoptimizer, int frame_index) { | |
| 1414 FrameDescription* output_frame = deoptimizer->output_[frame_index]; | |
| 1415 expression_count_ = output_frame->GetExpressionCount(deoptimizer); | |
| 1416 expression_stack_ = new Object*[expression_count_]; | |
| 1417 for (int i = 0; i < expression_count_; i++) { | |
| 1418 SetExpression(i, output_frame->GetExpression(deoptimizer, i)); | |
| 1419 } | |
| 1420 } | |
| 1421 | |
| 1422 | |
| 1423 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() { | |
| 1424 delete expression_stack_; | |
| 1425 } | |
| 1426 | |
| 1427 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { | |
| 1428 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); | |
| 1429 } | |
| 1430 | |
| 1431 | |
| 1259 } } // namespace v8::internal | 1432 } } // namespace v8::internal |
| OLD | NEW |