| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 2239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2250 } | 2250 } |
| 2251 new_map->set_unused_property_fields(0); | 2251 new_map->set_unused_property_fields(0); |
| 2252 | 2252 |
| 2253 // We have now successfully allocated all the necessary objects. | 2253 // We have now successfully allocated all the necessary objects. |
| 2254 // Changes can now be made with the guarantee that all of them take effect. | 2254 // Changes can now be made with the guarantee that all of them take effect. |
| 2255 set_map(new_map); | 2255 set_map(new_map); |
| 2256 map()->set_instance_descriptors(Heap::empty_descriptor_array()); | 2256 map()->set_instance_descriptors(Heap::empty_descriptor_array()); |
| 2257 | 2257 |
| 2258 set_properties(dictionary); | 2258 set_properties(dictionary); |
| 2259 | 2259 |
| 2260 Counters::props_to_dictionary.Increment(); | 2260 INC_COUNTER(props_to_dictionary); |
| 2261 | 2261 |
| 2262 #ifdef DEBUG | 2262 #ifdef DEBUG |
| 2263 if (FLAG_trace_normalization) { | 2263 if (FLAG_trace_normalization) { |
| 2264 PrintF("Object properties have been normalized:\n"); | 2264 PrintF("Object properties have been normalized:\n"); |
| 2265 Print(); | 2265 Print(); |
| 2266 } | 2266 } |
| 2267 #endif | 2267 #endif |
| 2268 return this; | 2268 return this; |
| 2269 } | 2269 } |
| 2270 | 2270 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2297 if (!value->IsTheHole()) { | 2297 if (!value->IsTheHole()) { |
| 2298 PropertyDetails details = PropertyDetails(NONE, NORMAL); | 2298 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
| 2299 Object* result = dictionary->AddNumberEntry(i, array->get(i), details); | 2299 Object* result = dictionary->AddNumberEntry(i, array->get(i), details); |
| 2300 if (result->IsFailure()) return result; | 2300 if (result->IsFailure()) return result; |
| 2301 dictionary = NumberDictionary::cast(result); | 2301 dictionary = NumberDictionary::cast(result); |
| 2302 } | 2302 } |
| 2303 } | 2303 } |
| 2304 // Switch to using the dictionary as the backing storage for elements. | 2304 // Switch to using the dictionary as the backing storage for elements. |
| 2305 set_elements(dictionary); | 2305 set_elements(dictionary); |
| 2306 | 2306 |
| 2307 Counters::elements_to_dictionary.Increment(); | 2307 INC_COUNTER(elements_to_dictionary); |
| 2308 | 2308 |
| 2309 #ifdef DEBUG | 2309 #ifdef DEBUG |
| 2310 if (FLAG_trace_normalization) { | 2310 if (FLAG_trace_normalization) { |
| 2311 PrintF("Object elements have been normalized:\n"); | 2311 PrintF("Object elements have been normalized:\n"); |
| 2312 Print(); | 2312 Print(); |
| 2313 } | 2313 } |
| 2314 #endif | 2314 #endif |
| 2315 | 2315 |
| 2316 return this; | 2316 return this; |
| 2317 } | 2317 } |
| (...skipping 1198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3516 if (other->IsEmpty()) return false; | 3516 if (other->IsEmpty()) return false; |
| 3517 if (length() != other->length()) return false; | 3517 if (length() != other->length()) return false; |
| 3518 for (int i = 0; i < length(); ++i) { | 3518 for (int i = 0; i < length(); ++i) { |
| 3519 if (get(i) != other->get(i) && i != kContentArrayIndex) return false; | 3519 if (get(i) != other->get(i) && i != kContentArrayIndex) return false; |
| 3520 } | 3520 } |
| 3521 return GetContentArray()->IsEqualTo(other->GetContentArray()); | 3521 return GetContentArray()->IsEqualTo(other->GetContentArray()); |
| 3522 } | 3522 } |
| 3523 #endif | 3523 #endif |
| 3524 | 3524 |
| 3525 | 3525 |
| 3526 static StaticResource<StringInputBuffer> string_input_buffer; | |
| 3527 | 3526 |
| 3528 | 3527 |
| 3529 bool String::LooksValid() { | 3528 bool String::LooksValid() { |
| 3530 if (!Heap::Contains(this)) return false; | 3529 if (!Heap::Contains(this)) return false; |
| 3531 return true; | 3530 return true; |
| 3532 } | 3531 } |
| 3533 | 3532 |
| 3534 | 3533 |
| 3535 int String::Utf8Length() { | 3534 int String::Utf8Length() { |
| 3536 if (IsAsciiRepresentation()) return length(); | 3535 if (IsAsciiRepresentation()) return length(); |
| 3537 // Attempt to flatten before accessing the string. It probably | 3536 // Attempt to flatten before accessing the string. It probably |
| 3538 // doesn't make Utf8Length faster, but it is very likely that | 3537 // doesn't make Utf8Length faster, but it is very likely that |
| 3539 // the string will be accessed later (for example by WriteUtf8) | 3538 // the string will be accessed later (for example by WriteUtf8) |
| 3540 // so it's still a good idea. | 3539 // so it's still a good idea. |
| 3541 TryFlattenIfNotFlat(); | 3540 TryFlattenIfNotFlat(); |
| 3542 Access<StringInputBuffer> buffer(&string_input_buffer); | 3541 Access<StringInputBuffer> buffer(& |
| 3542 v8_context()->objects_data_.string_input_buffer_); |
| 3543 buffer->Reset(0, this); | 3543 buffer->Reset(0, this); |
| 3544 int result = 0; | 3544 int result = 0; |
| 3545 while (buffer->has_more()) | 3545 while (buffer->has_more()) |
| 3546 result += unibrow::Utf8::Length(buffer->GetNext()); | 3546 result += unibrow::Utf8::Length(buffer->GetNext()); |
| 3547 return result; | 3547 return result; |
| 3548 } | 3548 } |
| 3549 | 3549 |
| 3550 | 3550 |
| 3551 Vector<const char> String::ToAsciiVector() { | 3551 Vector<const char> String::ToAsciiVector() { |
| 3552 ASSERT(IsAsciiRepresentation()); | 3552 ASSERT(IsAsciiRepresentation()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3607 int* length_return) { | 3607 int* length_return) { |
| 3608 ASSERT(NativeAllocationChecker::allocation_allowed()); | 3608 ASSERT(NativeAllocationChecker::allocation_allowed()); |
| 3609 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { | 3609 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { |
| 3610 return SmartPointer<char>(NULL); | 3610 return SmartPointer<char>(NULL); |
| 3611 } | 3611 } |
| 3612 | 3612 |
| 3613 // Negative length means the to the end of the string. | 3613 // Negative length means the to the end of the string. |
| 3614 if (length < 0) length = kMaxInt - offset; | 3614 if (length < 0) length = kMaxInt - offset; |
| 3615 | 3615 |
| 3616 // Compute the size of the UTF-8 string. Start at the specified offset. | 3616 // Compute the size of the UTF-8 string. Start at the specified offset. |
| 3617 Access<StringInputBuffer> buffer(&string_input_buffer); | 3617 Access<StringInputBuffer> buffer(& |
| 3618 v8_context()->objects_data_.string_input_buffer_); |
| 3618 buffer->Reset(offset, this); | 3619 buffer->Reset(offset, this); |
| 3619 int character_position = offset; | 3620 int character_position = offset; |
| 3620 int utf8_bytes = 0; | 3621 int utf8_bytes = 0; |
| 3621 while (buffer->has_more()) { | 3622 while (buffer->has_more()) { |
| 3622 uint16_t character = buffer->GetNext(); | 3623 uint16_t character = buffer->GetNext(); |
| 3623 if (character_position < offset + length) { | 3624 if (character_position < offset + length) { |
| 3624 utf8_bytes += unibrow::Utf8::Length(character); | 3625 utf8_bytes += unibrow::Utf8::Length(character); |
| 3625 } | 3626 } |
| 3626 character_position++; | 3627 character_position++; |
| 3627 } | 3628 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3682 } | 3683 } |
| 3683 | 3684 |
| 3684 | 3685 |
| 3685 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { | 3686 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { |
| 3686 ASSERT(NativeAllocationChecker::allocation_allowed()); | 3687 ASSERT(NativeAllocationChecker::allocation_allowed()); |
| 3687 | 3688 |
| 3688 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { | 3689 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { |
| 3689 return SmartPointer<uc16>(); | 3690 return SmartPointer<uc16>(); |
| 3690 } | 3691 } |
| 3691 | 3692 |
| 3692 Access<StringInputBuffer> buffer(&string_input_buffer); | 3693 Access<StringInputBuffer> buffer(& |
| 3694 v8_context()->objects_data_.string_input_buffer_); |
| 3693 buffer->Reset(this); | 3695 buffer->Reset(this); |
| 3694 | 3696 |
| 3695 uc16* result = NewArray<uc16>(length() + 1); | 3697 uc16* result = NewArray<uc16>(length() + 1); |
| 3696 | 3698 |
| 3697 int i = 0; | 3699 int i = 0; |
| 3698 while (buffer->has_more()) { | 3700 while (buffer->has_more()) { |
| 3699 uint16_t character = buffer->GetNext(); | 3701 uint16_t character = buffer->GetNext(); |
| 3700 result[i++] = character; | 3702 result[i++] = character; |
| 3701 } | 3703 } |
| 3702 result[i] = 0; | 3704 result[i] = 0; |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3964 return rbb->util_buffer; | 3966 return rbb->util_buffer; |
| 3965 } | 3967 } |
| 3966 default: | 3968 default: |
| 3967 break; | 3969 break; |
| 3968 } | 3970 } |
| 3969 | 3971 |
| 3970 UNREACHABLE(); | 3972 UNREACHABLE(); |
| 3971 return 0; | 3973 return 0; |
| 3972 } | 3974 } |
| 3973 | 3975 |
| 3974 | 3976 RelocatableData::RelocatableData() |
| 3975 Relocatable* Relocatable::top_ = NULL; | 3977 :top_(NULL) { |
| 3976 | 3978 } |
| 3977 | 3979 |
| 3978 void Relocatable::PostGarbageCollectionProcessing() { | 3980 void Relocatable::PostGarbageCollectionProcessing() { |
| 3979 Relocatable* current = top_; | 3981 Relocatable* current = v8_context()->relocatable_data_.top_; |
| 3980 while (current != NULL) { | 3982 while (current != NULL) { |
| 3981 current->PostGarbageCollection(); | 3983 current->PostGarbageCollection(); |
| 3982 current = current->prev_; | 3984 current = current->prev_; |
| 3983 } | 3985 } |
| 3984 } | 3986 } |
| 3985 | 3987 |
| 3986 | 3988 |
| 3987 // Reserve space for statics needing saving and restoring. | 3989 // Reserve space for statics needing saving and restoring. |
| 3988 int Relocatable::ArchiveSpacePerThread() { | 3990 int Relocatable::ArchiveSpacePerThread() { |
| 3989 return sizeof(top_); | 3991 return sizeof(RelocatableData); |
| 3990 } | 3992 } |
| 3991 | 3993 |
| 3992 | 3994 |
| 3993 // Archive statics that are thread local. | 3995 // Archive statics that are thread local. |
| 3994 char* Relocatable::ArchiveState(char* to) { | 3996 char* Relocatable::ArchiveState(char* to) { |
| 3995 *reinterpret_cast<Relocatable**>(to) = top_; | 3997 Relocatable*& top = v8_context()->relocatable_data_.top_; |
| 3996 top_ = NULL; | 3998 *reinterpret_cast<Relocatable**>(to) = top; |
| 3999 top = NULL; |
| 3997 return to + ArchiveSpacePerThread(); | 4000 return to + ArchiveSpacePerThread(); |
| 3998 } | 4001 } |
| 3999 | 4002 |
| 4000 | 4003 |
| 4001 // Restore statics that are thread local. | 4004 // Restore statics that are thread local. |
| 4002 char* Relocatable::RestoreState(char* from) { | 4005 char* Relocatable::RestoreState(char* from) { |
| 4003 top_ = *reinterpret_cast<Relocatable**>(from); | 4006 v8_context()->relocatable_data_.top_ = *reinterpret_cast<Relocatable**>(from); |
| 4004 return from + ArchiveSpacePerThread(); | 4007 return from + ArchiveSpacePerThread(); |
| 4005 } | 4008 } |
| 4006 | 4009 |
| 4007 | 4010 |
| 4008 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) { | 4011 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) { |
| 4009 Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage); | 4012 Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage); |
| 4010 Iterate(v, top); | 4013 Iterate(v, top); |
| 4011 return thread_storage + ArchiveSpacePerThread(); | 4014 return thread_storage + ArchiveSpacePerThread(); |
| 4012 } | 4015 } |
| 4013 | 4016 |
| 4014 | 4017 |
| 4015 void Relocatable::Iterate(ObjectVisitor* v) { | 4018 void Relocatable::Iterate(ObjectVisitor* v) { |
| 4016 Iterate(v, top_); | 4019 Iterate(v, v8_context()->relocatable_data_.top_); |
| 4017 } | 4020 } |
| 4018 | 4021 |
| 4019 | 4022 |
| 4020 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) { | 4023 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) { |
| 4021 Relocatable* current = top; | 4024 Relocatable* current = top; |
| 4022 while (current != NULL) { | 4025 while (current != NULL) { |
| 4023 current->IterateInstance(v); | 4026 current->IterateInstance(v); |
| 4024 current = current->prev_; | 4027 current = current->prev_; |
| 4025 } | 4028 } |
| 4026 } | 4029 } |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4385 // Compare the remaining characters that didn't fit into a block. | 4388 // Compare the remaining characters that didn't fit into a block. |
| 4386 for (; i < length; i++) { | 4389 for (; i < length; i++) { |
| 4387 if (a[i] != b[i]) { | 4390 if (a[i] != b[i]) { |
| 4388 return false; | 4391 return false; |
| 4389 } | 4392 } |
| 4390 } | 4393 } |
| 4391 return true; | 4394 return true; |
| 4392 } | 4395 } |
| 4393 | 4396 |
| 4394 | 4397 |
| 4395 static StringInputBuffer string_compare_buffer_b; | |
| 4396 | 4398 |
| 4397 | 4399 |
| 4398 template <typename IteratorA> | 4400 template <typename IteratorA> |
| 4399 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { | 4401 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { |
| 4400 if (b->IsFlat()) { | 4402 if (b->IsFlat()) { |
| 4401 if (b->IsAsciiRepresentation()) { | 4403 if (b->IsAsciiRepresentation()) { |
| 4402 VectorIterator<char> ib(b->ToAsciiVector()); | 4404 VectorIterator<char> ib(b->ToAsciiVector()); |
| 4403 return CompareStringContents(ia, &ib); | 4405 return CompareStringContents(ia, &ib); |
| 4404 } else { | 4406 } else { |
| 4405 VectorIterator<uc16> ib(b->ToUC16Vector()); | 4407 VectorIterator<uc16> ib(b->ToUC16Vector()); |
| 4406 return CompareStringContents(ia, &ib); | 4408 return CompareStringContents(ia, &ib); |
| 4407 } | 4409 } |
| 4408 } else { | 4410 } else { |
| 4411 StringInputBuffer& string_compare_buffer_b = |
| 4412 v8_context()->objects_data_.string_compare_buffer_b_; |
| 4409 string_compare_buffer_b.Reset(0, b); | 4413 string_compare_buffer_b.Reset(0, b); |
| 4410 return CompareStringContents(ia, &string_compare_buffer_b); | 4414 return CompareStringContents(ia, &string_compare_buffer_b); |
| 4411 } | 4415 } |
| 4412 } | 4416 } |
| 4413 | 4417 |
| 4414 | 4418 |
| 4415 static StringInputBuffer string_compare_buffer_a; | |
| 4416 | 4419 |
| 4417 | 4420 |
| 4418 bool String::SlowEquals(String* other) { | 4421 bool String::SlowEquals(String* other) { |
| 4419 // Fast check: negative check with lengths. | 4422 // Fast check: negative check with lengths. |
| 4420 int len = length(); | 4423 int len = length(); |
| 4421 if (len != other->length()) return false; | 4424 if (len != other->length()) return false; |
| 4422 if (len == 0) return true; | 4425 if (len == 0) return true; |
| 4423 | 4426 |
| 4424 // Fast check: if hash code is computed for both strings | 4427 // Fast check: if hash code is computed for both strings |
| 4425 // a fast negative check can be performed. | 4428 // a fast negative check can be performed. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 4442 if (other->IsAsciiRepresentation()) { | 4445 if (other->IsAsciiRepresentation()) { |
| 4443 Vector<const char> vec2 = other->ToAsciiVector(); | 4446 Vector<const char> vec2 = other->ToAsciiVector(); |
| 4444 return CompareRawStringContents(vec1, vec2); | 4447 return CompareRawStringContents(vec1, vec2); |
| 4445 } else { | 4448 } else { |
| 4446 VectorIterator<char> buf1(vec1); | 4449 VectorIterator<char> buf1(vec1); |
| 4447 VectorIterator<uc16> ib(other->ToUC16Vector()); | 4450 VectorIterator<uc16> ib(other->ToUC16Vector()); |
| 4448 return CompareStringContents(&buf1, &ib); | 4451 return CompareStringContents(&buf1, &ib); |
| 4449 } | 4452 } |
| 4450 } else { | 4453 } else { |
| 4451 VectorIterator<char> buf1(vec1); | 4454 VectorIterator<char> buf1(vec1); |
| 4455 StringInputBuffer& string_compare_buffer_b = |
| 4456 v8_context()->objects_data_.string_compare_buffer_b_; |
| 4452 string_compare_buffer_b.Reset(0, other); | 4457 string_compare_buffer_b.Reset(0, other); |
| 4453 return CompareStringContents(&buf1, &string_compare_buffer_b); | 4458 return CompareStringContents(&buf1, &string_compare_buffer_b); |
| 4454 } | 4459 } |
| 4455 } else { | 4460 } else { |
| 4456 Vector<const uc16> vec1 = this->ToUC16Vector(); | 4461 Vector<const uc16> vec1 = this->ToUC16Vector(); |
| 4457 if (other->IsFlat()) { | 4462 if (other->IsFlat()) { |
| 4458 if (other->IsAsciiRepresentation()) { | 4463 if (other->IsAsciiRepresentation()) { |
| 4459 VectorIterator<uc16> buf1(vec1); | 4464 VectorIterator<uc16> buf1(vec1); |
| 4460 VectorIterator<char> ib(other->ToAsciiVector()); | 4465 VectorIterator<char> ib(other->ToAsciiVector()); |
| 4461 return CompareStringContents(&buf1, &ib); | 4466 return CompareStringContents(&buf1, &ib); |
| 4462 } else { | 4467 } else { |
| 4463 Vector<const uc16> vec2(other->ToUC16Vector()); | 4468 Vector<const uc16> vec2(other->ToUC16Vector()); |
| 4464 return CompareRawStringContents(vec1, vec2); | 4469 return CompareRawStringContents(vec1, vec2); |
| 4465 } | 4470 } |
| 4466 } else { | 4471 } else { |
| 4467 VectorIterator<uc16> buf1(vec1); | 4472 VectorIterator<uc16> buf1(vec1); |
| 4473 StringInputBuffer& string_compare_buffer_b = |
| 4474 v8_context()->objects_data_.string_compare_buffer_b_; |
| 4468 string_compare_buffer_b.Reset(0, other); | 4475 string_compare_buffer_b.Reset(0, other); |
| 4469 return CompareStringContents(&buf1, &string_compare_buffer_b); | 4476 return CompareStringContents(&buf1, &string_compare_buffer_b); |
| 4470 } | 4477 } |
| 4471 } | 4478 } |
| 4472 } else { | 4479 } else { |
| 4480 StringInputBuffer& string_compare_buffer_a = |
| 4481 v8_context()->objects_data_.string_compare_buffer_a_; |
| 4473 string_compare_buffer_a.Reset(0, this); | 4482 string_compare_buffer_a.Reset(0, this); |
| 4474 return CompareStringContentsPartial(&string_compare_buffer_a, other); | 4483 return CompareStringContentsPartial(&string_compare_buffer_a, other); |
| 4475 } | 4484 } |
| 4476 } | 4485 } |
| 4477 | 4486 |
| 4478 | 4487 |
| 4479 bool String::MarkAsUndetectable() { | 4488 bool String::MarkAsUndetectable() { |
| 4480 if (StringShape(this).IsSymbol()) return false; | 4489 if (StringShape(this).IsSymbol()) return false; |
| 4481 | 4490 |
| 4482 Map* map = this->map(); | 4491 Map* map = this->map(); |
| (...skipping 3805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8288 if (break_point_objects()->IsUndefined()) return 0; | 8297 if (break_point_objects()->IsUndefined()) return 0; |
| 8289 // Single beak point. | 8298 // Single beak point. |
| 8290 if (!break_point_objects()->IsFixedArray()) return 1; | 8299 if (!break_point_objects()->IsFixedArray()) return 1; |
| 8291 // Multiple break points. | 8300 // Multiple break points. |
| 8292 return FixedArray::cast(break_point_objects())->length(); | 8301 return FixedArray::cast(break_point_objects())->length(); |
| 8293 } | 8302 } |
| 8294 #endif | 8303 #endif |
| 8295 | 8304 |
| 8296 | 8305 |
| 8297 } } // namespace v8::internal | 8306 } } // namespace v8::internal |
| OLD | NEW |