| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 30 matching lines...) Expand all Loading... |
| 41 class HGraph; | 41 class HGraph; |
| 42 class HInstruction; | 42 class HInstruction; |
| 43 class HPhi; | 43 class HPhi; |
| 44 class HTracer; | 44 class HTracer; |
| 45 class HValue; | 45 class HValue; |
| 46 class BitVector; | 46 class BitVector; |
| 47 class StringStream; | 47 class StringStream; |
| 48 | 48 |
| 49 class LArgument; | 49 class LArgument; |
| 50 class LChunk; | 50 class LChunk; |
| 51 class LOperand; |
| 52 class LUnallocated; |
| 51 class LConstantOperand; | 53 class LConstantOperand; |
| 52 class LGap; | 54 class LGap; |
| 53 class LParallelMove; | 55 class LParallelMove; |
| 54 class LPointerMap; | 56 class LPointerMap; |
| 55 class LStackSlot; | 57 class LStackSlot; |
| 56 class LRegister; | 58 class LRegister; |
| 57 | 59 |
| 58 | 60 |
| 59 // This class represents a single point of a LOperand's lifetime. | 61 // This class represents a single point of a LOperand's lifetime. |
| 60 // For each lithium instruction there are exactly two lifetime positions: | 62 // For each lithium instruction there are exactly two lifetime positions: |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 }; | 144 }; |
| 143 | 145 |
| 144 | 146 |
| 145 enum RegisterKind { | 147 enum RegisterKind { |
| 146 NONE, | 148 NONE, |
| 147 GENERAL_REGISTERS, | 149 GENERAL_REGISTERS, |
| 148 DOUBLE_REGISTERS | 150 DOUBLE_REGISTERS |
| 149 }; | 151 }; |
| 150 | 152 |
| 151 | 153 |
| 152 class LOperand: public ZoneObject { | |
| 153 public: | |
| 154 enum Kind { | |
| 155 INVALID, | |
| 156 UNALLOCATED, | |
| 157 CONSTANT_OPERAND, | |
| 158 STACK_SLOT, | |
| 159 DOUBLE_STACK_SLOT, | |
| 160 REGISTER, | |
| 161 DOUBLE_REGISTER, | |
| 162 ARGUMENT | |
| 163 }; | |
| 164 | |
| 165 LOperand() : value_(KindField::encode(INVALID)) { } | |
| 166 | |
| 167 Kind kind() const { return KindField::decode(value_); } | |
| 168 int index() const { return static_cast<int>(value_) >> kKindFieldWidth; } | |
| 169 bool IsConstantOperand() const { return kind() == CONSTANT_OPERAND; } | |
| 170 bool IsStackSlot() const { return kind() == STACK_SLOT; } | |
| 171 bool IsDoubleStackSlot() const { return kind() == DOUBLE_STACK_SLOT; } | |
| 172 bool IsRegister() const { return kind() == REGISTER; } | |
| 173 bool IsDoubleRegister() const { return kind() == DOUBLE_REGISTER; } | |
| 174 bool IsArgument() const { return kind() == ARGUMENT; } | |
| 175 bool IsUnallocated() const { return kind() == UNALLOCATED; } | |
| 176 bool Equals(LOperand* other) const { return value_ == other->value_; } | |
| 177 int VirtualRegister(); | |
| 178 | |
| 179 void PrintTo(StringStream* stream); | |
| 180 void ConvertTo(Kind kind, int index) { | |
| 181 value_ = KindField::encode(kind); | |
| 182 value_ |= index << kKindFieldWidth; | |
| 183 ASSERT(this->index() == index); | |
| 184 } | |
| 185 | |
| 186 protected: | |
| 187 static const int kKindFieldWidth = 3; | |
| 188 class KindField : public BitField<Kind, 0, kKindFieldWidth> { }; | |
| 189 | |
| 190 LOperand(Kind kind, int index) { ConvertTo(kind, index); } | |
| 191 | |
| 192 unsigned value_; | |
| 193 }; | |
| 194 | |
| 195 | |
| 196 class LUnallocated: public LOperand { | |
| 197 public: | |
| 198 enum Policy { | |
| 199 NONE, | |
| 200 ANY, | |
| 201 FIXED_REGISTER, | |
| 202 FIXED_DOUBLE_REGISTER, | |
| 203 FIXED_SLOT, | |
| 204 MUST_HAVE_REGISTER, | |
| 205 WRITABLE_REGISTER, | |
| 206 SAME_AS_FIRST_INPUT, | |
| 207 IGNORE | |
| 208 }; | |
| 209 | |
| 210 // Lifetime of operand inside the instruction. | |
| 211 enum Lifetime { | |
| 212 // USED_AT_START operand is guaranteed to be live only at | |
| 213 // instruction start. Register allocator is free to assign the same register | |
| 214 // to some other operand used inside instruction (i.e. temporary or | |
| 215 // output). | |
| 216 USED_AT_START, | |
| 217 | |
| 218 // USED_AT_END operand is treated as live until the end of | |
| 219 // instruction. This means that register allocator will not reuse it's | |
| 220 // register for any other operand inside instruction. | |
| 221 USED_AT_END | |
| 222 }; | |
| 223 | |
| 224 explicit LUnallocated(Policy policy) : LOperand(UNALLOCATED, 0) { | |
| 225 Initialize(policy, 0, USED_AT_END); | |
| 226 } | |
| 227 | |
| 228 LUnallocated(Policy policy, int fixed_index) : LOperand(UNALLOCATED, 0) { | |
| 229 Initialize(policy, fixed_index, USED_AT_END); | |
| 230 } | |
| 231 | |
| 232 LUnallocated(Policy policy, Lifetime lifetime) : LOperand(UNALLOCATED, 0) { | |
| 233 Initialize(policy, 0, lifetime); | |
| 234 } | |
| 235 | |
| 236 // The superclass has a KindField. Some policies have a signed fixed | |
| 237 // index in the upper bits. | |
| 238 static const int kPolicyWidth = 4; | |
| 239 static const int kLifetimeWidth = 1; | |
| 240 static const int kVirtualRegisterWidth = 17; | |
| 241 | |
| 242 static const int kPolicyShift = kKindFieldWidth; | |
| 243 static const int kLifetimeShift = kPolicyShift + kPolicyWidth; | |
| 244 static const int kVirtualRegisterShift = kLifetimeShift + kLifetimeWidth; | |
| 245 static const int kFixedIndexShift = | |
| 246 kVirtualRegisterShift + kVirtualRegisterWidth; | |
| 247 | |
| 248 class PolicyField : public BitField<Policy, kPolicyShift, kPolicyWidth> { }; | |
| 249 | |
| 250 class LifetimeField | |
| 251 : public BitField<Lifetime, kLifetimeShift, kLifetimeWidth> { | |
| 252 }; | |
| 253 | |
| 254 class VirtualRegisterField | |
| 255 : public BitField<unsigned, | |
| 256 kVirtualRegisterShift, | |
| 257 kVirtualRegisterWidth> { | |
| 258 }; | |
| 259 | |
| 260 static const int kMaxVirtualRegisters = 1 << (kVirtualRegisterWidth + 1); | |
| 261 static const int kMaxFixedIndices = 128; | |
| 262 | |
| 263 bool HasIgnorePolicy() const { return policy() == IGNORE; } | |
| 264 bool HasNoPolicy() const { return policy() == NONE; } | |
| 265 bool HasAnyPolicy() const { | |
| 266 return policy() == ANY; | |
| 267 } | |
| 268 bool HasFixedPolicy() const { | |
| 269 return policy() == FIXED_REGISTER || | |
| 270 policy() == FIXED_DOUBLE_REGISTER || | |
| 271 policy() == FIXED_SLOT; | |
| 272 } | |
| 273 bool HasRegisterPolicy() const { | |
| 274 return policy() == WRITABLE_REGISTER || policy() == MUST_HAVE_REGISTER; | |
| 275 } | |
| 276 bool HasSameAsInputPolicy() const { | |
| 277 return policy() == SAME_AS_FIRST_INPUT; | |
| 278 } | |
| 279 Policy policy() const { return PolicyField::decode(value_); } | |
| 280 void set_policy(Policy policy) { | |
| 281 value_ &= ~PolicyField::mask(); | |
| 282 value_ |= PolicyField::encode(policy); | |
| 283 } | |
| 284 int fixed_index() const { | |
| 285 return static_cast<int>(value_) >> kFixedIndexShift; | |
| 286 } | |
| 287 | |
| 288 unsigned virtual_register() const { | |
| 289 return VirtualRegisterField::decode(value_); | |
| 290 } | |
| 291 | |
| 292 void set_virtual_register(unsigned id) { | |
| 293 value_ &= ~VirtualRegisterField::mask(); | |
| 294 value_ |= VirtualRegisterField::encode(id); | |
| 295 } | |
| 296 | |
| 297 LUnallocated* CopyUnconstrained() { | |
| 298 LUnallocated* result = new LUnallocated(ANY); | |
| 299 result->set_virtual_register(virtual_register()); | |
| 300 return result; | |
| 301 } | |
| 302 | |
| 303 static LUnallocated* cast(LOperand* op) { | |
| 304 ASSERT(op->IsUnallocated()); | |
| 305 return reinterpret_cast<LUnallocated*>(op); | |
| 306 } | |
| 307 | |
| 308 bool IsUsedAtStart() { | |
| 309 return LifetimeField::decode(value_) == USED_AT_START; | |
| 310 } | |
| 311 | |
| 312 private: | |
| 313 void Initialize(Policy policy, int fixed_index, Lifetime lifetime) { | |
| 314 value_ |= PolicyField::encode(policy); | |
| 315 value_ |= LifetimeField::encode(lifetime); | |
| 316 value_ |= fixed_index << kFixedIndexShift; | |
| 317 ASSERT(this->fixed_index() == fixed_index); | |
| 318 } | |
| 319 }; | |
| 320 | |
| 321 | |
| 322 class LMoveOperands BASE_EMBEDDED { | |
| 323 public: | |
| 324 LMoveOperands(LOperand* source, LOperand* destination) | |
| 325 : source_(source), destination_(destination) { | |
| 326 } | |
| 327 | |
| 328 LOperand* source() const { return source_; } | |
| 329 void set_source(LOperand* operand) { source_ = operand; } | |
| 330 | |
| 331 LOperand* destination() const { return destination_; } | |
| 332 void set_destination(LOperand* operand) { destination_ = operand; } | |
| 333 | |
| 334 // The gap resolver marks moves as "in-progress" by clearing the | |
| 335 // destination (but not the source). | |
| 336 bool IsPending() const { | |
| 337 return destination_ == NULL && source_ != NULL; | |
| 338 } | |
| 339 | |
| 340 // True if this move a move into the given destination operand. | |
| 341 bool Blocks(LOperand* operand) const { | |
| 342 return !IsEliminated() && source()->Equals(operand); | |
| 343 } | |
| 344 | |
| 345 // A move is redundant if it's been eliminated, if its source and | |
| 346 // destination are the same, or if its destination is unneeded. | |
| 347 bool IsRedundant() const { | |
| 348 return IsEliminated() || source_->Equals(destination_) || IsIgnored(); | |
| 349 } | |
| 350 | |
| 351 bool IsIgnored() const { | |
| 352 return destination_ != NULL && | |
| 353 destination_->IsUnallocated() && | |
| 354 LUnallocated::cast(destination_)->HasIgnorePolicy(); | |
| 355 } | |
| 356 | |
| 357 // We clear both operands to indicate move that's been eliminated. | |
| 358 void Eliminate() { source_ = destination_ = NULL; } | |
| 359 bool IsEliminated() const { | |
| 360 ASSERT(source_ != NULL || destination_ == NULL); | |
| 361 return source_ == NULL; | |
| 362 } | |
| 363 | |
| 364 private: | |
| 365 LOperand* source_; | |
| 366 LOperand* destination_; | |
| 367 }; | |
| 368 | |
| 369 | |
| 370 class LConstantOperand: public LOperand { | |
| 371 public: | |
| 372 static LConstantOperand* Create(int index) { | |
| 373 ASSERT(index >= 0); | |
| 374 if (index < kNumCachedOperands) return &cache[index]; | |
| 375 return new LConstantOperand(index); | |
| 376 } | |
| 377 | |
| 378 static LConstantOperand* cast(LOperand* op) { | |
| 379 ASSERT(op->IsConstantOperand()); | |
| 380 return reinterpret_cast<LConstantOperand*>(op); | |
| 381 } | |
| 382 | |
| 383 static void SetupCache(); | |
| 384 | |
| 385 private: | |
| 386 static const int kNumCachedOperands = 128; | |
| 387 static LConstantOperand cache[]; | |
| 388 | |
| 389 LConstantOperand() : LOperand() { } | |
| 390 explicit LConstantOperand(int index) : LOperand(CONSTANT_OPERAND, index) { } | |
| 391 }; | |
| 392 | |
| 393 | |
| 394 class LArgument: public LOperand { | |
| 395 public: | |
| 396 explicit LArgument(int index) : LOperand(ARGUMENT, index) { } | |
| 397 | |
| 398 static LArgument* cast(LOperand* op) { | |
| 399 ASSERT(op->IsArgument()); | |
| 400 return reinterpret_cast<LArgument*>(op); | |
| 401 } | |
| 402 }; | |
| 403 | |
| 404 | |
| 405 class LStackSlot: public LOperand { | |
| 406 public: | |
| 407 static LStackSlot* Create(int index) { | |
| 408 ASSERT(index >= 0); | |
| 409 if (index < kNumCachedOperands) return &cache[index]; | |
| 410 return new LStackSlot(index); | |
| 411 } | |
| 412 | |
| 413 static LStackSlot* cast(LOperand* op) { | |
| 414 ASSERT(op->IsStackSlot()); | |
| 415 return reinterpret_cast<LStackSlot*>(op); | |
| 416 } | |
| 417 | |
| 418 static void SetupCache(); | |
| 419 | |
| 420 private: | |
| 421 static const int kNumCachedOperands = 128; | |
| 422 static LStackSlot cache[]; | |
| 423 | |
| 424 LStackSlot() : LOperand() { } | |
| 425 explicit LStackSlot(int index) : LOperand(STACK_SLOT, index) { } | |
| 426 }; | |
| 427 | |
| 428 | |
| 429 class LDoubleStackSlot: public LOperand { | |
| 430 public: | |
| 431 static LDoubleStackSlot* Create(int index) { | |
| 432 ASSERT(index >= 0); | |
| 433 if (index < kNumCachedOperands) return &cache[index]; | |
| 434 return new LDoubleStackSlot(index); | |
| 435 } | |
| 436 | |
| 437 static LDoubleStackSlot* cast(LOperand* op) { | |
| 438 ASSERT(op->IsStackSlot()); | |
| 439 return reinterpret_cast<LDoubleStackSlot*>(op); | |
| 440 } | |
| 441 | |
| 442 static void SetupCache(); | |
| 443 | |
| 444 private: | |
| 445 static const int kNumCachedOperands = 128; | |
| 446 static LDoubleStackSlot cache[]; | |
| 447 | |
| 448 LDoubleStackSlot() : LOperand() { } | |
| 449 explicit LDoubleStackSlot(int index) : LOperand(DOUBLE_STACK_SLOT, index) { } | |
| 450 }; | |
| 451 | |
| 452 | |
| 453 class LRegister: public LOperand { | |
| 454 public: | |
| 455 static LRegister* Create(int index) { | |
| 456 ASSERT(index >= 0); | |
| 457 if (index < kNumCachedOperands) return &cache[index]; | |
| 458 return new LRegister(index); | |
| 459 } | |
| 460 | |
| 461 static LRegister* cast(LOperand* op) { | |
| 462 ASSERT(op->IsRegister()); | |
| 463 return reinterpret_cast<LRegister*>(op); | |
| 464 } | |
| 465 | |
| 466 static void SetupCache(); | |
| 467 | |
| 468 private: | |
| 469 static const int kNumCachedOperands = 16; | |
| 470 static LRegister cache[]; | |
| 471 | |
| 472 LRegister() : LOperand() { } | |
| 473 explicit LRegister(int index) : LOperand(REGISTER, index) { } | |
| 474 }; | |
| 475 | |
| 476 | |
| 477 class LDoubleRegister: public LOperand { | |
| 478 public: | |
| 479 static LDoubleRegister* Create(int index) { | |
| 480 ASSERT(index >= 0); | |
| 481 if (index < kNumCachedOperands) return &cache[index]; | |
| 482 return new LDoubleRegister(index); | |
| 483 } | |
| 484 | |
| 485 static LDoubleRegister* cast(LOperand* op) { | |
| 486 ASSERT(op->IsDoubleRegister()); | |
| 487 return reinterpret_cast<LDoubleRegister*>(op); | |
| 488 } | |
| 489 | |
| 490 static void SetupCache(); | |
| 491 | |
| 492 private: | |
| 493 static const int kNumCachedOperands = 16; | |
| 494 static LDoubleRegister cache[]; | |
| 495 | |
| 496 LDoubleRegister() : LOperand() { } | |
| 497 explicit LDoubleRegister(int index) : LOperand(DOUBLE_REGISTER, index) { } | |
| 498 }; | |
| 499 | |
| 500 | |
| 501 // A register-allocator view of a Lithium instruction. It contains the id of | 154 // A register-allocator view of a Lithium instruction. It contains the id of |
| 502 // the output operand and a list of input operand uses. | 155 // the output operand and a list of input operand uses. |
| 503 class InstructionSummary: public ZoneObject { | 156 class InstructionSummary: public ZoneObject { |
| 504 public: | 157 public: |
| 505 InstructionSummary() | 158 InstructionSummary() |
| 506 : output_operand_(NULL), | 159 : output_operand_(NULL), |
| 507 input_count_(0), | 160 input_count_(0), |
| 508 operands_(4), | 161 operands_(4), |
| 509 is_call_(false), | 162 is_call_(false), |
| 510 is_save_doubles_(false) {} | 163 is_save_doubles_(false) {} |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 LifetimePosition start_; | 234 LifetimePosition start_; |
| 582 LifetimePosition end_; | 235 LifetimePosition end_; |
| 583 UseInterval* next_; | 236 UseInterval* next_; |
| 584 | 237 |
| 585 friend class LiveRange; // Assigns to start_. | 238 friend class LiveRange; // Assigns to start_. |
| 586 }; | 239 }; |
| 587 | 240 |
| 588 // Representation of a use position. | 241 // Representation of a use position. |
| 589 class UsePosition: public ZoneObject { | 242 class UsePosition: public ZoneObject { |
| 590 public: | 243 public: |
| 591 UsePosition(LifetimePosition pos, LOperand* operand) | 244 UsePosition(LifetimePosition pos, LOperand* operand); |
| 592 : operand_(operand), | |
| 593 hint_(NULL), | |
| 594 pos_(pos), | |
| 595 next_(NULL), | |
| 596 requires_reg_(false), | |
| 597 register_beneficial_(true) { | |
| 598 if (operand_ != NULL && operand_->IsUnallocated()) { | |
| 599 LUnallocated* unalloc = LUnallocated::cast(operand_); | |
| 600 requires_reg_ = unalloc->HasRegisterPolicy(); | |
| 601 register_beneficial_ = !unalloc->HasAnyPolicy(); | |
| 602 } | |
| 603 ASSERT(pos_.IsValid()); | |
| 604 } | |
| 605 | 245 |
| 606 LOperand* operand() const { return operand_; } | 246 LOperand* operand() const { return operand_; } |
| 607 bool HasOperand() const { return operand_ != NULL; } | 247 bool HasOperand() const { return operand_ != NULL; } |
| 608 | 248 |
| 609 LOperand* hint() const { return hint_; } | 249 LOperand* hint() const { return hint_; } |
| 610 void set_hint(LOperand* hint) { hint_ = hint; } | 250 void set_hint(LOperand* hint) { hint_ = hint; } |
| 611 bool HasHint() const { return hint_ != NULL && !hint_->IsUnallocated(); } | 251 bool HasHint() const; |
| 612 bool RequiresRegister() const; | 252 bool RequiresRegister() const; |
| 613 bool RegisterIsBeneficial() const; | 253 bool RegisterIsBeneficial() const; |
| 614 | 254 |
| 615 LifetimePosition pos() const { return pos_; } | 255 LifetimePosition pos() const { return pos_; } |
| 616 UsePosition* next() const { return next_; } | 256 UsePosition* next() const { return next_; } |
| 617 | 257 |
| 618 private: | 258 private: |
| 619 void set_next(UsePosition* next) { next_ = next; } | 259 void set_next(UsePosition* next) { next_ = next; } |
| 620 | 260 |
| 621 LOperand* operand_; | 261 LOperand* operand_; |
| 622 LOperand* hint_; | 262 LOperand* hint_; |
| 623 LifetimePosition pos_; | 263 LifetimePosition pos_; |
| 624 UsePosition* next_; | 264 UsePosition* next_; |
| 625 bool requires_reg_; | 265 bool requires_reg_; |
| 626 bool register_beneficial_; | 266 bool register_beneficial_; |
| 627 | 267 |
| 628 friend class LiveRange; | 268 friend class LiveRange; |
| 629 }; | 269 }; |
| 630 | 270 |
| 631 // Representation of SSA values' live ranges as a collection of (continuous) | 271 // Representation of SSA values' live ranges as a collection of (continuous) |
| 632 // intervals over the instruction ordering. | 272 // intervals over the instruction ordering. |
| 633 class LiveRange: public ZoneObject { | 273 class LiveRange: public ZoneObject { |
| 634 public: | 274 public: |
| 635 static const int kInvalidAssignment = 0x7fffffff; | 275 static const int kInvalidAssignment = 0x7fffffff; |
| 636 | 276 |
| 637 explicit LiveRange(int id) | 277 explicit LiveRange(int id); |
| 638 : id_(id), | |
| 639 spilled_(false), | |
| 640 assigned_register_(kInvalidAssignment), | |
| 641 assigned_register_kind_(NONE), | |
| 642 last_interval_(NULL), | |
| 643 first_interval_(NULL), | |
| 644 first_pos_(NULL), | |
| 645 parent_(NULL), | |
| 646 next_(NULL), | |
| 647 current_interval_(NULL), | |
| 648 last_processed_use_(NULL), | |
| 649 spill_start_index_(kMaxInt) { | |
| 650 spill_operand_ = new LUnallocated(LUnallocated::IGNORE); | |
| 651 } | |
| 652 | 278 |
| 653 UseInterval* first_interval() const { return first_interval_; } | 279 UseInterval* first_interval() const { return first_interval_; } |
| 654 UsePosition* first_pos() const { return first_pos_; } | 280 UsePosition* first_pos() const { return first_pos_; } |
| 655 LiveRange* parent() const { return parent_; } | 281 LiveRange* parent() const { return parent_; } |
| 656 LiveRange* TopLevel() { return (parent_ == NULL) ? this : parent_; } | 282 LiveRange* TopLevel() { return (parent_ == NULL) ? this : parent_; } |
| 657 LiveRange* next() const { return next_; } | 283 LiveRange* next() const { return next_; } |
| 658 bool IsChild() const { return parent() != NULL; } | 284 bool IsChild() const { return parent() != NULL; } |
| 659 bool IsParent() const { return parent() == NULL; } | 285 bool IsParent() const { return parent() == NULL; } |
| 660 int id() const { return id_; } | 286 int id() const { return id_; } |
| 661 bool IsFixed() const { return id_ < 0; } | 287 bool IsFixed() const { return id_ < 0; } |
| 662 bool IsEmpty() const { return first_interval() == NULL; } | 288 bool IsEmpty() const { return first_interval() == NULL; } |
| 663 LOperand* CreateAssignedOperand(); | 289 LOperand* CreateAssignedOperand(); |
| 664 int assigned_register() const { return assigned_register_; } | 290 int assigned_register() const { return assigned_register_; } |
| 665 int spill_start_index() const { return spill_start_index_; } | 291 int spill_start_index() const { return spill_start_index_; } |
| 666 void set_assigned_register(int reg, RegisterKind register_kind) { | 292 void set_assigned_register(int reg, RegisterKind register_kind); |
| 667 ASSERT(!HasRegisterAssigned() && !IsSpilled()); | 293 void MakeSpilled(); |
| 668 assigned_register_ = reg; | |
| 669 assigned_register_kind_ = register_kind; | |
| 670 ConvertOperands(); | |
| 671 } | |
| 672 void MakeSpilled() { | |
| 673 ASSERT(!IsSpilled()); | |
| 674 ASSERT(TopLevel()->HasAllocatedSpillOperand()); | |
| 675 spilled_ = true; | |
| 676 assigned_register_ = kInvalidAssignment; | |
| 677 ConvertOperands(); | |
| 678 } | |
| 679 | 294 |
| 680 // Returns use position in this live range that follows both start | 295 // Returns use position in this live range that follows both start |
| 681 // and last processed use position. | 296 // and last processed use position. |
| 682 // Modifies internal state of live range! | 297 // Modifies internal state of live range! |
| 683 UsePosition* NextUsePosition(LifetimePosition start); | 298 UsePosition* NextUsePosition(LifetimePosition start); |
| 684 | 299 |
| 685 // Returns use position for which register is required in this live | 300 // Returns use position for which register is required in this live |
| 686 // range and which follows both start and last processed use position | 301 // range and which follows both start and last processed use position |
| 687 // Modifies internal state of live range! | 302 // Modifies internal state of live range! |
| 688 UsePosition* NextRegisterPosition(LifetimePosition start); | 303 UsePosition* NextRegisterPosition(LifetimePosition start); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 717 LifetimePosition Start() const { | 332 LifetimePosition Start() const { |
| 718 ASSERT(!IsEmpty()); | 333 ASSERT(!IsEmpty()); |
| 719 return first_interval()->start(); | 334 return first_interval()->start(); |
| 720 } | 335 } |
| 721 | 336 |
| 722 LifetimePosition End() const { | 337 LifetimePosition End() const { |
| 723 ASSERT(!IsEmpty()); | 338 ASSERT(!IsEmpty()); |
| 724 return last_interval_->end(); | 339 return last_interval_->end(); |
| 725 } | 340 } |
| 726 | 341 |
| 727 bool HasAllocatedSpillOperand() const { | 342 bool HasAllocatedSpillOperand() const; |
| 728 return spill_operand_ != NULL && !spill_operand_->IsUnallocated(); | |
| 729 } | |
| 730 | |
| 731 LOperand* GetSpillOperand() const { return spill_operand_; } | 343 LOperand* GetSpillOperand() const { return spill_operand_; } |
| 732 void SetSpillOperand(LOperand* operand) { | 344 void SetSpillOperand(LOperand* operand); |
| 733 ASSERT(!operand->IsUnallocated()); | |
| 734 ASSERT(spill_operand_ != NULL); | |
| 735 ASSERT(spill_operand_->IsUnallocated()); | |
| 736 spill_operand_->ConvertTo(operand->kind(), operand->index()); | |
| 737 } | |
| 738 | 345 |
| 739 void SetSpillStartIndex(int start) { | 346 void SetSpillStartIndex(int start) { |
| 740 spill_start_index_ = Min(start, spill_start_index_); | 347 spill_start_index_ = Min(start, spill_start_index_); |
| 741 } | 348 } |
| 742 | 349 |
| 743 bool ShouldBeAllocatedBefore(const LiveRange* other) const; | 350 bool ShouldBeAllocatedBefore(const LiveRange* other) const; |
| 744 bool CanCover(LifetimePosition position) const; | 351 bool CanCover(LifetimePosition position) const; |
| 745 bool Covers(LifetimePosition position); | 352 bool Covers(LifetimePosition position); |
| 746 LifetimePosition FirstIntersection(LiveRange* other); | 353 LifetimePosition FirstIntersection(LiveRange* other); |
| 747 | 354 |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1049 | 656 |
| 1050 bool has_osr_entry_; | 657 bool has_osr_entry_; |
| 1051 | 658 |
| 1052 DISALLOW_COPY_AND_ASSIGN(LAllocator); | 659 DISALLOW_COPY_AND_ASSIGN(LAllocator); |
| 1053 }; | 660 }; |
| 1054 | 661 |
| 1055 | 662 |
| 1056 } } // namespace v8::internal | 663 } } // namespace v8::internal |
| 1057 | 664 |
| 1058 #endif // V8_LITHIUM_ALLOCATOR_H_ | 665 #endif // V8_LITHIUM_ALLOCATOR_H_ |
| OLD | NEW |