| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_COMPILER_INSTRUCTION_H_ | 5 #ifndef V8_COMPILER_INSTRUCTION_H_ |
| 6 #define V8_COMPILER_INSTRUCTION_H_ | 6 #define V8_COMPILER_INSTRUCTION_H_ |
| 7 | 7 |
| 8 #include <deque> | 8 #include <deque> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <set> | 10 #include <set> |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 bool Is##name() const { return kind() == type; } | 66 bool Is##name() const { return kind() == type; } |
| 67 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) | 67 INSTRUCTION_OPERAND_LIST(INSTRUCTION_OPERAND_PREDICATE) |
| 68 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED, 0) | 68 INSTRUCTION_OPERAND_PREDICATE(Unallocated, UNALLOCATED, 0) |
| 69 INSTRUCTION_OPERAND_PREDICATE(Ignored, INVALID, 0) | 69 INSTRUCTION_OPERAND_PREDICATE(Ignored, INVALID, 0) |
| 70 #undef INSTRUCTION_OPERAND_PREDICATE | 70 #undef INSTRUCTION_OPERAND_PREDICATE |
| 71 bool Equals(InstructionOperand* other) const { | 71 bool Equals(InstructionOperand* other) const { |
| 72 return value_ == other->value_; | 72 return value_ == other->value_; |
| 73 } | 73 } |
| 74 | 74 |
| 75 void ConvertTo(Kind kind, int index) { | 75 void ConvertTo(Kind kind, int index) { |
| 76 if (kind == REGISTER || kind == DOUBLE_REGISTER) ASSERT(index >= 0); | 76 if (kind == REGISTER || kind == DOUBLE_REGISTER) DCHECK(index >= 0); |
| 77 value_ = KindField::encode(kind); | 77 value_ = KindField::encode(kind); |
| 78 value_ |= index << KindField::kSize; | 78 value_ |= index << KindField::kSize; |
| 79 ASSERT(this->index() == index); | 79 DCHECK(this->index() == index); |
| 80 } | 80 } |
| 81 | 81 |
| 82 // Calls SetUpCache()/TearDownCache() for each subclass. | 82 // Calls SetUpCache()/TearDownCache() for each subclass. |
| 83 static void SetUpCaches(); | 83 static void SetUpCaches(); |
| 84 static void TearDownCaches(); | 84 static void TearDownCaches(); |
| 85 | 85 |
| 86 protected: | 86 protected: |
| 87 typedef BitField<Kind, 0, 3> KindField; | 87 typedef BitField<Kind, 0, 3> KindField; |
| 88 | 88 |
| 89 unsigned value_; | 89 unsigned value_; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 120 | 120 |
| 121 explicit UnallocatedOperand(ExtendedPolicy policy) | 121 explicit UnallocatedOperand(ExtendedPolicy policy) |
| 122 : InstructionOperand(UNALLOCATED, 0) { | 122 : InstructionOperand(UNALLOCATED, 0) { |
| 123 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); | 123 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); |
| 124 value_ |= ExtendedPolicyField::encode(policy); | 124 value_ |= ExtendedPolicyField::encode(policy); |
| 125 value_ |= LifetimeField::encode(USED_AT_END); | 125 value_ |= LifetimeField::encode(USED_AT_END); |
| 126 } | 126 } |
| 127 | 127 |
| 128 UnallocatedOperand(BasicPolicy policy, int index) | 128 UnallocatedOperand(BasicPolicy policy, int index) |
| 129 : InstructionOperand(UNALLOCATED, 0) { | 129 : InstructionOperand(UNALLOCATED, 0) { |
| 130 ASSERT(policy == FIXED_SLOT); | 130 DCHECK(policy == FIXED_SLOT); |
| 131 value_ |= BasicPolicyField::encode(policy); | 131 value_ |= BasicPolicyField::encode(policy); |
| 132 value_ |= index << FixedSlotIndexField::kShift; | 132 value_ |= index << FixedSlotIndexField::kShift; |
| 133 ASSERT(this->fixed_slot_index() == index); | 133 DCHECK(this->fixed_slot_index() == index); |
| 134 } | 134 } |
| 135 | 135 |
| 136 UnallocatedOperand(ExtendedPolicy policy, int index) | 136 UnallocatedOperand(ExtendedPolicy policy, int index) |
| 137 : InstructionOperand(UNALLOCATED, 0) { | 137 : InstructionOperand(UNALLOCATED, 0) { |
| 138 ASSERT(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER); | 138 DCHECK(policy == FIXED_REGISTER || policy == FIXED_DOUBLE_REGISTER); |
| 139 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); | 139 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); |
| 140 value_ |= ExtendedPolicyField::encode(policy); | 140 value_ |= ExtendedPolicyField::encode(policy); |
| 141 value_ |= LifetimeField::encode(USED_AT_END); | 141 value_ |= LifetimeField::encode(USED_AT_END); |
| 142 value_ |= FixedRegisterField::encode(index); | 142 value_ |= FixedRegisterField::encode(index); |
| 143 } | 143 } |
| 144 | 144 |
| 145 UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime) | 145 UnallocatedOperand(ExtendedPolicy policy, Lifetime lifetime) |
| 146 : InstructionOperand(UNALLOCATED, 0) { | 146 : InstructionOperand(UNALLOCATED, 0) { |
| 147 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); | 147 value_ |= BasicPolicyField::encode(EXTENDED_POLICY); |
| 148 value_ |= ExtendedPolicyField::encode(policy); | 148 value_ |= ExtendedPolicyField::encode(policy); |
| 149 value_ |= LifetimeField::encode(lifetime); | 149 value_ |= LifetimeField::encode(lifetime); |
| 150 } | 150 } |
| 151 | 151 |
| 152 UnallocatedOperand* CopyUnconstrained(Zone* zone) { | 152 UnallocatedOperand* CopyUnconstrained(Zone* zone) { |
| 153 UnallocatedOperand* result = new (zone) UnallocatedOperand(ANY); | 153 UnallocatedOperand* result = new (zone) UnallocatedOperand(ANY); |
| 154 result->set_virtual_register(virtual_register()); | 154 result->set_virtual_register(virtual_register()); |
| 155 return result; | 155 return result; |
| 156 } | 156 } |
| 157 | 157 |
| 158 static const UnallocatedOperand* cast(const InstructionOperand* op) { | 158 static const UnallocatedOperand* cast(const InstructionOperand* op) { |
| 159 ASSERT(op->IsUnallocated()); | 159 DCHECK(op->IsUnallocated()); |
| 160 return static_cast<const UnallocatedOperand*>(op); | 160 return static_cast<const UnallocatedOperand*>(op); |
| 161 } | 161 } |
| 162 | 162 |
| 163 static UnallocatedOperand* cast(InstructionOperand* op) { | 163 static UnallocatedOperand* cast(InstructionOperand* op) { |
| 164 ASSERT(op->IsUnallocated()); | 164 DCHECK(op->IsUnallocated()); |
| 165 return static_cast<UnallocatedOperand*>(op); | 165 return static_cast<UnallocatedOperand*>(op); |
| 166 } | 166 } |
| 167 | 167 |
| 168 // The encoding used for UnallocatedOperand operands depends on the policy | 168 // The encoding used for UnallocatedOperand operands depends on the policy |
| 169 // that is | 169 // that is |
| 170 // stored within the operand. The FIXED_SLOT policy uses a compact encoding | 170 // stored within the operand. The FIXED_SLOT policy uses a compact encoding |
| 171 // because it accommodates a larger pay-load. | 171 // because it accommodates a larger pay-load. |
| 172 // | 172 // |
| 173 // For FIXED_SLOT policy: | 173 // For FIXED_SLOT policy: |
| 174 // +------------------------------------------+ | 174 // +------------------------------------------+ |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 228 bool HasFixedDoubleRegisterPolicy() const { | 228 bool HasFixedDoubleRegisterPolicy() const { |
| 229 return basic_policy() == EXTENDED_POLICY && | 229 return basic_policy() == EXTENDED_POLICY && |
| 230 extended_policy() == FIXED_DOUBLE_REGISTER; | 230 extended_policy() == FIXED_DOUBLE_REGISTER; |
| 231 } | 231 } |
| 232 | 232 |
| 233 // [basic_policy]: Distinguish between FIXED_SLOT and all other policies. | 233 // [basic_policy]: Distinguish between FIXED_SLOT and all other policies. |
| 234 BasicPolicy basic_policy() const { return BasicPolicyField::decode(value_); } | 234 BasicPolicy basic_policy() const { return BasicPolicyField::decode(value_); } |
| 235 | 235 |
| 236 // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy. | 236 // [extended_policy]: Only for non-FIXED_SLOT. The finer-grained policy. |
| 237 ExtendedPolicy extended_policy() const { | 237 ExtendedPolicy extended_policy() const { |
| 238 ASSERT(basic_policy() == EXTENDED_POLICY); | 238 DCHECK(basic_policy() == EXTENDED_POLICY); |
| 239 return ExtendedPolicyField::decode(value_); | 239 return ExtendedPolicyField::decode(value_); |
| 240 } | 240 } |
| 241 | 241 |
| 242 // [fixed_slot_index]: Only for FIXED_SLOT. | 242 // [fixed_slot_index]: Only for FIXED_SLOT. |
| 243 int fixed_slot_index() const { | 243 int fixed_slot_index() const { |
| 244 ASSERT(HasFixedSlotPolicy()); | 244 DCHECK(HasFixedSlotPolicy()); |
| 245 return static_cast<int>(value_) >> FixedSlotIndexField::kShift; | 245 return static_cast<int>(value_) >> FixedSlotIndexField::kShift; |
| 246 } | 246 } |
| 247 | 247 |
| 248 // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER. | 248 // [fixed_register_index]: Only for FIXED_REGISTER or FIXED_DOUBLE_REGISTER. |
| 249 int fixed_register_index() const { | 249 int fixed_register_index() const { |
| 250 ASSERT(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy()); | 250 DCHECK(HasFixedRegisterPolicy() || HasFixedDoubleRegisterPolicy()); |
| 251 return FixedRegisterField::decode(value_); | 251 return FixedRegisterField::decode(value_); |
| 252 } | 252 } |
| 253 | 253 |
| 254 // [virtual_register]: The virtual register ID for this operand. | 254 // [virtual_register]: The virtual register ID for this operand. |
| 255 int virtual_register() const { return VirtualRegisterField::decode(value_); } | 255 int virtual_register() const { return VirtualRegisterField::decode(value_); } |
| 256 void set_virtual_register(unsigned id) { | 256 void set_virtual_register(unsigned id) { |
| 257 value_ = VirtualRegisterField::update(value_, id); | 257 value_ = VirtualRegisterField::update(value_, id); |
| 258 } | 258 } |
| 259 | 259 |
| 260 // [lifetime]: Only for non-FIXED_SLOT. | 260 // [lifetime]: Only for non-FIXED_SLOT. |
| 261 bool IsUsedAtStart() { | 261 bool IsUsedAtStart() { |
| 262 ASSERT(basic_policy() == EXTENDED_POLICY); | 262 DCHECK(basic_policy() == EXTENDED_POLICY); |
| 263 return LifetimeField::decode(value_) == USED_AT_START; | 263 return LifetimeField::decode(value_) == USED_AT_START; |
| 264 } | 264 } |
| 265 }; | 265 }; |
| 266 | 266 |
| 267 | 267 |
| 268 class MoveOperands V8_FINAL { | 268 class MoveOperands V8_FINAL { |
| 269 public: | 269 public: |
| 270 MoveOperands(InstructionOperand* source, InstructionOperand* destination) | 270 MoveOperands(InstructionOperand* source, InstructionOperand* destination) |
| 271 : source_(source), destination_(destination) {} | 271 : source_(source), destination_(destination) {} |
| 272 | 272 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 292 (destination_ != NULL && destination_->IsConstant()); | 292 (destination_ != NULL && destination_->IsConstant()); |
| 293 } | 293 } |
| 294 | 294 |
| 295 bool IsIgnored() const { | 295 bool IsIgnored() const { |
| 296 return destination_ != NULL && destination_->IsIgnored(); | 296 return destination_ != NULL && destination_->IsIgnored(); |
| 297 } | 297 } |
| 298 | 298 |
| 299 // We clear both operands to indicate move that's been eliminated. | 299 // We clear both operands to indicate move that's been eliminated. |
| 300 void Eliminate() { source_ = destination_ = NULL; } | 300 void Eliminate() { source_ = destination_ = NULL; } |
| 301 bool IsEliminated() const { | 301 bool IsEliminated() const { |
| 302 ASSERT(source_ != NULL || destination_ == NULL); | 302 DCHECK(source_ != NULL || destination_ == NULL); |
| 303 return source_ == NULL; | 303 return source_ == NULL; |
| 304 } | 304 } |
| 305 | 305 |
| 306 private: | 306 private: |
| 307 InstructionOperand* source_; | 307 InstructionOperand* source_; |
| 308 InstructionOperand* destination_; | 308 InstructionOperand* destination_; |
| 309 }; | 309 }; |
| 310 | 310 |
| 311 OStream& operator<<(OStream& os, const MoveOperands& mo); | 311 OStream& operator<<(OStream& os, const MoveOperands& mo); |
| 312 | 312 |
| 313 template <InstructionOperand::Kind kOperandKind, int kNumCachedOperands> | 313 template <InstructionOperand::Kind kOperandKind, int kNumCachedOperands> |
| 314 class SubKindOperand V8_FINAL : public InstructionOperand { | 314 class SubKindOperand V8_FINAL : public InstructionOperand { |
| 315 public: | 315 public: |
| 316 static SubKindOperand* Create(int index, Zone* zone) { | 316 static SubKindOperand* Create(int index, Zone* zone) { |
| 317 ASSERT(index >= 0); | 317 DCHECK(index >= 0); |
| 318 if (index < kNumCachedOperands) return &cache[index]; | 318 if (index < kNumCachedOperands) return &cache[index]; |
| 319 return new (zone) SubKindOperand(index); | 319 return new (zone) SubKindOperand(index); |
| 320 } | 320 } |
| 321 | 321 |
| 322 static SubKindOperand* cast(InstructionOperand* op) { | 322 static SubKindOperand* cast(InstructionOperand* op) { |
| 323 ASSERT(op->kind() == kOperandKind); | 323 DCHECK(op->kind() == kOperandKind); |
| 324 return reinterpret_cast<SubKindOperand*>(op); | 324 return reinterpret_cast<SubKindOperand*>(op); |
| 325 } | 325 } |
| 326 | 326 |
| 327 static void SetUpCache(); | 327 static void SetUpCache(); |
| 328 static void TearDownCache(); | 328 static void TearDownCache(); |
| 329 | 329 |
| 330 private: | 330 private: |
| 331 static SubKindOperand* cache; | 331 static SubKindOperand* cache; |
| 332 | 332 |
| 333 SubKindOperand() : InstructionOperand() {} | 333 SubKindOperand() : InstructionOperand() {} |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 const ZoneList<InstructionOperand*>* GetNormalizedOperands() { | 373 const ZoneList<InstructionOperand*>* GetNormalizedOperands() { |
| 374 for (int i = 0; i < untagged_operands_.length(); ++i) { | 374 for (int i = 0; i < untagged_operands_.length(); ++i) { |
| 375 RemovePointer(untagged_operands_[i]); | 375 RemovePointer(untagged_operands_[i]); |
| 376 } | 376 } |
| 377 untagged_operands_.Clear(); | 377 untagged_operands_.Clear(); |
| 378 return &pointer_operands_; | 378 return &pointer_operands_; |
| 379 } | 379 } |
| 380 int instruction_position() const { return instruction_position_; } | 380 int instruction_position() const { return instruction_position_; } |
| 381 | 381 |
| 382 void set_instruction_position(int pos) { | 382 void set_instruction_position(int pos) { |
| 383 ASSERT(instruction_position_ == -1); | 383 DCHECK(instruction_position_ == -1); |
| 384 instruction_position_ = pos; | 384 instruction_position_ = pos; |
| 385 } | 385 } |
| 386 | 386 |
| 387 void RecordPointer(InstructionOperand* op, Zone* zone); | 387 void RecordPointer(InstructionOperand* op, Zone* zone); |
| 388 void RemovePointer(InstructionOperand* op); | 388 void RemovePointer(InstructionOperand* op); |
| 389 void RecordUntagged(InstructionOperand* op, Zone* zone); | 389 void RecordUntagged(InstructionOperand* op, Zone* zone); |
| 390 | 390 |
| 391 private: | 391 private: |
| 392 friend OStream& operator<<(OStream& os, const PointerMap& pm); | 392 friend OStream& operator<<(OStream& os, const PointerMap& pm); |
| 393 | 393 |
| 394 ZoneList<InstructionOperand*> pointer_operands_; | 394 ZoneList<InstructionOperand*> pointer_operands_; |
| 395 ZoneList<InstructionOperand*> untagged_operands_; | 395 ZoneList<InstructionOperand*> untagged_operands_; |
| 396 int instruction_position_; | 396 int instruction_position_; |
| 397 }; | 397 }; |
| 398 | 398 |
| 399 OStream& operator<<(OStream& os, const PointerMap& pm); | 399 OStream& operator<<(OStream& os, const PointerMap& pm); |
| 400 | 400 |
| 401 // TODO(titzer): s/PointerMap/ReferenceMap/ | 401 // TODO(titzer): s/PointerMap/ReferenceMap/ |
| 402 class Instruction : public ZoneObject { | 402 class Instruction : public ZoneObject { |
| 403 public: | 403 public: |
| 404 size_t OutputCount() const { return OutputCountField::decode(bit_field_); } | 404 size_t OutputCount() const { return OutputCountField::decode(bit_field_); } |
| 405 InstructionOperand* Output() const { return OutputAt(0); } | 405 InstructionOperand* Output() const { return OutputAt(0); } |
| 406 InstructionOperand* OutputAt(size_t i) const { | 406 InstructionOperand* OutputAt(size_t i) const { |
| 407 ASSERT(i < OutputCount()); | 407 DCHECK(i < OutputCount()); |
| 408 return operands_[i]; | 408 return operands_[i]; |
| 409 } | 409 } |
| 410 | 410 |
| 411 size_t InputCount() const { return InputCountField::decode(bit_field_); } | 411 size_t InputCount() const { return InputCountField::decode(bit_field_); } |
| 412 InstructionOperand* InputAt(size_t i) const { | 412 InstructionOperand* InputAt(size_t i) const { |
| 413 ASSERT(i < InputCount()); | 413 DCHECK(i < InputCount()); |
| 414 return operands_[OutputCount() + i]; | 414 return operands_[OutputCount() + i]; |
| 415 } | 415 } |
| 416 | 416 |
| 417 size_t TempCount() const { return TempCountField::decode(bit_field_); } | 417 size_t TempCount() const { return TempCountField::decode(bit_field_); } |
| 418 InstructionOperand* TempAt(size_t i) const { | 418 InstructionOperand* TempAt(size_t i) const { |
| 419 ASSERT(i < TempCount()); | 419 DCHECK(i < TempCount()); |
| 420 return operands_[OutputCount() + InputCount() + i]; | 420 return operands_[OutputCount() + InputCount() + i]; |
| 421 } | 421 } |
| 422 | 422 |
| 423 InstructionCode opcode() const { return opcode_; } | 423 InstructionCode opcode() const { return opcode_; } |
| 424 ArchOpcode arch_opcode() const { return ArchOpcodeField::decode(opcode()); } | 424 ArchOpcode arch_opcode() const { return ArchOpcodeField::decode(opcode()); } |
| 425 AddressingMode addressing_mode() const { | 425 AddressingMode addressing_mode() const { |
| 426 return AddressingModeField::decode(opcode()); | 426 return AddressingModeField::decode(opcode()); |
| 427 } | 427 } |
| 428 FlagsMode flags_mode() const { return FlagsModeField::decode(opcode()); } | 428 FlagsMode flags_mode() const { return FlagsModeField::decode(opcode()); } |
| 429 FlagsCondition flags_condition() const { | 429 FlagsCondition flags_condition() const { |
| 430 return FlagsConditionField::decode(opcode()); | 430 return FlagsConditionField::decode(opcode()); |
| 431 } | 431 } |
| 432 | 432 |
| 433 // TODO(titzer): make control and call into flags. | 433 // TODO(titzer): make control and call into flags. |
| 434 static Instruction* New(Zone* zone, InstructionCode opcode) { | 434 static Instruction* New(Zone* zone, InstructionCode opcode) { |
| 435 return New(zone, opcode, 0, NULL, 0, NULL, 0, NULL); | 435 return New(zone, opcode, 0, NULL, 0, NULL, 0, NULL); |
| 436 } | 436 } |
| 437 | 437 |
| 438 static Instruction* New(Zone* zone, InstructionCode opcode, | 438 static Instruction* New(Zone* zone, InstructionCode opcode, |
| 439 size_t output_count, InstructionOperand** outputs, | 439 size_t output_count, InstructionOperand** outputs, |
| 440 size_t input_count, InstructionOperand** inputs, | 440 size_t input_count, InstructionOperand** inputs, |
| 441 size_t temp_count, InstructionOperand** temps) { | 441 size_t temp_count, InstructionOperand** temps) { |
| 442 ASSERT(opcode >= 0); | 442 DCHECK(opcode >= 0); |
| 443 ASSERT(output_count == 0 || outputs != NULL); | 443 DCHECK(output_count == 0 || outputs != NULL); |
| 444 ASSERT(input_count == 0 || inputs != NULL); | 444 DCHECK(input_count == 0 || inputs != NULL); |
| 445 ASSERT(temp_count == 0 || temps != NULL); | 445 DCHECK(temp_count == 0 || temps != NULL); |
| 446 InstructionOperand* none = NULL; | 446 InstructionOperand* none = NULL; |
| 447 USE(none); | 447 USE(none); |
| 448 int size = static_cast<int>(RoundUp(sizeof(Instruction), kPointerSize) + | 448 int size = static_cast<int>(RoundUp(sizeof(Instruction), kPointerSize) + |
| 449 (output_count + input_count + temp_count - 1) * | 449 (output_count + input_count + temp_count - 1) * |
| 450 sizeof(none)); | 450 sizeof(none)); |
| 451 return new (zone->New(size)) Instruction( | 451 return new (zone->New(size)) Instruction( |
| 452 opcode, output_count, outputs, input_count, inputs, temp_count, temps); | 452 opcode, output_count, outputs, input_count, inputs, temp_count, temps); |
| 453 } | 453 } |
| 454 | 454 |
| 455 // TODO(titzer): another holdover from lithium days; register allocator | 455 // TODO(titzer): another holdover from lithium days; register allocator |
| (...skipping 18 matching lines...) Expand all Loading... |
| 474 bool IsSourcePosition() const { | 474 bool IsSourcePosition() const { |
| 475 return opcode() == kSourcePositionInstruction; | 475 return opcode() == kSourcePositionInstruction; |
| 476 } | 476 } |
| 477 | 477 |
| 478 bool ClobbersRegisters() const { return IsCall(); } | 478 bool ClobbersRegisters() const { return IsCall(); } |
| 479 bool ClobbersTemps() const { return IsCall(); } | 479 bool ClobbersTemps() const { return IsCall(); } |
| 480 bool ClobbersDoubleRegisters() const { return IsCall(); } | 480 bool ClobbersDoubleRegisters() const { return IsCall(); } |
| 481 PointerMap* pointer_map() const { return pointer_map_; } | 481 PointerMap* pointer_map() const { return pointer_map_; } |
| 482 | 482 |
| 483 void set_pointer_map(PointerMap* map) { | 483 void set_pointer_map(PointerMap* map) { |
| 484 ASSERT(NeedsPointerMap()); | 484 DCHECK(NeedsPointerMap()); |
| 485 ASSERT_EQ(NULL, pointer_map_); | 485 DCHECK_EQ(NULL, pointer_map_); |
| 486 pointer_map_ = map; | 486 pointer_map_ = map; |
| 487 } | 487 } |
| 488 | 488 |
| 489 // Placement new operator so that we can smash instructions into | 489 // Placement new operator so that we can smash instructions into |
| 490 // zone-allocated memory. | 490 // zone-allocated memory. |
| 491 void* operator new(size_t, void* location) { return location; } | 491 void* operator new(size_t, void* location) { return location; } |
| 492 | 492 |
| 493 void operator delete(void* pointer, void* location) { UNREACHABLE(); } | 493 void operator delete(void* pointer, void* location) { UNREACHABLE(); } |
| 494 | 494 |
| 495 protected: | 495 protected: |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 ParallelMove* GetParallelMove(InnerPosition pos) { | 560 ParallelMove* GetParallelMove(InnerPosition pos) { |
| 561 return parallel_moves_[pos]; | 561 return parallel_moves_[pos]; |
| 562 } | 562 } |
| 563 | 563 |
| 564 static GapInstruction* New(Zone* zone) { | 564 static GapInstruction* New(Zone* zone) { |
| 565 void* buffer = zone->New(sizeof(GapInstruction)); | 565 void* buffer = zone->New(sizeof(GapInstruction)); |
| 566 return new (buffer) GapInstruction(kGapInstruction); | 566 return new (buffer) GapInstruction(kGapInstruction); |
| 567 } | 567 } |
| 568 | 568 |
| 569 static GapInstruction* cast(Instruction* instr) { | 569 static GapInstruction* cast(Instruction* instr) { |
| 570 ASSERT(instr->IsGapMoves()); | 570 DCHECK(instr->IsGapMoves()); |
| 571 return static_cast<GapInstruction*>(instr); | 571 return static_cast<GapInstruction*>(instr); |
| 572 } | 572 } |
| 573 | 573 |
| 574 static const GapInstruction* cast(const Instruction* instr) { | 574 static const GapInstruction* cast(const Instruction* instr) { |
| 575 ASSERT(instr->IsGapMoves()); | 575 DCHECK(instr->IsGapMoves()); |
| 576 return static_cast<const GapInstruction*>(instr); | 576 return static_cast<const GapInstruction*>(instr); |
| 577 } | 577 } |
| 578 | 578 |
| 579 protected: | 579 protected: |
| 580 explicit GapInstruction(InstructionCode opcode) : Instruction(opcode) { | 580 explicit GapInstruction(InstructionCode opcode) : Instruction(opcode) { |
| 581 parallel_moves_[BEFORE] = NULL; | 581 parallel_moves_[BEFORE] = NULL; |
| 582 parallel_moves_[START] = NULL; | 582 parallel_moves_[START] = NULL; |
| 583 parallel_moves_[END] = NULL; | 583 parallel_moves_[END] = NULL; |
| 584 parallel_moves_[AFTER] = NULL; | 584 parallel_moves_[AFTER] = NULL; |
| 585 } | 585 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 597 public: | 597 public: |
| 598 BasicBlock* block() const { return block_; } | 598 BasicBlock* block() const { return block_; } |
| 599 Label* label() { return &label_; } | 599 Label* label() { return &label_; } |
| 600 | 600 |
| 601 static BlockStartInstruction* New(Zone* zone, BasicBlock* block) { | 601 static BlockStartInstruction* New(Zone* zone, BasicBlock* block) { |
| 602 void* buffer = zone->New(sizeof(BlockStartInstruction)); | 602 void* buffer = zone->New(sizeof(BlockStartInstruction)); |
| 603 return new (buffer) BlockStartInstruction(block); | 603 return new (buffer) BlockStartInstruction(block); |
| 604 } | 604 } |
| 605 | 605 |
| 606 static BlockStartInstruction* cast(Instruction* instr) { | 606 static BlockStartInstruction* cast(Instruction* instr) { |
| 607 ASSERT(instr->IsBlockStart()); | 607 DCHECK(instr->IsBlockStart()); |
| 608 return static_cast<BlockStartInstruction*>(instr); | 608 return static_cast<BlockStartInstruction*>(instr); |
| 609 } | 609 } |
| 610 | 610 |
| 611 private: | 611 private: |
| 612 explicit BlockStartInstruction(BasicBlock* block) | 612 explicit BlockStartInstruction(BasicBlock* block) |
| 613 : GapInstruction(kBlockStartInstruction), block_(block) {} | 613 : GapInstruction(kBlockStartInstruction), block_(block) {} |
| 614 | 614 |
| 615 BasicBlock* block_; | 615 BasicBlock* block_; |
| 616 Label label_; | 616 Label label_; |
| 617 }; | 617 }; |
| 618 | 618 |
| 619 | 619 |
| 620 class SourcePositionInstruction V8_FINAL : public Instruction { | 620 class SourcePositionInstruction V8_FINAL : public Instruction { |
| 621 public: | 621 public: |
| 622 static SourcePositionInstruction* New(Zone* zone, SourcePosition position) { | 622 static SourcePositionInstruction* New(Zone* zone, SourcePosition position) { |
| 623 void* buffer = zone->New(sizeof(SourcePositionInstruction)); | 623 void* buffer = zone->New(sizeof(SourcePositionInstruction)); |
| 624 return new (buffer) SourcePositionInstruction(position); | 624 return new (buffer) SourcePositionInstruction(position); |
| 625 } | 625 } |
| 626 | 626 |
| 627 SourcePosition source_position() const { return source_position_; } | 627 SourcePosition source_position() const { return source_position_; } |
| 628 | 628 |
| 629 static SourcePositionInstruction* cast(Instruction* instr) { | 629 static SourcePositionInstruction* cast(Instruction* instr) { |
| 630 ASSERT(instr->IsSourcePosition()); | 630 DCHECK(instr->IsSourcePosition()); |
| 631 return static_cast<SourcePositionInstruction*>(instr); | 631 return static_cast<SourcePositionInstruction*>(instr); |
| 632 } | 632 } |
| 633 | 633 |
| 634 static const SourcePositionInstruction* cast(const Instruction* instr) { | 634 static const SourcePositionInstruction* cast(const Instruction* instr) { |
| 635 ASSERT(instr->IsSourcePosition()); | 635 DCHECK(instr->IsSourcePosition()); |
| 636 return static_cast<const SourcePositionInstruction*>(instr); | 636 return static_cast<const SourcePositionInstruction*>(instr); |
| 637 } | 637 } |
| 638 | 638 |
| 639 private: | 639 private: |
| 640 explicit SourcePositionInstruction(SourcePosition source_position) | 640 explicit SourcePositionInstruction(SourcePosition source_position) |
| 641 : Instruction(kSourcePositionInstruction), | 641 : Instruction(kSourcePositionInstruction), |
| 642 source_position_(source_position) { | 642 source_position_(source_position) { |
| 643 ASSERT(!source_position_.IsInvalid()); | 643 DCHECK(!source_position_.IsInvalid()); |
| 644 ASSERT(!source_position_.IsUnknown()); | 644 DCHECK(!source_position_.IsUnknown()); |
| 645 } | 645 } |
| 646 | 646 |
| 647 SourcePosition source_position_; | 647 SourcePosition source_position_; |
| 648 }; | 648 }; |
| 649 | 649 |
| 650 | 650 |
| 651 class Constant V8_FINAL { | 651 class Constant V8_FINAL { |
| 652 public: | 652 public: |
| 653 enum Type { kInt32, kInt64, kFloat64, kExternalReference, kHeapObject }; | 653 enum Type { kInt32, kInt64, kFloat64, kExternalReference, kHeapObject }; |
| 654 | 654 |
| 655 explicit Constant(int32_t v) : type_(kInt32), value_(v) {} | 655 explicit Constant(int32_t v) : type_(kInt32), value_(v) {} |
| 656 explicit Constant(int64_t v) : type_(kInt64), value_(v) {} | 656 explicit Constant(int64_t v) : type_(kInt64), value_(v) {} |
| 657 explicit Constant(double v) : type_(kFloat64), value_(BitCast<int64_t>(v)) {} | 657 explicit Constant(double v) : type_(kFloat64), value_(BitCast<int64_t>(v)) {} |
| 658 explicit Constant(ExternalReference ref) | 658 explicit Constant(ExternalReference ref) |
| 659 : type_(kExternalReference), value_(BitCast<intptr_t>(ref)) {} | 659 : type_(kExternalReference), value_(BitCast<intptr_t>(ref)) {} |
| 660 explicit Constant(Handle<HeapObject> obj) | 660 explicit Constant(Handle<HeapObject> obj) |
| 661 : type_(kHeapObject), value_(BitCast<intptr_t>(obj)) {} | 661 : type_(kHeapObject), value_(BitCast<intptr_t>(obj)) {} |
| 662 | 662 |
| 663 Type type() const { return type_; } | 663 Type type() const { return type_; } |
| 664 | 664 |
| 665 int32_t ToInt32() const { | 665 int32_t ToInt32() const { |
| 666 ASSERT_EQ(kInt32, type()); | 666 DCHECK_EQ(kInt32, type()); |
| 667 return static_cast<int32_t>(value_); | 667 return static_cast<int32_t>(value_); |
| 668 } | 668 } |
| 669 | 669 |
| 670 int64_t ToInt64() const { | 670 int64_t ToInt64() const { |
| 671 if (type() == kInt32) return ToInt32(); | 671 if (type() == kInt32) return ToInt32(); |
| 672 ASSERT_EQ(kInt64, type()); | 672 DCHECK_EQ(kInt64, type()); |
| 673 return value_; | 673 return value_; |
| 674 } | 674 } |
| 675 | 675 |
| 676 double ToFloat64() const { | 676 double ToFloat64() const { |
| 677 if (type() == kInt32) return ToInt32(); | 677 if (type() == kInt32) return ToInt32(); |
| 678 ASSERT_EQ(kFloat64, type()); | 678 DCHECK_EQ(kFloat64, type()); |
| 679 return BitCast<double>(value_); | 679 return BitCast<double>(value_); |
| 680 } | 680 } |
| 681 | 681 |
| 682 ExternalReference ToExternalReference() const { | 682 ExternalReference ToExternalReference() const { |
| 683 ASSERT_EQ(kExternalReference, type()); | 683 DCHECK_EQ(kExternalReference, type()); |
| 684 return BitCast<ExternalReference>(static_cast<intptr_t>(value_)); | 684 return BitCast<ExternalReference>(static_cast<intptr_t>(value_)); |
| 685 } | 685 } |
| 686 | 686 |
| 687 Handle<HeapObject> ToHeapObject() const { | 687 Handle<HeapObject> ToHeapObject() const { |
| 688 ASSERT_EQ(kHeapObject, type()); | 688 DCHECK_EQ(kHeapObject, type()); |
| 689 return BitCast<Handle<HeapObject> >(static_cast<intptr_t>(value_)); | 689 return BitCast<Handle<HeapObject> >(static_cast<intptr_t>(value_)); |
| 690 } | 690 } |
| 691 | 691 |
| 692 private: | 692 private: |
| 693 Type type_; | 693 Type type_; |
| 694 int64_t value_; | 694 int64_t value_; |
| 695 }; | 695 }; |
| 696 | 696 |
| 697 OStream& operator<<(OStream& os, const Constant& constant); | 697 OStream& operator<<(OStream& os, const Constant& constant); |
| 698 | 698 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 | 764 |
| 765 typedef InstructionDeque::const_iterator const_iterator; | 765 typedef InstructionDeque::const_iterator const_iterator; |
| 766 const_iterator begin() const { return instructions_.begin(); } | 766 const_iterator begin() const { return instructions_.begin(); } |
| 767 const_iterator end() const { return instructions_.end(); } | 767 const_iterator end() const { return instructions_.end(); } |
| 768 | 768 |
| 769 GapInstruction* GapAt(int index) const { | 769 GapInstruction* GapAt(int index) const { |
| 770 return GapInstruction::cast(InstructionAt(index)); | 770 return GapInstruction::cast(InstructionAt(index)); |
| 771 } | 771 } |
| 772 bool IsGapAt(int index) const { return InstructionAt(index)->IsGapMoves(); } | 772 bool IsGapAt(int index) const { return InstructionAt(index)->IsGapMoves(); } |
| 773 Instruction* InstructionAt(int index) const { | 773 Instruction* InstructionAt(int index) const { |
| 774 ASSERT(index >= 0); | 774 DCHECK(index >= 0); |
| 775 ASSERT(index < static_cast<int>(instructions_.size())); | 775 DCHECK(index < static_cast<int>(instructions_.size())); |
| 776 return instructions_[index]; | 776 return instructions_[index]; |
| 777 } | 777 } |
| 778 | 778 |
| 779 Frame* frame() { return &frame_; } | 779 Frame* frame() { return &frame_; } |
| 780 Graph* graph() const { return graph_; } | 780 Graph* graph() const { return graph_; } |
| 781 Isolate* isolate() const { return zone()->isolate(); } | 781 Isolate* isolate() const { return zone()->isolate(); } |
| 782 Linkage* linkage() const { return linkage_; } | 782 Linkage* linkage() const { return linkage_; } |
| 783 Schedule* schedule() const { return schedule_; } | 783 Schedule* schedule() const { return schedule_; } |
| 784 const PointerMapDeque* pointer_maps() const { return &pointer_maps_; } | 784 const PointerMapDeque* pointer_maps() const { return &pointer_maps_; } |
| 785 Zone* zone() const { return graph_->zone(); } | 785 Zone* zone() const { return graph_->zone(); } |
| 786 | 786 |
| 787 // Used by the code generator while adding instructions. | 787 // Used by the code generator while adding instructions. |
| 788 int AddInstruction(Instruction* instr, BasicBlock* block); | 788 int AddInstruction(Instruction* instr, BasicBlock* block); |
| 789 void StartBlock(BasicBlock* block); | 789 void StartBlock(BasicBlock* block); |
| 790 void EndBlock(BasicBlock* block); | 790 void EndBlock(BasicBlock* block); |
| 791 | 791 |
| 792 void AddConstant(int virtual_register, Constant constant) { | 792 void AddConstant(int virtual_register, Constant constant) { |
| 793 ASSERT(constants_.find(virtual_register) == constants_.end()); | 793 DCHECK(constants_.find(virtual_register) == constants_.end()); |
| 794 constants_.insert(std::make_pair(virtual_register, constant)); | 794 constants_.insert(std::make_pair(virtual_register, constant)); |
| 795 } | 795 } |
| 796 Constant GetConstant(int virtual_register) const { | 796 Constant GetConstant(int virtual_register) const { |
| 797 ConstantMap::const_iterator it = constants_.find(virtual_register); | 797 ConstantMap::const_iterator it = constants_.find(virtual_register); |
| 798 ASSERT(it != constants_.end()); | 798 DCHECK(it != constants_.end()); |
| 799 ASSERT_EQ(virtual_register, it->first); | 799 DCHECK_EQ(virtual_register, it->first); |
| 800 return it->second; | 800 return it->second; |
| 801 } | 801 } |
| 802 | 802 |
| 803 typedef ConstantDeque Immediates; | 803 typedef ConstantDeque Immediates; |
| 804 const Immediates& immediates() const { return immediates_; } | 804 const Immediates& immediates() const { return immediates_; } |
| 805 | 805 |
| 806 int AddImmediate(Constant constant) { | 806 int AddImmediate(Constant constant) { |
| 807 int index = static_cast<int>(immediates_.size()); | 807 int index = static_cast<int>(immediates_.size()); |
| 808 immediates_.push_back(constant); | 808 immediates_.push_back(constant); |
| 809 return index; | 809 return index; |
| 810 } | 810 } |
| 811 Constant GetImmediate(int index) const { | 811 Constant GetImmediate(int index) const { |
| 812 ASSERT(index >= 0); | 812 DCHECK(index >= 0); |
| 813 ASSERT(index < static_cast<int>(immediates_.size())); | 813 DCHECK(index < static_cast<int>(immediates_.size())); |
| 814 return immediates_[index]; | 814 return immediates_[index]; |
| 815 } | 815 } |
| 816 | 816 |
| 817 int AddDeoptimizationEntry(const FrameStateDescriptor& descriptor); | 817 int AddDeoptimizationEntry(const FrameStateDescriptor& descriptor); |
| 818 FrameStateDescriptor GetDeoptimizationEntry(int deoptimization_id); | 818 FrameStateDescriptor GetDeoptimizationEntry(int deoptimization_id); |
| 819 int GetDeoptimizationEntryCount(); | 819 int GetDeoptimizationEntryCount(); |
| 820 | 820 |
| 821 private: | 821 private: |
| 822 friend OStream& operator<<(OStream& os, const InstructionSequence& code); | 822 friend OStream& operator<<(OStream& os, const InstructionSequence& code); |
| 823 | 823 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 837 DeoptimizationVector deoptimization_entries_; | 837 DeoptimizationVector deoptimization_entries_; |
| 838 }; | 838 }; |
| 839 | 839 |
| 840 OStream& operator<<(OStream& os, const InstructionSequence& code); | 840 OStream& operator<<(OStream& os, const InstructionSequence& code); |
| 841 | 841 |
| 842 } // namespace compiler | 842 } // namespace compiler |
| 843 } // namespace internal | 843 } // namespace internal |
| 844 } // namespace v8 | 844 } // namespace v8 |
| 845 | 845 |
| 846 #endif // V8_COMPILER_INSTRUCTION_H_ | 846 #endif // V8_COMPILER_INSTRUCTION_H_ |
| OLD | NEW |