| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 return true; // An Ape, an ABCBook. | 580 return true; // An Ape, an ABCBook. |
| 581 } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) && | 581 } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) && |
| 582 (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' || | 582 (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' || |
| 583 c0 == 'S' || c0 == 'X')) { | 583 c0 == 'S' || c0 == 'X')) { |
| 584 return true; // An MP3File, an M. | 584 return true; // An MP3File, an M. |
| 585 } | 585 } |
| 586 return false; | 586 return false; |
| 587 } | 587 } |
| 588 | 588 |
| 589 | 589 |
| 590 Object* String::Flatten(StringShape shape) { | 590 Object* String::TryFlatten(StringShape shape) { |
| 591 #ifdef DEBUG | 591 #ifdef DEBUG |
| 592 // Do not attempt to flatten in debug mode when allocation is not | 592 // Do not attempt to flatten in debug mode when allocation is not |
| 593 // allowed. This is to avoid an assertion failure when allocating. | 593 // allowed. This is to avoid an assertion failure when allocating. |
| 594 // Flattening strings is the only case where we always allow | 594 // Flattening strings is the only case where we always allow |
| 595 // allocation because no GC is performed if the allocation fails. | 595 // allocation because no GC is performed if the allocation fails. |
| 596 if (!Heap::IsAllocationAllowed()) return this; | 596 if (!Heap::IsAllocationAllowed()) return this; |
| 597 #endif | 597 #endif |
| 598 | 598 |
| 599 switch (shape.representation_tag()) { | 599 switch (shape.representation_tag()) { |
| 600 case kSlicedStringTag: { | 600 case kSlicedStringTag: { |
| 601 SlicedString* ss = SlicedString::cast(this); | 601 SlicedString* ss = SlicedString::cast(this); |
| 602 // The SlicedString constructor should ensure that there are no | 602 // The SlicedString constructor should ensure that there are no |
| 603 // SlicedStrings that are constructed directly on top of other | 603 // SlicedStrings that are constructed directly on top of other |
| 604 // SlicedStrings. | 604 // SlicedStrings. |
| 605 String* buf = ss->buffer(); | 605 String* buf = ss->buffer(); |
| 606 ASSERT(!buf->IsSlicedString()); | 606 ASSERT(!buf->IsSlicedString()); |
| 607 Object* ok = buf->Flatten(StringShape(buf)); | 607 Object* ok = buf->TryFlatten(StringShape(buf)); |
| 608 if (ok->IsFailure()) return ok; | 608 if (ok->IsFailure()) return ok; |
| 609 // Under certain circumstances (TryFlatten fails in String::Slice) | 609 // Under certain circumstances (TryFlattenIfNotFlat fails in |
| 610 // we can have a cons string under a slice. In this case we need | 610 // String::Slice) we can have a cons string under a slice. |
| 611 // to get the flat string out of the cons! | 611 // In this case we need to get the flat string out of the cons! |
| 612 if (StringShape(String::cast(ok)).IsCons()) { | 612 if (StringShape(String::cast(ok)).IsCons()) { |
| 613 ss->set_buffer(ConsString::cast(ok)->first()); | 613 ss->set_buffer(ConsString::cast(ok)->first()); |
| 614 } | 614 } |
| 615 return this; | 615 return this; |
| 616 } | 616 } |
| 617 case kConsStringTag: { | 617 case kConsStringTag: { |
| 618 ConsString* cs = ConsString::cast(this); | 618 ConsString* cs = ConsString::cast(this); |
| 619 if (cs->second()->length() == 0) { | 619 if (cs->second()->length() == 0) { |
| 620 return this; | 620 return this; |
| 621 } | 621 } |
| (...skipping 1318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1940 } else { | 1940 } else { |
| 1941 int byte_array_length = ByteArray::LengthFor(instance_size_delta); | 1941 int byte_array_length = ByteArray::LengthFor(instance_size_delta); |
| 1942 int byte_array_length_offset = new_instance_size + kPointerSize; | 1942 int byte_array_length_offset = new_instance_size + kPointerSize; |
| 1943 WRITE_FIELD(this, new_instance_size, Heap::byte_array_map()); | 1943 WRITE_FIELD(this, new_instance_size, Heap::byte_array_map()); |
| 1944 WRITE_INT_FIELD(this, byte_array_length_offset, byte_array_length); | 1944 WRITE_INT_FIELD(this, byte_array_length_offset, byte_array_length); |
| 1945 } | 1945 } |
| 1946 WRITE_BARRIER(this, new_instance_size); | 1946 WRITE_BARRIER(this, new_instance_size); |
| 1947 } | 1947 } |
| 1948 new_map->set_unused_property_fields(0); | 1948 new_map->set_unused_property_fields(0); |
| 1949 | 1949 |
| 1950 // We have now sucessfully allocated all the necessary objects. | 1950 // We have now successfully allocated all the necessary objects. |
| 1951 // Changes can now be made with the guarantee that all of them take effect. | 1951 // Changes can now be made with the guarantee that all of them take effect. |
| 1952 set_map(new_map); | 1952 set_map(new_map); |
| 1953 map()->set_instance_descriptors(Heap::empty_descriptor_array()); | 1953 map()->set_instance_descriptors(Heap::empty_descriptor_array()); |
| 1954 | 1954 |
| 1955 set_properties(dictionary); | 1955 set_properties(dictionary); |
| 1956 | 1956 |
| 1957 Counters::props_to_dictionary.Increment(); | 1957 Counters::props_to_dictionary.Increment(); |
| 1958 | 1958 |
| 1959 #ifdef DEBUG | 1959 #ifdef DEBUG |
| 1960 if (FLAG_trace_normalization) { | 1960 if (FLAG_trace_normalization) { |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2406 // interceptor calls. | 2406 // interceptor calls. |
| 2407 AssertNoContextChange ncc; | 2407 AssertNoContextChange ncc; |
| 2408 | 2408 |
| 2409 // Check access rights if needed. | 2409 // Check access rights if needed. |
| 2410 if (IsAccessCheckNeeded() && | 2410 if (IsAccessCheckNeeded() && |
| 2411 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 2411 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 2412 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 2412 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 2413 return Heap::undefined_value(); | 2413 return Heap::undefined_value(); |
| 2414 } | 2414 } |
| 2415 | 2415 |
| 2416 // TryFlatten before operating on the string. | 2416 // Try to flatten before operating on the string. |
| 2417 name->TryFlatten(StringShape(name)); | 2417 name->TryFlattenIfNotFlat(StringShape(name)); |
| 2418 | 2418 |
| 2419 // Make sure name is not an index. | 2419 // Make sure name is not an index. |
| 2420 uint32_t index; | 2420 uint32_t index; |
| 2421 if (name->AsArrayIndex(&index)) return Heap::undefined_value(); | 2421 if (name->AsArrayIndex(&index)) return Heap::undefined_value(); |
| 2422 | 2422 |
| 2423 // Check if there is an API defined callback object which prohibits | 2423 // Check if there is an API defined callback object which prohibits |
| 2424 // callback overwriting in this object or it's prototype chain. | 2424 // callback overwriting in this object or it's prototype chain. |
| 2425 // This mechanism is needed for instance in a browser setting, where | 2425 // This mechanism is needed for instance in a browser setting, where |
| 2426 // certain accessors such as window.location should not be allowed | 2426 // certain accessors such as window.location should not be allowed |
| 2427 // to be overwriten because allowing overwriting could potentially | 2427 // to be overwritten because allowing overwriting could potentially |
| 2428 // cause security problems. | 2428 // cause security problems. |
| 2429 LookupResult callback_result; | 2429 LookupResult callback_result; |
| 2430 LookupCallback(name, &callback_result); | 2430 LookupCallback(name, &callback_result); |
| 2431 if (callback_result.IsValid()) { | 2431 if (callback_result.IsValid()) { |
| 2432 Object* obj = callback_result.GetCallbackObject(); | 2432 Object* obj = callback_result.GetCallbackObject(); |
| 2433 if (obj->IsAccessorInfo() && | 2433 if (obj->IsAccessorInfo() && |
| 2434 AccessorInfo::cast(obj)->prohibits_overwriting()) { | 2434 AccessorInfo::cast(obj)->prohibits_overwriting()) { |
| 2435 return Heap::undefined_value(); | 2435 return Heap::undefined_value(); |
| 2436 } | 2436 } |
| 2437 } | 2437 } |
| (...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3058 } | 3058 } |
| 3059 | 3059 |
| 3060 | 3060 |
| 3061 int String::Utf8Length() { | 3061 int String::Utf8Length() { |
| 3062 StringShape shape(this); | 3062 StringShape shape(this); |
| 3063 if (shape.IsAsciiRepresentation()) return length(shape); | 3063 if (shape.IsAsciiRepresentation()) return length(shape); |
| 3064 // Attempt to flatten before accessing the string. It probably | 3064 // Attempt to flatten before accessing the string. It probably |
| 3065 // doesn't make Utf8Length faster, but it is very likely that | 3065 // doesn't make Utf8Length faster, but it is very likely that |
| 3066 // the string will be accessed later (for example by WriteUtf8) | 3066 // the string will be accessed later (for example by WriteUtf8) |
| 3067 // so it's still a good idea. | 3067 // so it's still a good idea. |
| 3068 if (!IsFlat(shape)) { | 3068 TryFlattenIfNotFlat(shape); // shape is now no longer valid. |
| 3069 TryFlatten(shape); // shape is now no longer valid. | |
| 3070 } | |
| 3071 Access<StringInputBuffer> buffer(&string_input_buffer); | 3069 Access<StringInputBuffer> buffer(&string_input_buffer); |
| 3072 buffer->Reset(0, this); | 3070 buffer->Reset(0, this); |
| 3073 int result = 0; | 3071 int result = 0; |
| 3074 while (buffer->has_more()) | 3072 while (buffer->has_more()) |
| 3075 result += unibrow::Utf8::Length(buffer->GetNext()); | 3073 result += unibrow::Utf8::Length(buffer->GetNext()); |
| 3076 return result; | 3074 return result; |
| 3077 } | 3075 } |
| 3078 | 3076 |
| 3079 | 3077 |
| 3080 Vector<const char> String::ToAsciiVector() { | 3078 Vector<const char> String::ToAsciiVector() { |
| (...skipping 2072 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5153 JSArray* array = JSArray::cast(this); | 5151 JSArray* array = JSArray::cast(this); |
| 5154 Object* return_value = array->JSArrayUpdateLengthFromIndex(index, value); | 5152 Object* return_value = array->JSArrayUpdateLengthFromIndex(index, value); |
| 5155 if (return_value->IsFailure()) return return_value; | 5153 if (return_value->IsFailure()) return return_value; |
| 5156 } | 5154 } |
| 5157 | 5155 |
| 5158 // Attempt to put this object back in fast case. | 5156 // Attempt to put this object back in fast case. |
| 5159 if (ShouldConvertToFastElements()) { | 5157 if (ShouldConvertToFastElements()) { |
| 5160 uint32_t new_length = 0; | 5158 uint32_t new_length = 0; |
| 5161 if (IsJSArray()) { | 5159 if (IsJSArray()) { |
| 5162 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &new_length)); | 5160 CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &new_length)); |
| 5161 JSArray::cast(this)->set_length(Smi::FromInt(new_length)); |
| 5163 } else { | 5162 } else { |
| 5164 new_length = Dictionary::cast(elements())->max_number_key() + 1; | 5163 new_length = Dictionary::cast(elements())->max_number_key() + 1; |
| 5165 } | 5164 } |
| 5166 Object* obj = Heap::AllocateFixedArrayWithHoles(new_length); | 5165 Object* obj = Heap::AllocateFixedArrayWithHoles(new_length); |
| 5167 if (obj->IsFailure()) return obj; | 5166 if (obj->IsFailure()) return obj; |
| 5168 SetFastElements(FixedArray::cast(obj)); | 5167 SetFastElements(FixedArray::cast(obj)); |
| 5169 #ifdef DEBUG | 5168 #ifdef DEBUG |
| 5170 if (FLAG_trace_normalization) { | 5169 if (FLAG_trace_normalization) { |
| 5171 PrintF("Object elements are fast case again:\n"); | 5170 PrintF("Object elements are fast case again:\n"); |
| 5172 Print(); | 5171 Print(); |
| (...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5688 } else { | 5687 } else { |
| 5689 HeapSortPairs(this, smis); | 5688 HeapSortPairs(this, smis); |
| 5690 return; | 5689 return; |
| 5691 } | 5690 } |
| 5692 } | 5691 } |
| 5693 | 5692 |
| 5694 | 5693 |
| 5695 // Fill in the names of local properties into the supplied storage. The main | 5694 // Fill in the names of local properties into the supplied storage. The main |
| 5696 // purpose of this function is to provide reflection information for the object | 5695 // purpose of this function is to provide reflection information for the object |
| 5697 // mirrors. | 5696 // mirrors. |
| 5698 void JSObject::GetLocalPropertyNames(FixedArray* storage) { | 5697 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) { |
| 5699 ASSERT(storage->length() == | 5698 ASSERT(storage->length() >= |
| 5700 NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE))); | 5699 NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE)) - |
| 5701 int index = 0; | 5700 index); |
| 5702 if (HasFastProperties()) { | 5701 if (HasFastProperties()) { |
| 5703 for (DescriptorReader r(map()->instance_descriptors()); | 5702 for (DescriptorReader r(map()->instance_descriptors()); |
| 5704 !r.eos(); | 5703 !r.eos(); |
| 5705 r.advance()) { | 5704 r.advance()) { |
| 5706 if (!r.IsTransition()) { | 5705 if (!r.IsTransition()) { |
| 5707 storage->set(index++, r.GetKey()); | 5706 storage->set(index++, r.GetKey()); |
| 5708 } | 5707 } |
| 5709 } | 5708 } |
| 5710 ASSERT(storage->length() == index); | 5709 ASSERT(storage->length() >= index); |
| 5711 } else { | 5710 } else { |
| 5712 property_dictionary()->CopyKeysTo(storage); | 5711 property_dictionary()->CopyKeysTo(storage); |
| 5713 } | 5712 } |
| 5714 } | 5713 } |
| 5715 | 5714 |
| 5716 | 5715 |
| 5717 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { | 5716 int JSObject::NumberOfLocalElements(PropertyAttributes filter) { |
| 5718 return GetLocalElementKeys(NULL, filter); | 5717 return GetLocalElementKeys(NULL, filter); |
| 5719 } | 5718 } |
| 5720 | 5719 |
| (...skipping 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7015 // No break point. | 7014 // No break point. |
| 7016 if (break_point_objects()->IsUndefined()) return 0; | 7015 if (break_point_objects()->IsUndefined()) return 0; |
| 7017 // Single beak point. | 7016 // Single beak point. |
| 7018 if (!break_point_objects()->IsFixedArray()) return 1; | 7017 if (!break_point_objects()->IsFixedArray()) return 1; |
| 7019 // Multiple break points. | 7018 // Multiple break points. |
| 7020 return FixedArray::cast(break_point_objects())->length(); | 7019 return FixedArray::cast(break_point_objects())->length(); |
| 7021 } | 7020 } |
| 7022 | 7021 |
| 7023 | 7022 |
| 7024 } } // namespace v8::internal | 7023 } } // namespace v8::internal |
| OLD | NEW |