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 |