Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 50 | 50 |
| 51 | 51 |
| 52 // When cloned, a frame is a deep copy of the original. | 52 // When cloned, a frame is a deep copy of the original. |
| 53 VirtualFrame::VirtualFrame(VirtualFrame* original) | 53 VirtualFrame::VirtualFrame(VirtualFrame* original) |
| 54 : cgen_(original->cgen_), | 54 : cgen_(original->cgen_), |
| 55 masm_(original->masm_), | 55 masm_(original->masm_), |
| 56 elements_(original->elements_.length()), | 56 elements_(original->elements_.length()), |
| 57 parameter_count_(original->parameter_count_), | 57 parameter_count_(original->parameter_count_), |
| 58 local_count_(original->local_count_), | 58 local_count_(original->local_count_), |
| 59 stack_pointer_(original->stack_pointer_), | 59 stack_pointer_(original->stack_pointer_), |
| 60 frame_pointer_(original->frame_pointer_), | 60 frame_pointer_(original->frame_pointer_) { |
| 61 frame_registers_(original->frame_registers_) { | |
| 62 // Copy all the elements from the original. | 61 // Copy all the elements from the original. |
| 63 for (int i = 0; i < original->elements_.length(); i++) { | 62 for (int i = 0; i < original->elements_.length(); i++) { |
| 64 elements_.Add(original->elements_[i]); | 63 elements_.Add(original->elements_[i]); |
| 65 } | 64 } |
| 66 for (int i = 0; i < kNumRegisters; i++) { | 65 for (int i = 0; i < kNumRegisters; i++) { |
| 67 register_locations_[i] = original->register_locations_[i]; | 66 register_locations_[i] = original->register_locations_[i]; |
| 68 } | 67 } |
| 69 } | 68 } |
| 70 | 69 |
| 71 | 70 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 145 | 144 |
| 146 for (int i = 0; i < count; i++) { | 145 for (int i = 0; i < count; i++) { |
| 147 FrameElement last = elements_.RemoveLast(); | 146 FrameElement last = elements_.RemoveLast(); |
| 148 if (last.is_register()) { | 147 if (last.is_register()) { |
| 149 // A hack to properly count register references for the code | 148 // A hack to properly count register references for the code |
| 150 // generator's current frame and also for other frames. The | 149 // generator's current frame and also for other frames. The |
| 151 // same code appears in PrepareMergeTo. | 150 // same code appears in PrepareMergeTo. |
| 152 if (cgen_->frame() == this) { | 151 if (cgen_->frame() == this) { |
| 153 Unuse(last.reg()); | 152 Unuse(last.reg()); |
| 154 } else { | 153 } else { |
| 155 frame_registers_.Unuse(last.reg()); | |
| 156 register_locations_[last.reg().code()] = kIllegalIndex; | 154 register_locations_[last.reg().code()] = kIllegalIndex; |
| 157 } | 155 } |
| 158 } | 156 } |
| 159 } | 157 } |
| 160 } | 158 } |
| 161 | 159 |
| 162 | 160 |
| 163 void VirtualFrame::Use(Register reg, int index) { | 161 void VirtualFrame::Use(Register reg, int index) { |
| 164 ASSERT(frame_registers_.count(reg) == 0); | |
| 165 ASSERT(register_locations_[reg.code()] == kIllegalIndex); | 162 ASSERT(register_locations_[reg.code()] == kIllegalIndex); |
| 166 register_locations_[reg.code()] = index; | 163 register_locations_[reg.code()] = index; |
| 167 frame_registers_.Use(reg); | |
| 168 cgen_->allocator()->Use(reg); | 164 cgen_->allocator()->Use(reg); |
| 169 } | 165 } |
| 170 | 166 |
| 171 | 167 |
| 172 void VirtualFrame::Unuse(Register reg) { | 168 void VirtualFrame::Unuse(Register reg) { |
| 173 ASSERT(frame_registers_.count(reg) == 1); | |
| 174 ASSERT(register_locations_[reg.code()] != kIllegalIndex); | 169 ASSERT(register_locations_[reg.code()] != kIllegalIndex); |
| 175 register_locations_[reg.code()] = kIllegalIndex; | 170 register_locations_[reg.code()] = kIllegalIndex; |
| 176 frame_registers_.Unuse(reg); | |
| 177 cgen_->allocator()->Unuse(reg); | 171 cgen_->allocator()->Unuse(reg); |
| 178 } | 172 } |
| 179 | 173 |
| 180 | 174 |
| 181 void VirtualFrame::Spill(Register target) { | 175 void VirtualFrame::Spill(Register target) { |
| 182 if (!frame_registers_.is_used(target)) return; | 176 if (is_used(target)) { |
| 183 for (int i = 0; i < elements_.length(); i++) { | 177 SpillElementAt(register_index(target)); |
| 184 if (elements_[i].is_register() && elements_[i].reg().is(target)) { | |
| 185 SpillElementAt(i); | |
| 186 } | |
| 187 } | 178 } |
| 188 } | 179 } |
| 189 | 180 |
| 190 | 181 |
| 191 // Spill any register if possible, making its external reference count zero. | 182 // Spill any register if possible, making its external reference count zero. |
| 192 Register VirtualFrame::SpillAnyRegister() { | 183 Register VirtualFrame::SpillAnyRegister() { |
| 193 // Find the leftmost (ordered by register code), least | 184 // Find the leftmost (ordered by register code), least |
| 194 // internally-referenced register whose internal reference count matches | 185 // internally-referenced register whose internal reference count matches |
| 195 // its external reference count (so that spilling it from the frame frees | 186 // its external reference count (so that spilling it from the frame frees |
| 196 // it for use). | 187 // it for use). |
| 197 int min_count = kMaxInt; | 188 // This function must be called with no free registers - all counts |
| 198 int best_register_code = no_reg.code_; | 189 // in the CodeGenerator's Allocator must be above 0. |
|
Kevin Millikin (Chromium)
2009/03/25 09:54:11
I don't like this comment. It's not really a true
William Hesse
2012/05/07 09:35:42
Done.
| |
| 199 | |
| 200 for (int i = 0; i < kNumRegisters; i++) { | 190 for (int i = 0; i < kNumRegisters; i++) { |
| 201 int count = frame_registers_.count(i); | 191 if (is_used(i) && cgen_->allocator()->count(i) == 1) { |
| 202 if (count < min_count && count == cgen_->allocator()->count(i)) { | 192 Register result = { i }; |
| 203 min_count = count; | 193 Spill(result); |
| 204 best_register_code = i; | 194 ASSERT(!cgen_->allocator()->is_used(result)); |
| 195 return result; | |
| 205 } | 196 } |
| 206 } | 197 } |
| 207 | 198 return no_reg; |
| 208 Register result = { best_register_code }; | |
| 209 if (result.is_valid()) { | |
| 210 Spill(result); | |
| 211 ASSERT(!cgen_->allocator()->is_used(result)); | |
| 212 } | |
| 213 return result; | |
| 214 } | 199 } |
| 215 | 200 |
| 216 | 201 |
| 217 // Make the type of the element at a given index be MEMORY. | 202 // Make the type of the element at a given index be MEMORY. |
| 218 void VirtualFrame::SpillElementAt(int index) { | 203 void VirtualFrame::SpillElementAt(int index) { |
| 219 if (!elements_[index].is_valid()) return; | 204 if (!elements_[index].is_valid()) return; |
| 220 | 205 |
| 221 SyncElementAt(index); | 206 SyncElementAt(index); |
| 222 // The element is now in memory. Its copied flag is preserved. | 207 // The element is now in memory. Its copied flag is preserved. |
| 223 FrameElement new_element = FrameElement::MemoryElement(); | 208 FrameElement new_element = FrameElement::MemoryElement(); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 272 // No code needs to be generated to move values to memory if | 257 // No code needs to be generated to move values to memory if |
| 273 // they are already synced. We perform those moves here, before | 258 // they are already synced. We perform those moves here, before |
| 274 // merging. | 259 // merging. |
| 275 if (source.is_register()) { | 260 if (source.is_register()) { |
| 276 // If the frame is the code generator's current frame, we have | 261 // If the frame is the code generator's current frame, we have |
| 277 // to decrement both the frame-internal and global register | 262 // to decrement both the frame-internal and global register |
| 278 // counts. | 263 // counts. |
| 279 if (cgen_->frame() == this) { | 264 if (cgen_->frame() == this) { |
| 280 Unuse(source.reg()); | 265 Unuse(source.reg()); |
| 281 } else { | 266 } else { |
| 282 frame_registers_.Unuse(source.reg()); | |
| 283 register_locations_[source.reg().code()] = kIllegalIndex; | 267 register_locations_[source.reg().code()] = kIllegalIndex; |
| 284 } | 268 } |
| 285 } | 269 } |
| 286 elements_[i] = target; | 270 elements_[i] = target; |
| 287 } else if (target.is_register() && !target.is_synced() && | 271 } else if (target.is_register() && !target.is_synced() && |
| 288 !source.is_memory()) { | 272 !source.is_memory()) { |
| 289 // If an element's target is a register that doesn't need to be | 273 // If an element's target is a register that doesn't need to be |
| 290 // synced, and the element is not in memory, then the sync state | 274 // synced, and the element is not in memory, then the sync state |
| 291 // of the element is irrelevant. We clear the sync bit. | 275 // of the element is irrelevant. We clear the sync bit. |
| 292 ASSERT(source.is_valid()); | 276 ASSERT(source.is_valid()); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 383 && original.handle().is_identical_to(value->handle()); | 367 && original.handle().is_identical_to(value->handle()); |
| 384 if (same_register || same_constant) { | 368 if (same_register || same_constant) { |
| 385 value->Unuse(); | 369 value->Unuse(); |
| 386 return; | 370 return; |
| 387 } | 371 } |
| 388 | 372 |
| 389 InvalidateFrameSlotAt(frame_index); | 373 InvalidateFrameSlotAt(frame_index); |
| 390 | 374 |
| 391 FrameElement new_element; | 375 FrameElement new_element; |
| 392 if (value->is_register()) { | 376 if (value->is_register()) { |
| 393 // There are two cases depending no whether the register already | 377 if (is_used(value->reg())) { |
| 394 // occurs in the frame or not. | 378 // The register already appears on the frame. Either the existing |
| 395 if (register_count(value->reg()) == 0) { | 379 // register element, or the new element at frame_index, must be made |
| 396 Use(value->reg(), frame_index); | 380 // a copy. |
| 397 elements_[frame_index] = | 381 int i = register_index(value->reg()); |
| 398 FrameElement::RegisterElement(value->reg(), | |
| 399 FrameElement::NOT_SYNCED); | |
| 400 } else { | |
| 401 int i = 0; | |
| 402 for (; i < elements_.length(); i++) { | |
| 403 if (elements_[i].is_register() && elements_[i].reg().is(value->reg())) { | |
| 404 break; | |
| 405 } | |
| 406 } | |
| 407 ASSERT(i < elements_.length()); | |
| 408 | |
| 409 if (i < frame_index) { | 382 if (i < frame_index) { |
| 410 // The register backing store is lower in the frame than its copy. | 383 // The register FrameElement is lower in the frame than the new copy. |
| 411 elements_[frame_index] = CopyElementAt(i); | 384 elements_[frame_index] = CopyElementAt(i); |
| 412 } else { | 385 } else { |
| 413 // There was an early bailout for the case of setting a | 386 // There was an early bailout for the case of setting a |
| 414 // register element to itself. | 387 // register element to itself. |
| 415 ASSERT(i != frame_index); | 388 ASSERT(i != frame_index); |
| 416 elements_[frame_index] = elements_[i]; | 389 elements_[frame_index] = elements_[i]; |
| 417 elements_[i] = CopyElementAt(frame_index); | 390 elements_[i] = CopyElementAt(frame_index); |
| 418 if (elements_[frame_index].is_synced()) { | 391 if (elements_[frame_index].is_synced()) { |
| 419 elements_[i].set_sync(); | 392 elements_[i].set_sync(); |
| 420 } | 393 } |
| 421 elements_[frame_index].clear_sync(); | 394 elements_[frame_index].clear_sync(); |
| 422 register_locations_[value->reg().code()] = frame_index; | 395 register_locations_[value->reg().code()] = frame_index; |
| 423 for (int j = i + 1; j < elements_.length(); j++) { | 396 for (int j = i + 1; j < elements_.length(); j++) { |
| 424 if (elements_[j].is_copy() && elements_[j].index() == i) { | 397 if (elements_[j].is_copy() && elements_[j].index() == i) { |
| 425 elements_[j].set_index(frame_index); | 398 elements_[j].set_index(frame_index); |
| 426 } | 399 } |
| 427 } | 400 } |
| 428 } | 401 } |
| 402 } else { | |
| 403 // The register value->reg() was not already used on the frame. | |
| 404 Use(value->reg(), frame_index); | |
| 405 elements_[frame_index] = | |
| 406 FrameElement::RegisterElement(value->reg(), | |
| 407 FrameElement::NOT_SYNCED); | |
| 429 } | 408 } |
| 430 } else { | 409 } else { |
| 431 ASSERT(value->is_constant()); | 410 ASSERT(value->is_constant()); |
| 432 elements_[frame_index] = | 411 elements_[frame_index] = |
| 433 FrameElement::ConstantElement(value->handle(), | 412 FrameElement::ConstantElement(value->handle(), |
| 434 FrameElement::NOT_SYNCED); | 413 FrameElement::NOT_SYNCED); |
| 435 } | 414 } |
| 436 value->Unuse(); | 415 value->Unuse(); |
| 437 } | 416 } |
| 438 | 417 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 490 // a different signature. | 469 // a different signature. |
| 491 UNREACHABLE(); | 470 UNREACHABLE(); |
| 492 break; | 471 break; |
| 493 } | 472 } |
| 494 PrepareForCall(spilled_args, dropped_args); | 473 PrepareForCall(spilled_args, dropped_args); |
| 495 return RawCallCodeObject(code, rmode); | 474 return RawCallCodeObject(code, rmode); |
| 496 } | 475 } |
| 497 | 476 |
| 498 | 477 |
| 499 void VirtualFrame::Push(Register reg) { | 478 void VirtualFrame::Push(Register reg) { |
| 500 FrameElement new_element; | 479 if (is_used(reg)) { |
| 501 if (register_count(reg) == 0) { | 480 elements_.Add(CopyElementAt(register_index(reg))); |
| 481 } else { | |
| 502 Use(reg, elements_.length()); | 482 Use(reg, elements_.length()); |
| 503 new_element = | 483 elements_.Add(FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED)); |
| 504 FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED); | |
| 505 } else { | |
| 506 for (int i = 0; i < elements_.length(); i++) { | |
| 507 FrameElement element = elements_[i]; | |
| 508 if (element.is_register() && element.reg().is(reg)) { | |
| 509 new_element = CopyElementAt(i); | |
| 510 break; | |
| 511 } | |
| 512 } | |
| 513 } | 484 } |
| 514 elements_.Add(new_element); | |
| 515 } | 485 } |
| 516 | 486 |
| 517 | 487 |
| 518 void VirtualFrame::Push(Handle<Object> value) { | 488 void VirtualFrame::Push(Handle<Object> value) { |
| 519 elements_.Add(FrameElement::ConstantElement(value, | 489 elements_.Add(FrameElement::ConstantElement(value, |
| 520 FrameElement::NOT_SYNCED)); | 490 FrameElement::NOT_SYNCED)); |
| 521 } | 491 } |
| 522 | 492 |
| 523 | 493 |
| 524 void VirtualFrame::Push(Result* result) { | 494 void VirtualFrame::Push(Result* result) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 562 #ifdef DEBUG | 532 #ifdef DEBUG |
| 563 // These are sanity checks in debug builds, but we do not need to | 533 // These are sanity checks in debug builds, but we do not need to |
| 564 // use them to distinguish frames at merge points. | 534 // use them to distinguish frames at merge points. |
| 565 if (cgen_ != other->cgen_) return false; | 535 if (cgen_ != other->cgen_) return false; |
| 566 if (masm_ != other->masm_) return false; | 536 if (masm_ != other->masm_) return false; |
| 567 if (parameter_count_ != other->parameter_count_) return false; | 537 if (parameter_count_ != other->parameter_count_) return false; |
| 568 if (local_count_ != other->local_count_) return false; | 538 if (local_count_ != other->local_count_) return false; |
| 569 if (frame_pointer_ != other->frame_pointer_) return false; | 539 if (frame_pointer_ != other->frame_pointer_) return false; |
| 570 | 540 |
| 571 for (int i = 0; i < kNumRegisters; i++) { | 541 for (int i = 0; i < kNumRegisters; i++) { |
| 572 if (frame_registers_.count(i) != other->frame_registers_.count(i)) { | |
| 573 return false; | |
| 574 } | |
| 575 if (register_locations_[i] != other->register_locations_[i]) { | 542 if (register_locations_[i] != other->register_locations_[i]) { |
| 576 return false; | 543 return false; |
| 577 } | 544 } |
| 578 } | 545 } |
| 579 if (elements_.length() != other->elements_.length()) return false; | 546 if (elements_.length() != other->elements_.length()) return false; |
| 580 #endif | 547 #endif |
| 581 if (stack_pointer_ != other->stack_pointer_) return false; | 548 if (stack_pointer_ != other->stack_pointer_) return false; |
| 582 for (int i = 0; i < elements_.length(); i++) { | 549 for (int i = 0; i < elements_.length(); i++) { |
| 583 if (!elements_[i].Equals(other->elements_[i])) return false; | 550 if (!elements_[i].Equals(other->elements_[i])) return false; |
| 584 } | 551 } |
| 585 | 552 |
| 586 return true; | 553 return true; |
| 587 } | 554 } |
| 588 | 555 |
| 589 } } // namespace v8::internal | 556 } } // namespace v8::internal |
| OLD | NEW |