Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(767)

Side by Side Diff: src/objects.cc

Issue 9086006: Randomize the seed used for string hashing. This helps guard against (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 6664 matching lines...) Expand 10 before | Expand all | Expand 10 after
6675 6675
6676 bool String::SlowEquals(String* other) { 6676 bool String::SlowEquals(String* other) {
6677 // Fast check: negative check with lengths. 6677 // Fast check: negative check with lengths.
6678 int len = length(); 6678 int len = length();
6679 if (len != other->length()) return false; 6679 if (len != other->length()) return false;
6680 if (len == 0) return true; 6680 if (len == 0) return true;
6681 6681
6682 // Fast check: if hash code is computed for both strings 6682 // Fast check: if hash code is computed for both strings
6683 // a fast negative check can be performed. 6683 // a fast negative check can be performed.
6684 if (HasHashCode() && other->HasHashCode()) { 6684 if (HasHashCode() && other->HasHashCode()) {
6685 #ifdef DEBUG
6686 if (Hash() != other->Hash()) {
6687 bool found_difference = false;
6688 for (int i = 0; i < len; i++) {
6689 if (Get(i) != other->Get(i)) {
6690 found_difference = true;
6691 break;
6692 }
6693 }
6694 ASSERT(found_difference);
6695 }
6696 #endif
Vyacheslav Egorov (Chromium) 2012/01/04 14:30:57 I think this should be checked only when slow asse
Erik Corry 2012/01/04 15:48:59 Done.
6685 if (Hash() != other->Hash()) return false; 6697 if (Hash() != other->Hash()) return false;
6686 } 6698 }
6687 6699
6688 // We know the strings are both non-empty. Compare the first chars 6700 // We know the strings are both non-empty. Compare the first chars
6689 // before we try to flatten the strings. 6701 // before we try to flatten the strings.
6690 if (this->Get(0) != other->Get(0)) return false; 6702 if (this->Get(0) != other->Get(0)) return false;
6691 6703
6692 String* lhs = this->TryFlattenGetString(); 6704 String* lhs = this->TryFlattenGetString();
6693 String* rhs = other->TryFlattenGetString(); 6705 String* rhs = other->TryFlattenGetString();
6694 6706
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
6810 6822
6811 uint32_t String::ComputeAndSetHash() { 6823 uint32_t String::ComputeAndSetHash() {
6812 // Should only be called if hash code has not yet been computed. 6824 // Should only be called if hash code has not yet been computed.
6813 ASSERT(!HasHashCode()); 6825 ASSERT(!HasHashCode());
6814 6826
6815 const int len = length(); 6827 const int len = length();
6816 6828
6817 // Compute the hash code. 6829 // Compute the hash code.
6818 uint32_t field = 0; 6830 uint32_t field = 0;
6819 if (StringShape(this).IsSequentialAscii()) { 6831 if (StringShape(this).IsSequentialAscii()) {
6820 field = HashSequentialString(SeqAsciiString::cast(this)->GetChars(), len); 6832 field = HashSequentialString(SeqAsciiString::cast(this)->GetChars(),
6833 len,
6834 GetHeap()->StringHashSeed());
6821 } else if (StringShape(this).IsSequentialTwoByte()) { 6835 } else if (StringShape(this).IsSequentialTwoByte()) {
6822 field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(), len); 6836 field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(),
6837 len,
6838 GetHeap()->StringHashSeed());
6823 } else { 6839 } else {
6824 StringInputBuffer buffer(this); 6840 StringInputBuffer buffer(this);
6825 field = ComputeHashField(&buffer, len); 6841 field = ComputeHashField(&buffer, len, GetHeap()->StringHashSeed());
6826 } 6842 }
6827 6843
6828 // Store the hash code in the object. 6844 // Store the hash code in the object.
6829 set_hash_field(field); 6845 set_hash_field(field);
6830 6846
6831 // Check the hash code is there. 6847 // Check the hash code is there.
6832 ASSERT(HasHashCode()); 6848 ASSERT(HasHashCode());
6833 uint32_t result = field >> kHashShift; 6849 uint32_t result = field >> kHashShift;
6834 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. 6850 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
6835 return result; 6851 return result;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
6906 return MakeArrayIndexHash(array_index(), length_); 6922 return MakeArrayIndexHash(array_index(), length_);
6907 } 6923 }
6908 return (GetHash() << String::kHashShift) | String::kIsNotArrayIndexMask; 6924 return (GetHash() << String::kHashShift) | String::kIsNotArrayIndexMask;
6909 } else { 6925 } else {
6910 return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask; 6926 return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
6911 } 6927 }
6912 } 6928 }
6913 6929
6914 6930
6915 uint32_t String::ComputeHashField(unibrow::CharacterStream* buffer, 6931 uint32_t String::ComputeHashField(unibrow::CharacterStream* buffer,
6916 int length) { 6932 int length,
6917 StringHasher hasher(length); 6933 uint32_t seed) {
6934 StringHasher hasher(length, seed);
6918 6935
6919 // Very long strings have a trivial hash that doesn't inspect the 6936 // Very long strings have a trivial hash that doesn't inspect the
6920 // string contents. 6937 // string contents.
6921 if (hasher.has_trivial_hash()) { 6938 if (hasher.has_trivial_hash()) {
6922 return hasher.GetHashField(); 6939 return hasher.GetHashField();
6923 } 6940 }
6924 6941
6925 // Do the iterative array index computation as long as there is a 6942 // Do the iterative array index computation as long as there is a
6926 // chance this is an array index. 6943 // chance this is an array index.
6927 while (buffer->has_more() && hasher.is_array_index()) { 6944 while (buffer->has_more() && hasher.is_array_index()) {
(...skipping 3521 matching lines...) Expand 10 before | Expand all | Expand 10 after
10449 return string->Hash() + flags->value(); 10466 return string->Hash() + flags->value();
10450 } 10467 }
10451 10468
10452 String* string_; 10469 String* string_;
10453 Smi* flags_; 10470 Smi* flags_;
10454 }; 10471 };
10455 10472
10456 // Utf8SymbolKey carries a vector of chars as key. 10473 // Utf8SymbolKey carries a vector of chars as key.
10457 class Utf8SymbolKey : public HashTableKey { 10474 class Utf8SymbolKey : public HashTableKey {
10458 public: 10475 public:
10459 explicit Utf8SymbolKey(Vector<const char> string) 10476 explicit Utf8SymbolKey(Vector<const char> string, uint32_t seed)
10460 : string_(string), hash_field_(0) { } 10477 : string_(string), hash_field_(0), seed_(seed) { }
10461 10478
10462 bool IsMatch(Object* string) { 10479 bool IsMatch(Object* string) {
10463 return String::cast(string)->IsEqualTo(string_); 10480 return String::cast(string)->IsEqualTo(string_);
10464 } 10481 }
10465 10482
10466 uint32_t Hash() { 10483 uint32_t Hash() {
10467 if (hash_field_ != 0) return hash_field_ >> String::kHashShift; 10484 if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
10468 unibrow::Utf8InputBuffer<> buffer(string_.start(), 10485 unibrow::Utf8InputBuffer<> buffer(string_.start(),
10469 static_cast<unsigned>(string_.length())); 10486 static_cast<unsigned>(string_.length()));
10470 chars_ = buffer.Length(); 10487 chars_ = buffer.Length();
10471 hash_field_ = String::ComputeHashField(&buffer, chars_); 10488 hash_field_ = String::ComputeHashField(&buffer, chars_, seed_);
10472 uint32_t result = hash_field_ >> String::kHashShift; 10489 uint32_t result = hash_field_ >> String::kHashShift;
10473 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. 10490 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed.
10474 return result; 10491 return result;
10475 } 10492 }
10476 10493
10477 uint32_t HashForObject(Object* other) { 10494 uint32_t HashForObject(Object* other) {
10478 return String::cast(other)->Hash(); 10495 return String::cast(other)->Hash();
10479 } 10496 }
10480 10497
10481 MaybeObject* AsObject() { 10498 MaybeObject* AsObject() {
10482 if (hash_field_ == 0) Hash(); 10499 if (hash_field_ == 0) Hash();
10483 return Isolate::Current()->heap()->AllocateSymbol( 10500 return Isolate::Current()->heap()->AllocateSymbol(
10484 string_, chars_, hash_field_); 10501 string_, chars_, hash_field_);
10485 } 10502 }
10486 10503
10487 Vector<const char> string_; 10504 Vector<const char> string_;
10488 uint32_t hash_field_; 10505 uint32_t hash_field_;
10489 int chars_; // Caches the number of characters when computing the hash code. 10506 int chars_; // Caches the number of characters when computing the hash code.
10507 uint32_t seed_;
10490 }; 10508 };
10491 10509
10492 10510
10493 template <typename Char> 10511 template <typename Char>
10494 class SequentialSymbolKey : public HashTableKey { 10512 class SequentialSymbolKey : public HashTableKey {
10495 public: 10513 public:
10496 explicit SequentialSymbolKey(Vector<const Char> string) 10514 explicit SequentialSymbolKey(Vector<const Char> string, uint32_t seed)
10497 : string_(string), hash_field_(0) { } 10515 : string_(string), hash_field_(0), seed_(seed) { }
10498 10516
10499 uint32_t Hash() { 10517 uint32_t Hash() {
10500 StringHasher hasher(string_.length()); 10518 StringHasher hasher(string_.length(), seed_);
10501 10519
10502 // Very long strings have a trivial hash that doesn't inspect the 10520 // Very long strings have a trivial hash that doesn't inspect the
10503 // string contents. 10521 // string contents.
10504 if (hasher.has_trivial_hash()) { 10522 if (hasher.has_trivial_hash()) {
10505 hash_field_ = hasher.GetHashField(); 10523 hash_field_ = hasher.GetHashField();
10506 } else { 10524 } else {
10507 int i = 0; 10525 int i = 0;
10508 // Do the iterative array index computation as long as there is a 10526 // Do the iterative array index computation as long as there is a
10509 // chance this is an array index. 10527 // chance this is an array index.
10510 while (i < string_.length() && hasher.is_array_index()) { 10528 while (i < string_.length() && hasher.is_array_index()) {
(...skipping 15 matching lines...) Expand all
10526 return result; 10544 return result;
10527 } 10545 }
10528 10546
10529 10547
10530 uint32_t HashForObject(Object* other) { 10548 uint32_t HashForObject(Object* other) {
10531 return String::cast(other)->Hash(); 10549 return String::cast(other)->Hash();
10532 } 10550 }
10533 10551
10534 Vector<const Char> string_; 10552 Vector<const Char> string_;
10535 uint32_t hash_field_; 10553 uint32_t hash_field_;
10554 uint32_t seed_;
10536 }; 10555 };
10537 10556
10538 10557
10539 10558
10540 class AsciiSymbolKey : public SequentialSymbolKey<char> { 10559 class AsciiSymbolKey : public SequentialSymbolKey<char> {
10541 public: 10560 public:
10542 explicit AsciiSymbolKey(Vector<const char> str) 10561 AsciiSymbolKey(Vector<const char> str, uint32_t seed)
10543 : SequentialSymbolKey<char>(str) { } 10562 : SequentialSymbolKey<char>(str, seed) { }
10544 10563
10545 bool IsMatch(Object* string) { 10564 bool IsMatch(Object* string) {
10546 return String::cast(string)->IsAsciiEqualTo(string_); 10565 return String::cast(string)->IsAsciiEqualTo(string_);
10547 } 10566 }
10548 10567
10549 MaybeObject* AsObject() { 10568 MaybeObject* AsObject() {
10550 if (hash_field_ == 0) Hash(); 10569 if (hash_field_ == 0) Hash();
10551 return HEAP->AllocateAsciiSymbol(string_, hash_field_); 10570 return HEAP->AllocateAsciiSymbol(string_, hash_field_);
10552 } 10571 }
10553 }; 10572 };
10554 10573
10555 10574
10556 class SubStringAsciiSymbolKey : public HashTableKey { 10575 class SubStringAsciiSymbolKey : public HashTableKey {
10557 public: 10576 public:
10558 explicit SubStringAsciiSymbolKey(Handle<SeqAsciiString> string, 10577 explicit SubStringAsciiSymbolKey(Handle<SeqAsciiString> string,
10559 int from, 10578 int from,
10560 int length) 10579 int length,
10561 : string_(string), from_(from), length_(length) { } 10580 uint32_t seed)
10581 : string_(string), from_(from), length_(length), seed_(seed) { }
10562 10582
10563 uint32_t Hash() { 10583 uint32_t Hash() {
10564 ASSERT(length_ >= 0); 10584 ASSERT(length_ >= 0);
10565 ASSERT(from_ + length_ <= string_->length()); 10585 ASSERT(from_ + length_ <= string_->length());
10566 StringHasher hasher(length_); 10586 StringHasher hasher(length_, string_->GetHeap()->StringHashSeed());
10567 10587
10568 // Very long strings have a trivial hash that doesn't inspect the 10588 // Very long strings have a trivial hash that doesn't inspect the
10569 // string contents. 10589 // string contents.
10570 if (hasher.has_trivial_hash()) { 10590 if (hasher.has_trivial_hash()) {
10571 hash_field_ = hasher.GetHashField(); 10591 hash_field_ = hasher.GetHashField();
10572 } else { 10592 } else {
10573 int i = 0; 10593 int i = 0;
10574 // Do the iterative array index computation as long as there is a 10594 // Do the iterative array index computation as long as there is a
10575 // chance this is an array index. 10595 // chance this is an array index.
10576 while (i < length_ && hasher.is_array_index()) { 10596 while (i < length_ && hasher.is_array_index()) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
10608 if (hash_field_ == 0) Hash(); 10628 if (hash_field_ == 0) Hash();
10609 Vector<const char> chars(string_->GetChars() + from_, length_); 10629 Vector<const char> chars(string_->GetChars() + from_, length_);
10610 return HEAP->AllocateAsciiSymbol(chars, hash_field_); 10630 return HEAP->AllocateAsciiSymbol(chars, hash_field_);
10611 } 10631 }
10612 10632
10613 private: 10633 private:
10614 Handle<SeqAsciiString> string_; 10634 Handle<SeqAsciiString> string_;
10615 int from_; 10635 int from_;
10616 int length_; 10636 int length_;
10617 uint32_t hash_field_; 10637 uint32_t hash_field_;
10638 uint32_t seed_;
10618 }; 10639 };
10619 10640
10620 10641
10621 class TwoByteSymbolKey : public SequentialSymbolKey<uc16> { 10642 class TwoByteSymbolKey : public SequentialSymbolKey<uc16> {
10622 public: 10643 public:
10623 explicit TwoByteSymbolKey(Vector<const uc16> str) 10644 explicit TwoByteSymbolKey(Vector<const uc16> str, uint32_t seed)
10624 : SequentialSymbolKey<uc16>(str) { } 10645 : SequentialSymbolKey<uc16>(str, seed) { }
10625 10646
10626 bool IsMatch(Object* string) { 10647 bool IsMatch(Object* string) {
10627 return String::cast(string)->IsTwoByteEqualTo(string_); 10648 return String::cast(string)->IsTwoByteEqualTo(string_);
10628 } 10649 }
10629 10650
10630 MaybeObject* AsObject() { 10651 MaybeObject* AsObject() {
10631 if (hash_field_ == 0) Hash(); 10652 if (hash_field_ == 0) Hash();
10632 return HEAP->AllocateTwoByteSymbol(string_, hash_field_); 10653 return HEAP->AllocateTwoByteSymbol(string_, hash_field_);
10633 } 10654 }
10634 }; 10655 };
(...skipping 764 matching lines...) Expand 10 before | Expand all | Expand 10 after
11399 } 11420 }
11400 11421
11401 11422
11402 // This class is used for looking up two character strings in the symbol table. 11423 // This class is used for looking up two character strings in the symbol table.
11403 // If we don't have a hit we don't want to waste much time so we unroll the 11424 // If we don't have a hit we don't want to waste much time so we unroll the
11404 // string hash calculation loop here for speed. Doesn't work if the two 11425 // string hash calculation loop here for speed. Doesn't work if the two
11405 // characters form a decimal integer, since such strings have a different hash 11426 // characters form a decimal integer, since such strings have a different hash
11406 // algorithm. 11427 // algorithm.
11407 class TwoCharHashTableKey : public HashTableKey { 11428 class TwoCharHashTableKey : public HashTableKey {
11408 public: 11429 public:
11409 TwoCharHashTableKey(uint32_t c1, uint32_t c2) 11430 TwoCharHashTableKey(uint32_t c1, uint32_t c2, uint32_t seed)
11410 : c1_(c1), c2_(c2) { 11431 : c1_(c1), c2_(c2) {
11411 // Char 1. 11432 // Char 1.
11412 uint32_t hash = c1 + (c1 << 10); 11433 uint32_t hash = seed;
11434 hash += c1;
11435 hash += hash << 10;
11413 hash ^= hash >> 6; 11436 hash ^= hash >> 6;
11414 // Char 2. 11437 // Char 2.
11415 hash += c2; 11438 hash += c2;
11416 hash += hash << 10; 11439 hash += hash << 10;
11417 hash ^= hash >> 6; 11440 hash ^= hash >> 6;
11418 // GetHash. 11441 // GetHash.
11419 hash += hash << 3; 11442 hash += hash << 3;
11420 hash ^= hash >> 11; 11443 hash ^= hash >> 11;
11421 hash += hash << 15; 11444 hash += hash << 15;
11422 if (hash == 0) hash = 27; 11445 if (hash == 0) hash = 27;
11423 #ifdef DEBUG 11446 #ifdef DEBUG
11424 StringHasher hasher(2); 11447 StringHasher hasher(2, seed);
11425 hasher.AddCharacter(c1); 11448 hasher.AddCharacter(c1);
11426 hasher.AddCharacter(c2); 11449 hasher.AddCharacter(c2);
11427 // If this assert fails then we failed to reproduce the two-character 11450 // If this assert fails then we failed to reproduce the two-character
11428 // version of the string hashing algorithm above. One reason could be 11451 // version of the string hashing algorithm above. One reason could be
11429 // that we were passed two digits as characters, since the hash 11452 // that we were passed two digits as characters, since the hash
11430 // algorithm is different in that case. 11453 // algorithm is different in that case.
11431 ASSERT_EQ(static_cast<int>(hasher.GetHash()), static_cast<int>(hash)); 11454 ASSERT_EQ(static_cast<int>(hasher.GetHash()), static_cast<int>(hash));
11432 #endif 11455 #endif
11433 hash_ = hash; 11456 hash_ = hash;
11434 } 11457 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
11471 ASSERT(StringShape(result).IsSymbol()); 11494 ASSERT(StringShape(result).IsSymbol());
11472 *symbol = result; 11495 *symbol = result;
11473 return true; 11496 return true;
11474 } 11497 }
11475 } 11498 }
11476 11499
11477 11500
11478 bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1, 11501 bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1,
11479 uint32_t c2, 11502 uint32_t c2,
11480 String** symbol) { 11503 String** symbol) {
11481 TwoCharHashTableKey key(c1, c2); 11504 TwoCharHashTableKey key(c1, c2, GetHeap()->StringHashSeed());
11482 int entry = FindEntry(&key); 11505 int entry = FindEntry(&key);
11483 if (entry == kNotFound) { 11506 if (entry == kNotFound) {
11484 return false; 11507 return false;
11485 } else { 11508 } else {
11486 String* result = String::cast(KeyAt(entry)); 11509 String* result = String::cast(KeyAt(entry));
11487 ASSERT(StringShape(result).IsSymbol()); 11510 ASSERT(StringShape(result).IsSymbol());
11488 *symbol = result; 11511 *symbol = result;
11489 return true; 11512 return true;
11490 } 11513 }
11491 } 11514 }
11492 11515
11493 11516
11494 MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) { 11517 MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str,
11495 Utf8SymbolKey key(str); 11518 Object** s) {
11519 Utf8SymbolKey key(str, GetHeap()->StringHashSeed());
11496 return LookupKey(&key, s); 11520 return LookupKey(&key, s);
11497 } 11521 }
11498 11522
11499 11523
11500 MaybeObject* SymbolTable::LookupAsciiSymbol(Vector<const char> str, 11524 MaybeObject* SymbolTable::LookupAsciiSymbol(Vector<const char> str,
11501 Object** s) { 11525 Object** s) {
11502 AsciiSymbolKey key(str); 11526 AsciiSymbolKey key(str, GetHeap()->StringHashSeed());
11503 return LookupKey(&key, s); 11527 return LookupKey(&key, s);
11504 } 11528 }
11505 11529
11506 11530
11507 MaybeObject* SymbolTable::LookupSubStringAsciiSymbol(Handle<SeqAsciiString> str, 11531 MaybeObject* SymbolTable::LookupSubStringAsciiSymbol(Handle<SeqAsciiString> str,
11508 int from, 11532 int from,
11509 int length, 11533 int length,
11510 Object** s) { 11534 Object** s) {
11511 SubStringAsciiSymbolKey key(str, from, length); 11535 SubStringAsciiSymbolKey key(str, from, length, GetHeap()->StringHashSeed());
11512 return LookupKey(&key, s); 11536 return LookupKey(&key, s);
11513 } 11537 }
11514 11538
11515 11539
11516 MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str, 11540 MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str,
11517 Object** s) { 11541 Object** s) {
11518 TwoByteSymbolKey key(str); 11542 TwoByteSymbolKey key(str, GetHeap()->StringHashSeed());
11519 return LookupKey(&key, s); 11543 return LookupKey(&key, s);
11520 } 11544 }
11521 11545
11522 MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) { 11546 MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
11523 int entry = FindEntry(key); 11547 int entry = FindEntry(key);
11524 11548
11525 // Symbol already in table. 11549 // Symbol already in table.
11526 if (entry != kNotFound) { 11550 if (entry != kNotFound) {
11527 *s = KeyAt(entry); 11551 *s = KeyAt(entry);
11528 return this; 11552 return this;
(...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after
12572 if (break_point_objects()->IsUndefined()) return 0; 12596 if (break_point_objects()->IsUndefined()) return 0;
12573 // Single break point. 12597 // Single break point.
12574 if (!break_point_objects()->IsFixedArray()) return 1; 12598 if (!break_point_objects()->IsFixedArray()) return 1;
12575 // Multiple break points. 12599 // Multiple break points.
12576 return FixedArray::cast(break_point_objects())->length(); 12600 return FixedArray::cast(break_point_objects())->length();
12577 } 12601 }
12578 #endif // ENABLE_DEBUGGER_SUPPORT 12602 #endif // ENABLE_DEBUGGER_SUPPORT
12579 12603
12580 12604
12581 } } // namespace v8::internal 12605 } } // namespace v8::internal
OLDNEW
« src/mips/code-stubs-mips.cc ('K') | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698