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 |