| 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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 result = HType::Boolean(); | 257 result = HType::Boolean(); |
| 258 } else if (value->IsJSObject()) { | 258 } else if (value->IsJSObject()) { |
| 259 result = HType::JSObject(); | 259 result = HType::JSObject(); |
| 260 } else if (value->IsJSArray()) { | 260 } else if (value->IsJSArray()) { |
| 261 result = HType::JSArray(); | 261 result = HType::JSArray(); |
| 262 } | 262 } |
| 263 return result; | 263 return result; |
| 264 } | 264 } |
| 265 | 265 |
| 266 | 266 |
| 267 int HValue::LookupOperandIndex(int occurrence_index, HValue* op) { | |
| 268 for (int i = 0; i < OperandCount(); ++i) { | |
| 269 if (OperandAt(i) == op) { | |
| 270 if (occurrence_index == 0) return i; | |
| 271 --occurrence_index; | |
| 272 } | |
| 273 } | |
| 274 return -1; | |
| 275 } | |
| 276 | |
| 277 | |
| 278 bool HValue::IsDefinedAfter(HBasicBlock* other) const { | 267 bool HValue::IsDefinedAfter(HBasicBlock* other) const { |
| 279 return block()->block_id() > other->block_id(); | 268 return block()->block_id() > other->block_id(); |
| 280 } | 269 } |
| 281 | 270 |
| 282 | 271 |
| 283 bool HValue::UsesMultipleTimes(HValue* op) { | 272 HUseIterator::HUseIterator(HUseListNode* head) : next_(head) { |
| 284 bool seen = false; | 273 Advance(); |
| 285 for (int i = 0; i < OperandCount(); ++i) { | |
| 286 if (OperandAt(i) == op) { | |
| 287 if (seen) return true; | |
| 288 seen = true; | |
| 289 } | |
| 290 } | |
| 291 return false; | |
| 292 } | 274 } |
| 293 | 275 |
| 294 | 276 |
| 277 void HUseIterator::Advance() { |
| 278 current_ = next_; |
| 279 if (current_ != NULL) { |
| 280 next_ = current_->tail(); |
| 281 value_ = current_->value(); |
| 282 index_ = current_->index(); |
| 283 } |
| 284 } |
| 285 |
| 286 |
| 287 int HValue::UseCount() const { |
| 288 int count = 0; |
| 289 for (HUseIterator it(uses()); !it.Done(); it.Advance()) ++count; |
| 290 return count; |
| 291 } |
| 292 |
| 293 |
| 294 HUseListNode* HValue::RemoveUse(HValue* value, int index) { |
| 295 HUseListNode* previous = NULL; |
| 296 HUseListNode* current = use_list_; |
| 297 while (current != NULL) { |
| 298 if (current->value() == value && current->index() == index) { |
| 299 if (previous == NULL) { |
| 300 use_list_ = current->tail(); |
| 301 } else { |
| 302 previous->set_tail(current->tail()); |
| 303 } |
| 304 break; |
| 305 } |
| 306 |
| 307 previous = current; |
| 308 current = current->tail(); |
| 309 } |
| 310 |
| 311 #ifdef DEBUG |
| 312 // Do not reuse use list nodes in debug mode, zap them. |
| 313 if (current != NULL) { |
| 314 HUseListNode* temp = |
| 315 new HUseListNode(current->value(), current->index(), NULL); |
| 316 current->Zap(); |
| 317 current = temp; |
| 318 } |
| 319 #endif |
| 320 return current; |
| 321 } |
| 322 |
| 323 |
| 295 bool HValue::Equals(HValue* other) { | 324 bool HValue::Equals(HValue* other) { |
| 296 if (other->opcode() != opcode()) return false; | 325 if (other->opcode() != opcode()) return false; |
| 297 if (!other->representation().Equals(representation())) return false; | 326 if (!other->representation().Equals(representation())) return false; |
| 298 if (!other->type_.Equals(type_)) return false; | 327 if (!other->type_.Equals(type_)) return false; |
| 299 if (other->flags() != flags()) return false; | 328 if (other->flags() != flags()) return false; |
| 300 if (OperandCount() != other->OperandCount()) return false; | 329 if (OperandCount() != other->OperandCount()) return false; |
| 301 for (int i = 0; i < OperandCount(); ++i) { | 330 for (int i = 0; i < OperandCount(); ++i) { |
| 302 if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false; | 331 if (OperandAt(i)->id() != other->OperandAt(i)->id()) return false; |
| 303 } | 332 } |
| 304 bool result = DataEquals(other); | 333 bool result = DataEquals(other); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 328 } | 357 } |
| 329 | 358 |
| 330 | 359 |
| 331 void HValue::SetOperandAt(int index, HValue* value) { | 360 void HValue::SetOperandAt(int index, HValue* value) { |
| 332 ASSERT(value == NULL || !value->representation().IsNone()); | 361 ASSERT(value == NULL || !value->representation().IsNone()); |
| 333 RegisterUse(index, value); | 362 RegisterUse(index, value); |
| 334 InternalSetOperandAt(index, value); | 363 InternalSetOperandAt(index, value); |
| 335 } | 364 } |
| 336 | 365 |
| 337 | 366 |
| 338 void HValue::ReplaceAndDelete(HValue* other) { | 367 void HValue::DeleteAndReplaceWith(HValue* other) { |
| 339 if (other != NULL) ReplaceValue(other); | 368 // We replace all uses first, so Delete can assert that there are none. |
| 340 Delete(); | 369 if (other != NULL) ReplaceAllUsesWith(other); |
| 370 ASSERT(HasNoUses()); |
| 371 ClearOperands(); |
| 372 DeleteFromGraph(); |
| 341 } | 373 } |
| 342 | 374 |
| 343 | 375 |
| 344 void HValue::ReplaceValue(HValue* other) { | 376 void HValue::ReplaceAllUsesWith(HValue* other) { |
| 345 for (int i = 0; i < uses_.length(); ++i) { | 377 while (use_list_ != NULL) { |
| 346 HValue* use = uses_[i]; | 378 HUseListNode* list_node = use_list_; |
| 347 ASSERT(!use->block()->IsStartBlock()); | 379 HValue* value = list_node->value(); |
| 348 InternalReplaceAtUse(use, other); | 380 ASSERT(!value->block()->IsStartBlock()); |
| 349 other->uses_.Add(use); | 381 value->InternalSetOperandAt(list_node->index(), other); |
| 382 use_list_ = list_node->tail(); |
| 383 list_node->set_tail(other->use_list_); |
| 384 other->use_list_ = list_node; |
| 350 } | 385 } |
| 351 uses_.Rewind(0); | |
| 352 } | 386 } |
| 353 | 387 |
| 354 | 388 |
| 355 void HValue::ClearOperands() { | 389 void HValue::ClearOperands() { |
| 356 for (int i = 0; i < OperandCount(); ++i) { | 390 for (int i = 0; i < OperandCount(); ++i) { |
| 357 SetOperandAt(i, NULL); | 391 SetOperandAt(i, NULL); |
| 358 } | 392 } |
| 359 } | 393 } |
| 360 | 394 |
| 361 | |
| 362 void HValue::Delete() { | |
| 363 ASSERT(HasNoUses()); | |
| 364 ClearOperands(); | |
| 365 DeleteFromGraph(); | |
| 366 } | |
| 367 | |
| 368 | |
| 369 void HValue::ReplaceAtUse(HValue* use, HValue* other) { | |
| 370 for (int i = 0; i < use->OperandCount(); ++i) { | |
| 371 if (use->OperandAt(i) == this) { | |
| 372 use->SetOperandAt(i, other); | |
| 373 } | |
| 374 } | |
| 375 } | |
| 376 | |
| 377 | |
| 378 void HValue::ReplaceFirstAtUse(HValue* use, HValue* other, Representation r) { | |
| 379 for (int i = 0; i < use->OperandCount(); ++i) { | |
| 380 if (use->RequiredInputRepresentation(i).Equals(r) && | |
| 381 use->OperandAt(i) == this) { | |
| 382 use->SetOperandAt(i, other); | |
| 383 return; | |
| 384 } | |
| 385 } | |
| 386 } | |
| 387 | |
| 388 | |
| 389 void HValue::InternalReplaceAtUse(HValue* use, HValue* other) { | |
| 390 for (int i = 0; i < use->OperandCount(); ++i) { | |
| 391 if (use->OperandAt(i) == this) { | |
| 392 // Call internal method that does not update use lists. The caller is | |
| 393 // responsible for doing so. | |
| 394 use->InternalSetOperandAt(i, other); | |
| 395 } | |
| 396 } | |
| 397 } | |
| 398 | |
| 399 | 395 |
| 400 void HValue::SetBlock(HBasicBlock* block) { | 396 void HValue::SetBlock(HBasicBlock* block) { |
| 401 ASSERT(block_ == NULL || block == NULL); | 397 ASSERT(block_ == NULL || block == NULL); |
| 402 block_ = block; | 398 block_ = block; |
| 403 if (id_ == kNoNumber && block != NULL) { | 399 if (id_ == kNoNumber && block != NULL) { |
| 404 id_ = block->graph()->GetNextValueID(this); | 400 id_ = block->graph()->GetNextValueID(this); |
| 405 } | 401 } |
| 406 } | 402 } |
| 407 | 403 |
| 408 | 404 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 420 HType type = CalculateInferredType(); | 416 HType type = CalculateInferredType(); |
| 421 bool result = (!type.Equals(type_)); | 417 bool result = (!type.Equals(type_)); |
| 422 type_ = type; | 418 type_ = type; |
| 423 return result; | 419 return result; |
| 424 } | 420 } |
| 425 | 421 |
| 426 | 422 |
| 427 void HValue::RegisterUse(int index, HValue* new_value) { | 423 void HValue::RegisterUse(int index, HValue* new_value) { |
| 428 HValue* old_value = OperandAt(index); | 424 HValue* old_value = OperandAt(index); |
| 429 if (old_value == new_value) return; | 425 if (old_value == new_value) return; |
| 430 if (old_value != NULL) old_value->uses_.RemoveElement(this); | 426 |
| 427 HUseListNode* removed = NULL; |
| 428 if (old_value != NULL) { |
| 429 removed = old_value->RemoveUse(this, index); |
| 430 } |
| 431 |
| 431 if (new_value != NULL) { | 432 if (new_value != NULL) { |
| 432 new_value->uses_.Add(this); | 433 #ifdef DEBUG |
| 434 // Never reuse list nodes in debug builds. |
| 435 removed = NULL; |
| 436 #endif |
| 437 if (removed == NULL) { |
| 438 new_value->use_list_ = new HUseListNode(this, index, new_value->use_list_)
; |
| 439 } else { |
| 440 removed->set_tail(new_value->use_list_); |
| 441 new_value->use_list_ = removed; |
| 442 } |
| 433 } | 443 } |
| 434 } | 444 } |
| 435 | 445 |
| 436 | 446 |
| 437 void HValue::AddNewRange(Range* r) { | 447 void HValue::AddNewRange(Range* r) { |
| 438 if (!HasRange()) ComputeInitialRange(); | 448 if (!HasRange()) ComputeInitialRange(); |
| 439 if (!HasRange()) range_ = new Range(); | 449 if (!HasRange()) range_ = new Range(); |
| 440 ASSERT(HasRange()); | 450 ASSERT(HasRange()); |
| 441 r->StackUpon(range_); | 451 r->StackUpon(range_); |
| 442 range_ = r; | 452 range_ = r; |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 919 | 929 |
| 920 void HPhi::PrintTo(StringStream* stream) { | 930 void HPhi::PrintTo(StringStream* stream) { |
| 921 stream->Add("["); | 931 stream->Add("["); |
| 922 for (int i = 0; i < OperandCount(); ++i) { | 932 for (int i = 0; i < OperandCount(); ++i) { |
| 923 HValue* value = OperandAt(i); | 933 HValue* value = OperandAt(i); |
| 924 stream->Add(" "); | 934 stream->Add(" "); |
| 925 value->PrintNameTo(stream); | 935 value->PrintNameTo(stream); |
| 926 stream->Add(" "); | 936 stream->Add(" "); |
| 927 } | 937 } |
| 928 stream->Add(" uses%d_%di_%dd_%dt]", | 938 stream->Add(" uses%d_%di_%dd_%dt]", |
| 929 uses()->length(), | 939 UseCount(), |
| 930 int32_non_phi_uses() + int32_indirect_uses(), | 940 int32_non_phi_uses() + int32_indirect_uses(), |
| 931 double_non_phi_uses() + double_indirect_uses(), | 941 double_non_phi_uses() + double_indirect_uses(), |
| 932 tagged_non_phi_uses() + tagged_indirect_uses()); | 942 tagged_non_phi_uses() + tagged_indirect_uses()); |
| 933 } | 943 } |
| 934 | 944 |
| 935 | 945 |
| 936 void HPhi::AddInput(HValue* value) { | 946 void HPhi::AddInput(HValue* value) { |
| 937 inputs_.Add(NULL); | 947 inputs_.Add(NULL); |
| 938 SetOperandAt(OperandCount() - 1, value); | 948 SetOperandAt(OperandCount() - 1, value); |
| 939 // Mark phis that may have 'arguments' directly or indirectly as an operand. | 949 // Mark phis that may have 'arguments' directly or indirectly as an operand. |
| 940 if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) { | 950 if (!CheckFlag(kIsArguments) && value->CheckFlag(kIsArguments)) { |
| 941 SetFlag(kIsArguments); | 951 SetFlag(kIsArguments); |
| 942 } | 952 } |
| 943 } | 953 } |
| 944 | 954 |
| 945 | 955 |
| 946 bool HPhi::HasRealUses() { | 956 bool HPhi::HasRealUses() { |
| 947 for (int i = 0; i < uses()->length(); i++) { | 957 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { |
| 948 if (!uses()->at(i)->IsPhi()) return true; | 958 if (!it.value()->IsPhi()) return true; |
| 949 } | 959 } |
| 950 return false; | 960 return false; |
| 951 } | 961 } |
| 952 | 962 |
| 953 | 963 |
| 954 HValue* HPhi::GetRedundantReplacement() { | 964 HValue* HPhi::GetRedundantReplacement() { |
| 955 HValue* candidate = NULL; | 965 HValue* candidate = NULL; |
| 956 int count = OperandCount(); | 966 int count = OperandCount(); |
| 957 int position = 0; | 967 int position = 0; |
| 958 while (position < count && candidate == NULL) { | 968 while (position < count && candidate == NULL) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 971 void HPhi::DeleteFromGraph() { | 981 void HPhi::DeleteFromGraph() { |
| 972 ASSERT(block() != NULL); | 982 ASSERT(block() != NULL); |
| 973 block()->RemovePhi(this); | 983 block()->RemovePhi(this); |
| 974 ASSERT(block() == NULL); | 984 ASSERT(block() == NULL); |
| 975 } | 985 } |
| 976 | 986 |
| 977 | 987 |
| 978 void HPhi::InitRealUses(int phi_id) { | 988 void HPhi::InitRealUses(int phi_id) { |
| 979 // Initialize real uses. | 989 // Initialize real uses. |
| 980 phi_id_ = phi_id; | 990 phi_id_ = phi_id; |
| 981 for (int j = 0; j < uses()->length(); j++) { | 991 for (HUseIterator it(uses()); !it.Done(); it.Advance()) { |
| 982 HValue* use = uses()->at(j); | 992 HValue* value = it.value(); |
| 983 if (!use->IsPhi()) { | 993 if (!value->IsPhi()) { |
| 984 int index = use->LookupOperandIndex(0, this); | 994 Representation rep = value->RequiredInputRepresentation(it.index()); |
| 985 Representation req_rep = use->RequiredInputRepresentation(index); | 995 ++non_phi_uses_[rep.kind()]; |
| 986 non_phi_uses_[req_rep.kind()]++; | |
| 987 } | 996 } |
| 988 } | 997 } |
| 989 } | 998 } |
| 990 | 999 |
| 991 | 1000 |
| 992 void HPhi::AddNonPhiUsesFrom(HPhi* other) { | 1001 void HPhi::AddNonPhiUsesFrom(HPhi* other) { |
| 993 for (int i = 0; i < Representation::kNumRepresentations; i++) { | 1002 for (int i = 0; i < Representation::kNumRepresentations; i++) { |
| 994 indirect_uses_[i] += other->non_phi_uses_[i]; | 1003 indirect_uses_[i] += other->non_phi_uses_[i]; |
| 995 } | 1004 } |
| 996 } | 1005 } |
| (...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1657 | 1666 |
| 1658 | 1667 |
| 1659 void HCheckPrototypeMaps::Verify() { | 1668 void HCheckPrototypeMaps::Verify() { |
| 1660 HInstruction::Verify(); | 1669 HInstruction::Verify(); |
| 1661 ASSERT(HasNoUses()); | 1670 ASSERT(HasNoUses()); |
| 1662 } | 1671 } |
| 1663 | 1672 |
| 1664 #endif | 1673 #endif |
| 1665 | 1674 |
| 1666 } } // namespace v8::internal | 1675 } } // namespace v8::internal |
| OLD | NEW |