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 |
| 170 // Allocate a heap number for the doubles belonging to this frame. |
| 171 deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame( |
| 172 top, size, info); |
| 173 |
| 174 // Finished using the deoptimizer instance. |
| 175 delete deoptimizer; |
| 176 |
| 177 return info; |
| 178 } |
| 179 |
| 180 |
| 181 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, |
| 182 Isolate* isolate) { |
| 183 ASSERT(isolate == Isolate::Current()); |
| 184 ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == info); |
| 185 delete info; |
| 186 isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL; |
| 187 } |
| 188 #endif |
89 | 189 |
90 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, | 190 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, |
91 int count, | 191 int count, |
92 BailoutType type) { | 192 BailoutType type) { |
93 TableEntryGenerator generator(masm, type, count); | 193 TableEntryGenerator generator(masm, type, count); |
94 generator.Generate(); | 194 generator.Generate(); |
95 } | 195 } |
96 | 196 |
97 | 197 |
98 class DeoptimizingVisitor : public OptimizedFunctionVisitor { | 198 class DeoptimizingVisitor : public OptimizedFunctionVisitor { |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) { | 302 void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) { |
203 deoptimizer->DoComputeOutputFrames(); | 303 deoptimizer->DoComputeOutputFrames(); |
204 } | 304 } |
205 | 305 |
206 | 306 |
207 Deoptimizer::Deoptimizer(Isolate* isolate, | 307 Deoptimizer::Deoptimizer(Isolate* isolate, |
208 JSFunction* function, | 308 JSFunction* function, |
209 BailoutType type, | 309 BailoutType type, |
210 unsigned bailout_id, | 310 unsigned bailout_id, |
211 Address from, | 311 Address from, |
212 int fp_to_sp_delta) | 312 int fp_to_sp_delta, |
| 313 Code* optimized_code) |
213 : isolate_(isolate), | 314 : isolate_(isolate), |
214 function_(function), | 315 function_(function), |
215 bailout_id_(bailout_id), | 316 bailout_id_(bailout_id), |
216 bailout_type_(type), | 317 bailout_type_(type), |
217 from_(from), | 318 from_(from), |
218 fp_to_sp_delta_(fp_to_sp_delta), | 319 fp_to_sp_delta_(fp_to_sp_delta), |
| 320 input_(NULL), |
219 output_count_(0), | 321 output_count_(0), |
220 output_(NULL), | 322 output_(NULL), |
221 deferred_heap_numbers_(0) { | 323 deferred_heap_numbers_(0) { |
222 if (FLAG_trace_deopt && type != OSR) { | 324 if (FLAG_trace_deopt && type != OSR) { |
223 PrintF("**** DEOPT: "); | 325 if (type == DEBUGGER) { |
| 326 PrintF("**** DEOPT FOR DEBUGGER: "); |
| 327 } else { |
| 328 PrintF("**** DEOPT: "); |
| 329 } |
224 function->PrintName(); | 330 function->PrintName(); |
225 PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n", | 331 PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n", |
226 bailout_id, | 332 bailout_id, |
227 reinterpret_cast<intptr_t>(from), | 333 reinterpret_cast<intptr_t>(from), |
228 fp_to_sp_delta - (2 * kPointerSize)); | 334 fp_to_sp_delta - (2 * kPointerSize)); |
229 } else if (FLAG_trace_osr && type == OSR) { | 335 } else if (FLAG_trace_osr && type == OSR) { |
230 PrintF("**** OSR: "); | 336 PrintF("**** OSR: "); |
231 function->PrintName(); | 337 function->PrintName(); |
232 PrintF(" at ast id #%u, address 0x%" V8PRIxPTR ", frame size %d\n", | 338 PrintF(" at ast id #%u, address 0x%" V8PRIxPTR ", frame size %d\n", |
233 bailout_id, | 339 bailout_id, |
234 reinterpret_cast<intptr_t>(from), | 340 reinterpret_cast<intptr_t>(from), |
235 fp_to_sp_delta - (2 * kPointerSize)); | 341 fp_to_sp_delta - (2 * kPointerSize)); |
236 } | 342 } |
237 // Find the optimized code. | 343 // Find the optimized code. |
238 if (type == EAGER) { | 344 if (type == EAGER) { |
239 ASSERT(from == NULL); | 345 ASSERT(from == NULL); |
240 optimized_code_ = function_->code(); | 346 optimized_code_ = function_->code(); |
241 } else if (type == LAZY) { | 347 } else if (type == LAZY) { |
242 optimized_code_ = FindDeoptimizingCodeFromAddress(from); | 348 optimized_code_ = FindDeoptimizingCodeFromAddress(from); |
243 ASSERT(optimized_code_ != NULL); | 349 ASSERT(optimized_code_ != NULL); |
244 } else if (type == OSR) { | 350 } else if (type == OSR) { |
245 // The function has already been optimized and we're transitioning | 351 // The function has already been optimized and we're transitioning |
246 // from the unoptimized shared version to the optimized one in the | 352 // from the unoptimized shared version to the optimized one in the |
247 // function. The return address (from) points to unoptimized code. | 353 // function. The return address (from) points to unoptimized code. |
248 optimized_code_ = function_->code(); | 354 optimized_code_ = function_->code(); |
249 ASSERT(optimized_code_->kind() == Code::OPTIMIZED_FUNCTION); | 355 ASSERT(optimized_code_->kind() == Code::OPTIMIZED_FUNCTION); |
250 ASSERT(!optimized_code_->contains(from)); | 356 ASSERT(!optimized_code_->contains(from)); |
| 357 } else if (type == DEBUGGER) { |
| 358 optimized_code_ = optimized_code; |
| 359 ASSERT(optimized_code_->contains(from)); |
251 } | 360 } |
252 ASSERT(HEAP->allow_allocation(false)); | 361 ASSERT(HEAP->allow_allocation(false)); |
253 unsigned size = ComputeInputFrameSize(); | 362 unsigned size = ComputeInputFrameSize(); |
254 input_ = new(size) FrameDescription(size, function); | 363 input_ = new(size) FrameDescription(size, function); |
| 364 #ifdef DEBUG |
| 365 input_->SetKind(Code::OPTIMIZED_FUNCTION); |
| 366 #endif |
255 } | 367 } |
256 | 368 |
257 | 369 |
258 Deoptimizer::~Deoptimizer() { | 370 Deoptimizer::~Deoptimizer() { |
259 ASSERT(input_ == NULL && output_ == NULL); | 371 ASSERT(input_ == NULL && output_ == NULL); |
260 } | 372 } |
261 | 373 |
262 | 374 |
263 void Deoptimizer::DeleteFrameDescriptions() { | 375 void Deoptimizer::DeleteFrameDescriptions() { |
264 delete input_; | 376 delete input_; |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 output_[index]->GetPc(), | 522 output_[index]->GetPc(), |
411 FullCodeGenerator::State2String( | 523 FullCodeGenerator::State2String( |
412 static_cast<FullCodeGenerator::State>( | 524 static_cast<FullCodeGenerator::State>( |
413 output_[index]->GetState()->value())), | 525 output_[index]->GetState()->value())), |
414 ms); | 526 ms); |
415 } | 527 } |
416 } | 528 } |
417 | 529 |
418 | 530 |
419 void Deoptimizer::MaterializeHeapNumbers() { | 531 void Deoptimizer::MaterializeHeapNumbers() { |
| 532 ASSERT_NE(DEBUGGER, bailout_type_); |
420 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { | 533 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { |
421 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; | 534 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; |
422 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); | 535 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); |
423 if (FLAG_trace_deopt) { | 536 if (FLAG_trace_deopt) { |
424 PrintF("Materializing a new heap number %p [%e] in slot %p\n", | 537 PrintF("Materializing a new heap number %p [%e] in slot %p\n", |
425 reinterpret_cast<void*>(*num), | 538 reinterpret_cast<void*>(*num), |
426 d.value(), | 539 d.value(), |
427 d.slot_address()); | 540 d.slot_address()); |
428 } | 541 } |
429 | 542 |
430 Memory::Object_at(d.slot_address()) = *num; | 543 Memory::Object_at(d.slot_address()) = *num; |
431 } | 544 } |
432 } | 545 } |
433 | 546 |
434 | 547 |
| 548 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 549 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( |
| 550 Address top, intptr_t size, DeoptimizedFrameInfo* info) { |
| 551 ASSERT_EQ(DEBUGGER, bailout_type_); |
| 552 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { |
| 553 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; |
| 554 |
| 555 // Check of the heap number to materialize actually belong to the frame |
| 556 // being extracted. |
| 557 Address slot = d.slot_address(); |
| 558 if (top <= slot && slot < top + size) { |
| 559 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); |
| 560 int expression_index = |
| 561 info->expression_count_ - (slot - top) / kPointerSize - 1; |
| 562 if (FLAG_trace_deopt) { |
| 563 PrintF("Materializing a new heap number %p [%e] in slot %p" |
| 564 "for expression stack index %d\n", |
| 565 reinterpret_cast<void*>(*num), |
| 566 d.value(), |
| 567 d.slot_address(), |
| 568 expression_index); |
| 569 } |
| 570 info->SetExpression(expression_index, *num); |
| 571 } |
| 572 } |
| 573 } |
| 574 #endif |
| 575 |
| 576 |
435 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, | 577 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, |
436 int frame_index, | 578 int frame_index, |
437 unsigned output_offset) { | 579 unsigned output_offset) { |
438 disasm::NameConverter converter; | 580 disasm::NameConverter converter; |
439 // A GC-safe temporary placeholder that we can put in the output frame. | 581 // 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)); | 582 const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0)); |
441 | 583 |
442 // Ignore commands marked as duplicate and act on the first non-duplicate. | 584 // Ignore commands marked as duplicate and act on the first non-duplicate. |
443 Translation::Opcode opcode = | 585 Translation::Opcode opcode = |
444 static_cast<Translation::Opcode>(iterator->Next()); | 586 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); | 1119 return base - ((slot_index + 1) * kPointerSize); |
978 } else { | 1120 } else { |
979 // Incoming parameter. | 1121 // Incoming parameter. |
980 unsigned base = static_cast<unsigned>(GetFrameSize() - | 1122 unsigned base = static_cast<unsigned>(GetFrameSize() - |
981 deoptimizer->ComputeIncomingArgumentSize(GetFunction())); | 1123 deoptimizer->ComputeIncomingArgumentSize(GetFunction())); |
982 return base - ((slot_index + 1) * kPointerSize); | 1124 return base - ((slot_index + 1) * kPointerSize); |
983 } | 1125 } |
984 } | 1126 } |
985 | 1127 |
986 | 1128 |
| 1129 unsigned FrameDescription::GetExpressionCount(Deoptimizer* deoptimizer) { |
| 1130 ASSERT_EQ(Code::FUNCTION, kind_); |
| 1131 return (GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction())) |
| 1132 / kPointerSize; |
| 1133 } |
| 1134 |
| 1135 |
| 1136 Object* FrameDescription::GetExpression(Deoptimizer* deoptimizer, int index) { |
| 1137 ASSERT_EQ(Code::FUNCTION, kind_); |
| 1138 unsigned offset = GetOffsetFromSlotIndex(deoptimizer, index); |
| 1139 return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); |
| 1140 } |
| 1141 |
| 1142 |
987 void TranslationBuffer::Add(int32_t value) { | 1143 void TranslationBuffer::Add(int32_t value) { |
988 // Encode the sign bit in the least significant bit. | 1144 // Encode the sign bit in the least significant bit. |
989 bool is_negative = (value < 0); | 1145 bool is_negative = (value < 0); |
990 uint32_t bits = ((is_negative ? -value : value) << 1) | | 1146 uint32_t bits = ((is_negative ? -value : value) << 1) | |
991 static_cast<int32_t>(is_negative); | 1147 static_cast<int32_t>(is_negative); |
992 // Encode the individual bytes using the least significant bit of | 1148 // Encode the individual bytes using the least significant bit of |
993 // each byte to indicate whether or not more bytes follow. | 1149 // each byte to indicate whether or not more bytes follow. |
994 do { | 1150 do { |
995 uint32_t next = bits >> 7; | 1151 uint32_t next = bits >> 7; |
996 contents_.Add(((bits << 1) & 0xFF) | (next != 0)); | 1152 contents_.Add(((bits << 1) & 0xFF) | (next != 0)); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1249 return; | 1405 return; |
1250 } | 1406 } |
1251 frames_to_skip--; | 1407 frames_to_skip--; |
1252 } | 1408 } |
1253 } | 1409 } |
1254 | 1410 |
1255 UNREACHABLE(); | 1411 UNREACHABLE(); |
1256 } | 1412 } |
1257 | 1413 |
1258 | 1414 |
| 1415 DeoptimizedFrameInfo::DeoptimizedFrameInfo( |
| 1416 Deoptimizer* deoptimizer, int frame_index) { |
| 1417 FrameDescription* output_frame = deoptimizer->output_[frame_index]; |
| 1418 expression_count_ = output_frame->GetExpressionCount(deoptimizer); |
| 1419 expression_stack_ = new Object*[expression_count_]; |
| 1420 for (int i = 0; i < expression_count_; i++) { |
| 1421 SetExpression(i, output_frame->GetExpression(deoptimizer, i)); |
| 1422 } |
| 1423 } |
| 1424 |
| 1425 |
| 1426 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() { |
| 1427 delete expression_stack_; |
| 1428 } |
| 1429 |
| 1430 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { |
| 1431 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); |
| 1432 } |
| 1433 |
| 1434 |
1259 } } // namespace v8::internal | 1435 } } // namespace v8::internal |
OLD | NEW |