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

Side by Side Diff: src/objects.cc

Issue 7477045: Tentative implementation of string slices (hidden under the flag --string-slices). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Implemented some changes suggested by Anton. Created 9 years, 4 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 715 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 return true; // An MP3File, an M. 726 return true; // An MP3File, an M.
727 } 727 }
728 return false; 728 return false;
729 } 729 }
730 730
731 731
732 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) { 732 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) {
733 #ifdef DEBUG 733 #ifdef DEBUG
734 // Do not attempt to flatten in debug mode when allocation is not 734 // Do not attempt to flatten in debug mode when allocation is not
735 // allowed. This is to avoid an assertion failure when allocating. 735 // allowed. This is to avoid an assertion failure when allocating.
736 // Flattening strings is the only case where we always allow 736 // Flattening and truncating strings are the only cases where we always
737 // allocation because no GC is performed if the allocation fails. 737 // allow allocation because no GC is performed if the allocation fails.
738 if (!HEAP->IsAllocationAllowed()) return this; 738 if (!HEAP->IsAllocationAllowed()) return this;
739 #endif 739 #endif
740 740
741 ASSERT(StringShape(this).representation_tag() == kConsStringTag);
742
741 Heap* heap = GetHeap(); 743 Heap* heap = GetHeap();
742 switch (StringShape(this).representation_tag()) { 744 ConsString* cs = ConsString::cast(this);
743 case kConsStringTag: { 745 // There's little point in putting the flat string in new space if the
744 ConsString* cs = ConsString::cast(this); 746 // cons string is in old space. It can never get GCed until there is
745 if (cs->second()->length() == 0) { 747 // an old space GC.
746 return cs->first(); 748 PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED;
747 } 749 int len = length();
748 // There's little point in putting the flat string in new space if the 750 Object* object;
749 // cons string is in old space. It can never get GCed until there is 751 String* result;
750 // an old space GC. 752 if (IsAsciiRepresentation()) {
751 PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED; 753 { MaybeObject* maybe_object = heap->AllocateRawAsciiString(len, tenure);
752 int len = length(); 754 if (!maybe_object->ToObject(&object)) return maybe_object;
753 Object* object;
754 String* result;
755 if (IsAsciiRepresentation()) {
756 { MaybeObject* maybe_object = heap->AllocateRawAsciiString(len, tenure);
757 if (!maybe_object->ToObject(&object)) return maybe_object;
758 }
759 result = String::cast(object);
760 String* first = cs->first();
761 int first_length = first->length();
762 char* dest = SeqAsciiString::cast(result)->GetChars();
763 WriteToFlat(first, dest, 0, first_length);
764 String* second = cs->second();
765 WriteToFlat(second,
766 dest + first_length,
767 0,
768 len - first_length);
769 } else {
770 { MaybeObject* maybe_object =
771 heap->AllocateRawTwoByteString(len, tenure);
772 if (!maybe_object->ToObject(&object)) return maybe_object;
773 }
774 result = String::cast(object);
775 uc16* dest = SeqTwoByteString::cast(result)->GetChars();
776 String* first = cs->first();
777 int first_length = first->length();
778 WriteToFlat(first, dest, 0, first_length);
779 String* second = cs->second();
780 WriteToFlat(second,
781 dest + first_length,
782 0,
783 len - first_length);
784 }
785 cs->set_first(result);
786 cs->set_second(heap->empty_string());
787 return result;
788 } 755 }
789 default: 756 result = String::cast(object);
790 return this; 757 String* first = cs->first();
758 int first_length = first->length();
759 char* dest = SeqAsciiString::cast(result)->GetChars();
760 WriteToFlat(first, dest, 0, first_length);
761 String* second = cs->second();
762 WriteToFlat(second,
763 dest + first_length,
764 0,
765 len - first_length);
766 } else {
767 { MaybeObject* maybe_object =
768 heap->AllocateRawTwoByteString(len, tenure);
769 if (!maybe_object->ToObject(&object)) return maybe_object;
770 }
771 result = String::cast(object);
772 uc16* dest = SeqTwoByteString::cast(result)->GetChars();
773 String* first = cs->first();
774 int first_length = first->length();
775 WriteToFlat(first, dest, 0, first_length);
776 String* second = cs->second();
777 WriteToFlat(second,
778 dest + first_length,
779 0,
780 len - first_length);
791 } 781 }
782 cs->set_first(result);
783 cs->set_second(heap->empty_string());
784 ASSERT(this->IsFlat());
785 return result;
792 } 786 }
793 787
794 788
789 MaybeObject* String::SlowTryTruncate(PretenureFlag pretenure) {
790 #ifdef DEBUG
791 // Do not attempt to truncate in debug mode when allocation is not
792 // allowed. This is to avoid an assertion failure when allocating.
793 // Flattening and truncating strings are the only cases where we always
794 // allow allocation because no GC is performed if the allocation fails.
795 if (!HEAP->IsAllocationAllowed()) return this;
796 #endif
797 ASSERT(StringShape(this).representation_tag() == kSlicedStringTag);
798
799 Heap* heap = GetHeap();
800 SlicedString* slice = SlicedString::cast(this);
801 // There's little point in putting the truncated string in new space if the
802 // sliced string is in old space. It can never get GCed until there is
803 // an old space GC.
804 PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED;
805 int len = length();
806 int offset = slice->offset();
807 Object* object;
808 String* result;
809 if (IsAsciiRepresentation()) {
810 { MaybeObject* maybe_object = heap->AllocateRawAsciiString(len, tenure);
811 if (!maybe_object->ToObject(&object)) return maybe_object;
812 }
813 result = String::cast(object);
814 String* parent = slice->parent();
815 ASSERT(StringShape(parent).IsSequentialAscii());
816 WriteToFlat(parent, SeqAsciiString::cast(result)->GetChars(),
817 offset, offset + len);
818 } else {
819 { MaybeObject* maybe_object =
820 heap->AllocateRawTwoByteString(len, tenure);
821 if (!maybe_object->ToObject(&object)) return maybe_object;
822 }
823 result = String::cast(object);
824 String* parent = slice->parent();
825 ASSERT(StringShape(parent).IsSequentialTwoByte());
826 WriteToFlat(parent, SeqTwoByteString::cast(result)->GetChars(),
827 offset, offset + len);
828 }
829 slice->set_parent(result);
830 slice->set_offset(0);
831 return result;
832 }
833
834
795 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { 835 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
796 // Externalizing twice leaks the external resource, so it's 836 // Externalizing twice leaks the external resource, so it's
797 // prohibited by the API. 837 // prohibited by the API.
798 ASSERT(!this->IsExternalString()); 838 ASSERT(!this->IsExternalString());
799 #ifdef DEBUG 839 #ifdef DEBUG
800 if (FLAG_enable_slow_asserts) { 840 if (FLAG_enable_slow_asserts) {
801 // Assert that the resource and the string are equivalent. 841 // Assert that the resource and the string are equivalent.
802 ASSERT(static_cast<size_t>(this->length()) == resource->length()); 842 ASSERT(static_cast<size_t>(this->length()) == resource->length());
803 ScopedVector<uc16> smart_chars(this->length()); 843 ScopedVector<uc16> smart_chars(this->length());
804 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); 844 String::WriteToFlat(this, smart_chars.start(), 0, this->length());
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
1162 ObjectVisitor* v) { 1202 ObjectVisitor* v) {
1163 // Avoiding <Type>::cast(this) because it accesses the map pointer field. 1203 // Avoiding <Type>::cast(this) because it accesses the map pointer field.
1164 // During GC, the map pointer field is encoded. 1204 // During GC, the map pointer field is encoded.
1165 if (type < FIRST_NONSTRING_TYPE) { 1205 if (type < FIRST_NONSTRING_TYPE) {
1166 switch (type & kStringRepresentationMask) { 1206 switch (type & kStringRepresentationMask) {
1167 case kSeqStringTag: 1207 case kSeqStringTag:
1168 break; 1208 break;
1169 case kConsStringTag: 1209 case kConsStringTag:
1170 ConsString::BodyDescriptor::IterateBody(this, v); 1210 ConsString::BodyDescriptor::IterateBody(this, v);
1171 break; 1211 break;
1212 case kSlicedStringTag:
1213 SlicedString::BodyDescriptor::IterateBody(this, v);
1214 break;
1172 case kExternalStringTag: 1215 case kExternalStringTag:
1173 if ((type & kStringEncodingMask) == kAsciiStringTag) { 1216 if ((type & kStringEncodingMask) == kAsciiStringTag) {
1174 reinterpret_cast<ExternalAsciiString*>(this)-> 1217 reinterpret_cast<ExternalAsciiString*>(this)->
1175 ExternalAsciiStringIterateBody(v); 1218 ExternalAsciiStringIterateBody(v);
1176 } else { 1219 } else {
1177 reinterpret_cast<ExternalTwoByteString*>(this)-> 1220 reinterpret_cast<ExternalTwoByteString*>(this)->
1178 ExternalTwoByteStringIterateBody(v); 1221 ExternalTwoByteStringIterateBody(v);
1179 } 1222 }
1180 break; 1223 break;
1181 } 1224 }
(...skipping 4056 matching lines...) Expand 10 before | Expand all | Expand 10 after
5238 5281
5239 int offset = 0; 5282 int offset = 0;
5240 int length = this->length(); 5283 int length = this->length();
5241 StringRepresentationTag string_tag = StringShape(this).representation_tag(); 5284 StringRepresentationTag string_tag = StringShape(this).representation_tag();
5242 String* string = this; 5285 String* string = this;
5243 if (string_tag == kConsStringTag) { 5286 if (string_tag == kConsStringTag) {
5244 ConsString* cons = ConsString::cast(string); 5287 ConsString* cons = ConsString::cast(string);
5245 ASSERT(cons->second()->length() == 0); 5288 ASSERT(cons->second()->length() == 0);
5246 string = cons->first(); 5289 string = cons->first();
5247 string_tag = StringShape(string).representation_tag(); 5290 string_tag = StringShape(string).representation_tag();
5291 ASSERT(string_tag != kConsStringTag);
5248 } 5292 }
5249 if (string_tag == kSeqStringTag) { 5293 if (string_tag == kSlicedStringTag) {
5250 SeqAsciiString* seq = SeqAsciiString::cast(string); 5294 // Note that the parent of a slice cannot be a cons.
5251 char* start = seq->GetChars(); 5295 SlicedString* slice = SlicedString::cast(string);
5296 offset = slice->offset();
5297 string = slice->parent();
5298 }
5299 if (string_tag == kExternalStringTag) {
5300 ExternalAsciiString* ext = ExternalAsciiString::cast(string);
5301 const char* start = ext->resource()->data();
5252 return Vector<const char>(start + offset, length); 5302 return Vector<const char>(start + offset, length);
5253 } 5303 }
5254 ASSERT(string_tag == kExternalStringTag); 5304 ASSERT(StringShape(string).representation_tag() == kSeqStringTag);
5255 ExternalAsciiString* ext = ExternalAsciiString::cast(string); 5305 SeqAsciiString* seq = SeqAsciiString::cast(string);
5256 const char* start = ext->resource()->data(); 5306 char* start = seq->GetChars();
5257 return Vector<const char>(start + offset, length); 5307 return Vector<const char>(start + offset, length);
5258 } 5308 }
5259 5309
5260 5310
5261 Vector<const uc16> String::ToUC16Vector() { 5311 Vector<const uc16> String::ToUC16Vector() {
5262 ASSERT(IsTwoByteRepresentation()); 5312 ASSERT(IsTwoByteRepresentation());
5263 ASSERT(IsFlat()); 5313 ASSERT(IsFlat());
5264 5314
5265 int offset = 0; 5315 int offset = 0;
5266 int length = this->length(); 5316 int length = this->length();
5267 StringRepresentationTag string_tag = StringShape(this).representation_tag(); 5317 StringRepresentationTag string_tag = StringShape(this).representation_tag();
5268 String* string = this; 5318 String* string = this;
5269 if (string_tag == kConsStringTag) { 5319 if (string_tag == kConsStringTag) {
5270 ConsString* cons = ConsString::cast(string); 5320 ConsString* cons = ConsString::cast(string);
5271 ASSERT(cons->second()->length() == 0); 5321 ASSERT(cons->second()->length() == 0);
5272 string = cons->first(); 5322 string = cons->first();
5273 string_tag = StringShape(string).representation_tag(); 5323 string_tag = StringShape(string).representation_tag();
5324 ASSERT(string_tag != kConsStringTag);
5274 } 5325 }
5275 if (string_tag == kSeqStringTag) { 5326 if (string_tag == kSlicedStringTag) {
5276 SeqTwoByteString* seq = SeqTwoByteString::cast(string); 5327 // Note that the parent of a slice cannot be a cons.
5277 return Vector<const uc16>(seq->GetChars() + offset, length); 5328 SlicedString* slice = SlicedString::cast(string);
5329 offset = slice->offset();
5330 string = slice->parent();
5278 } 5331 }
5279 ASSERT(string_tag == kExternalStringTag); 5332 if (string_tag == kExternalStringTag) {
5280 ExternalTwoByteString* ext = ExternalTwoByteString::cast(string); 5333 ExternalTwoByteString* ext = ExternalTwoByteString::cast(string);
5281 const uc16* start = 5334 const uc16* start =
5282 reinterpret_cast<const uc16*>(ext->resource()->data()); 5335 reinterpret_cast<const uc16*>(ext->resource()->data());
5283 return Vector<const uc16>(start + offset, length); 5336 return Vector<const uc16>(start + offset, length);
5337 }
5338 ASSERT(StringShape(string).representation_tag() == kSeqStringTag);
5339 SeqTwoByteString* seq = SeqTwoByteString::cast(string);
5340 return Vector<const uc16>(seq->GetChars() + offset, length);
5284 } 5341 }
5285 5342
5286 5343
5287 SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls, 5344 SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
5288 RobustnessFlag robust_flag, 5345 RobustnessFlag robust_flag,
5289 int offset, 5346 int offset,
5290 int length, 5347 int length,
5291 int* length_return) { 5348 int* length_return) {
5292 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { 5349 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
5293 return SmartPointer<char>(NULL); 5350 return SmartPointer<char>(NULL);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
5351 5408
5352 5409
5353 const uc16* String::GetTwoByteData(unsigned start) { 5410 const uc16* String::GetTwoByteData(unsigned start) {
5354 ASSERT(!IsAsciiRepresentation()); 5411 ASSERT(!IsAsciiRepresentation());
5355 switch (StringShape(this).representation_tag()) { 5412 switch (StringShape(this).representation_tag()) {
5356 case kSeqStringTag: 5413 case kSeqStringTag:
5357 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start); 5414 return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
5358 case kExternalStringTag: 5415 case kExternalStringTag:
5359 return ExternalTwoByteString::cast(this)-> 5416 return ExternalTwoByteString::cast(this)->
5360 ExternalTwoByteStringGetData(start); 5417 ExternalTwoByteStringGetData(start);
5418 case kSlicedStringTag: {
5419 SlicedString* slice = SlicedString::cast(this);
5420 return slice->parent()->GetTwoByteData(start + slice->offset());
5421 }
5361 case kConsStringTag: 5422 case kConsStringTag:
5362 UNREACHABLE(); 5423 UNREACHABLE();
5363 return NULL; 5424 return NULL;
5364 } 5425 }
5365 UNREACHABLE(); 5426 UNREACHABLE();
5366 return NULL; 5427 return NULL;
5367 } 5428 }
5368 5429
5369 5430
5370 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { 5431 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
5641 &rbb->remaining, 5702 &rbb->remaining,
5642 offset_ptr, 5703 offset_ptr,
5643 max_chars); 5704 max_chars);
5644 } else { 5705 } else {
5645 ExternalTwoByteString::cast(input)-> 5706 ExternalTwoByteString::cast(input)->
5646 ExternalTwoByteStringReadBlockIntoBuffer(rbb, 5707 ExternalTwoByteStringReadBlockIntoBuffer(rbb,
5647 offset_ptr, 5708 offset_ptr,
5648 max_chars); 5709 max_chars);
5649 return rbb->util_buffer; 5710 return rbb->util_buffer;
5650 } 5711 }
5712 case kSlicedStringTag:
5713 return SlicedString::cast(input)->SlicedStringReadBlock(rbb,
5714 offset_ptr,
5715 max_chars);
5651 default: 5716 default:
5652 break; 5717 break;
5653 } 5718 }
5654 5719
5655 UNREACHABLE(); 5720 UNREACHABLE();
5656 return 0; 5721 return 0;
5657 } 5722 }
5658 5723
5659 5724
5660 void Relocatable::PostGarbageCollectionProcessing() { 5725 void Relocatable::PostGarbageCollectionProcessing() {
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
5782 if (input->IsAsciiRepresentation()) { 5847 if (input->IsAsciiRepresentation()) {
5783 ExternalAsciiString::cast(input)-> 5848 ExternalAsciiString::cast(input)->
5784 ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars); 5849 ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
5785 } else { 5850 } else {
5786 ExternalTwoByteString::cast(input)-> 5851 ExternalTwoByteString::cast(input)->
5787 ExternalTwoByteStringReadBlockIntoBuffer(rbb, 5852 ExternalTwoByteStringReadBlockIntoBuffer(rbb,
5788 offset_ptr, 5853 offset_ptr,
5789 max_chars); 5854 max_chars);
5790 } 5855 }
5791 return; 5856 return;
5857 case kSlicedStringTag:
5858 SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb,
5859 offset_ptr,
5860 max_chars);
5861 return;
5792 default: 5862 default:
5793 break; 5863 break;
5794 } 5864 }
5795 5865
5796 UNREACHABLE(); 5866 UNREACHABLE();
5797 return; 5867 return;
5798 } 5868 }
5799 5869
5800 5870
5801 const unibrow::byte* String::ReadBlock(String* input, 5871 const unibrow::byte* String::ReadBlock(String* input,
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
5916 } else { 5986 } else {
5917 return string->Get(index); 5987 return string->Get(index);
5918 } 5988 }
5919 } 5989 }
5920 5990
5921 UNREACHABLE(); 5991 UNREACHABLE();
5922 return 0; 5992 return 0;
5923 } 5993 }
5924 5994
5925 5995
5996 uint16_t SlicedString::SlicedStringGet(int index) {
5997 return parent()->Get(offset() + index);
5998 }
5999
6000
6001 const unibrow::byte* SlicedString::SlicedStringReadBlock(
6002 ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
6003 unsigned offset = this->offset();
6004 *offset_ptr += offset;
6005 const unibrow::byte* answer = String::ReadBlock(String::cast(parent()),
6006 buffer, offset_ptr, chars);
6007 *offset_ptr -= offset;
6008 return answer;
6009 }
6010
6011
6012 void SlicedString::SlicedStringReadBlockIntoBuffer(
6013 ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
6014 unsigned offset = this->offset();
6015 *offset_ptr += offset;
6016 String::ReadBlockIntoBuffer(String::cast(parent()),
6017 buffer, offset_ptr, chars);
6018 *offset_ptr -= offset;
6019 }
6020
5926 template <typename sinkchar> 6021 template <typename sinkchar>
5927 void String::WriteToFlat(String* src, 6022 void String::WriteToFlat(String* src,
5928 sinkchar* sink, 6023 sinkchar* sink,
5929 int f, 6024 int f,
5930 int t) { 6025 int t) {
5931 String* source = src; 6026 String* source = src;
5932 int from = f; 6027 int from = f;
5933 int to = t; 6028 int to = t;
5934 while (true) { 6029 while (true) {
5935 ASSERT(0 <= from && from <= to && to <= source->length()); 6030 ASSERT(0 <= from && from <= to && to <= source->length());
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
5983 WriteToFlat(second, 6078 WriteToFlat(second,
5984 sink + boundary - from, 6079 sink + boundary - from,
5985 0, 6080 0,
5986 to - boundary); 6081 to - boundary);
5987 to = boundary; 6082 to = boundary;
5988 } 6083 }
5989 source = first; 6084 source = first;
5990 } 6085 }
5991 break; 6086 break;
5992 } 6087 }
6088 case kAsciiStringTag | kSlicedStringTag:
6089 case kTwoByteStringTag | kSlicedStringTag: {
6090 SlicedString* slice = SlicedString::cast(source);
6091 unsigned offset = slice->offset();
6092 WriteToFlat(slice->parent(), sink, from + offset, to + offset);
6093 return;
6094 }
5993 } 6095 }
5994 } 6096 }
5995 } 6097 }
5996 6098
5997 6099
5998 template <typename IteratorA, typename IteratorB> 6100 template <typename IteratorA, typename IteratorB>
5999 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) { 6101 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
6000 // General slow case check. We know that the ia and ib iterators 6102 // General slow case check. We know that the ia and ib iterators
6001 // have the same length. 6103 // have the same length.
6002 while (ia->has_more()) { 6104 while (ia->has_more()) {
(...skipping 5935 matching lines...) Expand 10 before | Expand all | Expand 10 after
11938 if (break_point_objects()->IsUndefined()) return 0; 12040 if (break_point_objects()->IsUndefined()) return 0;
11939 // Single beak point. 12041 // Single beak point.
11940 if (!break_point_objects()->IsFixedArray()) return 1; 12042 if (!break_point_objects()->IsFixedArray()) return 1;
11941 // Multiple break points. 12043 // Multiple break points.
11942 return FixedArray::cast(break_point_objects())->length(); 12044 return FixedArray::cast(break_point_objects())->length();
11943 } 12045 }
11944 #endif 12046 #endif
11945 12047
11946 12048
11947 } } // namespace v8::internal 12049 } } // namespace v8::internal
OLDNEW
« src/objects.h ('K') | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698