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

Side by Side Diff: src/objects.cc

Issue 225823003: Implement handlified String::Equals and Name::Equals. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: refactored StringToDouble Created 6 years, 8 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
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 1188 matching lines...) Expand 10 before | Expand all | Expand 10 after
1199 result = flat; 1199 result = flat;
1200 } else { 1200 } else {
1201 Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString( 1201 Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
1202 length, tenure).ToHandleChecked(); 1202 length, tenure).ToHandleChecked();
1203 DisallowHeapAllocation no_gc; 1203 DisallowHeapAllocation no_gc;
1204 WriteToFlat(*cons, flat->GetChars(), 0, length); 1204 WriteToFlat(*cons, flat->GetChars(), 0, length);
1205 result = flat; 1205 result = flat;
1206 } 1206 }
1207 cons->set_first(*result); 1207 cons->set_first(*result);
1208 cons->set_second(isolate->heap()->empty_string()); 1208 cons->set_second(isolate->heap()->empty_string());
1209 ASSERT(result->IsFlat());
1209 return result; 1210 return result;
1210 } 1211 }
1211 1212
1212 1213
1213 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) {
1214 #ifdef DEBUG
1215 // Do not attempt to flatten in debug mode when allocation is not
1216 // allowed. This is to avoid an assertion failure when allocating.
1217 // Flattening strings is the only case where we always allow
1218 // allocation because no GC is performed if the allocation fails.
1219 if (!AllowHeapAllocation::IsAllowed()) return this;
1220 #endif
1221
1222 Heap* heap = GetHeap();
1223 switch (StringShape(this).representation_tag()) {
1224 case kConsStringTag: {
1225 ConsString* cs = ConsString::cast(this);
1226 if (cs->second()->length() == 0) {
1227 return cs->first();
1228 }
1229 // There's little point in putting the flat string in new space if the
1230 // cons string is in old space. It can never get GCed until there is
1231 // an old space GC.
1232 PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED;
1233 int len = length();
1234 Object* object;
1235 String* result;
1236 if (IsOneByteRepresentation()) {
1237 { MaybeObject* maybe_object =
1238 heap->AllocateRawOneByteString(len, tenure);
1239 if (!maybe_object->ToObject(&object)) return maybe_object;
1240 }
1241 result = String::cast(object);
1242 String* first = cs->first();
1243 int first_length = first->length();
1244 uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
1245 WriteToFlat(first, dest, 0, first_length);
1246 String* second = cs->second();
1247 WriteToFlat(second,
1248 dest + first_length,
1249 0,
1250 len - first_length);
1251 } else {
1252 { MaybeObject* maybe_object =
1253 heap->AllocateRawTwoByteString(len, tenure);
1254 if (!maybe_object->ToObject(&object)) return maybe_object;
1255 }
1256 result = String::cast(object);
1257 uc16* dest = SeqTwoByteString::cast(result)->GetChars();
1258 String* first = cs->first();
1259 int first_length = first->length();
1260 WriteToFlat(first, dest, 0, first_length);
1261 String* second = cs->second();
1262 WriteToFlat(second,
1263 dest + first_length,
1264 0,
1265 len - first_length);
1266 }
1267 cs->set_first(result);
1268 cs->set_second(heap->empty_string(), SKIP_WRITE_BARRIER);
1269 return result;
1270 }
1271 default:
1272 return this;
1273 }
1274 }
1275
1276 1214
1277 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { 1215 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
1278 // Externalizing twice leaks the external resource, so it's 1216 // Externalizing twice leaks the external resource, so it's
1279 // prohibited by the API. 1217 // prohibited by the API.
1280 ASSERT(!this->IsExternalString()); 1218 ASSERT(!this->IsExternalString());
1281 #ifdef ENABLE_SLOW_ASSERTS 1219 #ifdef ENABLE_SLOW_ASSERTS
1282 if (FLAG_enable_slow_asserts) { 1220 if (FLAG_enable_slow_asserts) {
1283 // Assert that the resource and the string are equivalent. 1221 // Assert that the resource and the string are equivalent.
1284 ASSERT(static_cast<size_t>(this->length()) == resource->length()); 1222 ASSERT(static_cast<size_t>(this->length()) == resource->length());
1285 ScopedVector<uc16> smart_chars(this->length()); 1223 ScopedVector<uc16> smart_chars(this->length());
(...skipping 4747 matching lines...) Expand 10 before | Expand all | Expand 10 after
6033 for (int i = 0; i < number_of_own_descriptors; i++) { 5971 for (int i = 0; i < number_of_own_descriptors; i++) {
6034 if (descs->GetType(i) == FIELD) { 5972 if (descs->GetType(i) == FIELD) {
6035 int current_index = descs->GetFieldIndex(i); 5973 int current_index = descs->GetFieldIndex(i);
6036 if (current_index > max_index) max_index = current_index; 5974 if (current_index > max_index) max_index = current_index;
6037 } 5975 }
6038 } 5976 }
6039 return max_index + 1; 5977 return max_index + 1;
6040 } 5978 }
6041 5979
6042 5980
6043 AccessorDescriptor* Map::FindAccessor(Name* name) {
6044 DescriptorArray* descs = instance_descriptors();
6045 int number_of_own_descriptors = NumberOfOwnDescriptors();
6046 for (int i = 0; i < number_of_own_descriptors; i++) {
6047 if (descs->GetType(i) == CALLBACKS && name->Equals(descs->GetKey(i))) {
6048 return descs->GetCallbacks(i);
6049 }
6050 }
6051 return NULL;
6052 }
6053
6054
6055 void JSReceiver::LocalLookup( 5981 void JSReceiver::LocalLookup(
6056 Name* name, LookupResult* result, bool search_hidden_prototypes) { 5982 Name* name, LookupResult* result, bool search_hidden_prototypes) {
6057 ASSERT(name->IsName()); 5983 ASSERT(name->IsName());
6058 5984
6059 Heap* heap = GetHeap(); 5985 Heap* heap = GetHeap();
6060 5986
6061 if (IsJSGlobalProxy()) { 5987 if (IsJSGlobalProxy()) {
6062 Object* proto = GetPrototype(); 5988 Object* proto = GetPrototype();
6063 if (proto->IsNull()) return result->NotFound(); 5989 if (proto->IsNull()) return result->NotFound();
6064 ASSERT(proto->IsJSGlobalObject()); 5990 ASSERT(proto->IsJSGlobalObject());
(...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after
6550 component, accessor, attributes); 6476 component, accessor, attributes);
6551 } 6477 }
6552 } else { 6478 } else {
6553 // If not, lookup a transition. 6479 // If not, lookup a transition.
6554 object->map()->LookupTransition(*object, *name, &result); 6480 object->map()->LookupTransition(*object, *name, &result);
6555 6481
6556 // If there is a transition, try to follow it. 6482 // If there is a transition, try to follow it.
6557 if (result.IsFound()) { 6483 if (result.IsFound()) {
6558 Handle<Map> target(result.GetTransitionTarget()); 6484 Handle<Map> target(result.GetTransitionTarget());
6559 int descriptor_number = target->LastAdded(); 6485 int descriptor_number = target->LastAdded();
6560 ASSERT(target->instance_descriptors()->GetKey(descriptor_number) 6486 ASSERT(Name::Equals(name,
6561 ->Equals(*name)); 6487 handle(target->instance_descriptors()->GetKey(descriptor_number))));
6562 return TryAccessorTransition(object, target, descriptor_number, 6488 return TryAccessorTransition(object, target, descriptor_number,
6563 component, accessor, attributes); 6489 component, accessor, attributes);
6564 } 6490 }
6565 } 6491 }
6566 6492
6567 // If there is no transition yet, add a transition to the a new accessor pair 6493 // If there is no transition yet, add a transition to the a new accessor pair
6568 // containing the accessor. Allocate a new pair if there were no source 6494 // containing the accessor. Allocate a new pair if there were no source
6569 // accessors. Otherwise, copy the pair and modify the accessor. 6495 // accessors. Otherwise, copy the pair and modify the accessor.
6570 Handle<AccessorPair> accessors = source_accessors != NULL 6496 Handle<AccessorPair> accessors = source_accessors != NULL
6571 ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors)) 6497 ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors))
(...skipping 1799 matching lines...) Expand 10 before | Expand all | Expand 10 after
8371 ASSERT(shape.representation_tag() != kConsStringTag && 8297 ASSERT(shape.representation_tag() != kConsStringTag &&
8372 shape.representation_tag() != kSlicedStringTag); 8298 shape.representation_tag() != kSlicedStringTag);
8373 } 8299 }
8374 if (shape.encoding_tag() == kOneByteStringTag) { 8300 if (shape.encoding_tag() == kOneByteStringTag) {
8375 const uint8_t* start; 8301 const uint8_t* start;
8376 if (shape.representation_tag() == kSeqStringTag) { 8302 if (shape.representation_tag() == kSeqStringTag) {
8377 start = SeqOneByteString::cast(string)->GetChars(); 8303 start = SeqOneByteString::cast(string)->GetChars();
8378 } else { 8304 } else {
8379 start = ExternalAsciiString::cast(string)->GetChars(); 8305 start = ExternalAsciiString::cast(string)->GetChars();
8380 } 8306 }
8381 return FlatContent(Vector<const uint8_t>(start + offset, length)); 8307 return FlatContent(start + offset, length);
8382 } else { 8308 } else {
8383 ASSERT(shape.encoding_tag() == kTwoByteStringTag); 8309 ASSERT(shape.encoding_tag() == kTwoByteStringTag);
8384 const uc16* start; 8310 const uc16* start;
8385 if (shape.representation_tag() == kSeqStringTag) { 8311 if (shape.representation_tag() == kSeqStringTag) {
8386 start = SeqTwoByteString::cast(string)->GetChars(); 8312 start = SeqTwoByteString::cast(string)->GetChars();
8387 } else { 8313 } else {
8388 start = ExternalTwoByteString::cast(string)->GetChars(); 8314 start = ExternalTwoByteString::cast(string)->GetChars();
8389 } 8315 }
8390 return FlatContent(Vector<const uc16>(start + offset, length)); 8316 return FlatContent(start + offset, length);
8391 } 8317 }
8392 } 8318 }
8393 8319
8394 8320
8395 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls, 8321 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
8396 RobustnessFlag robust_flag, 8322 RobustnessFlag robust_flag,
8397 int offset, 8323 int offset,
8398 int length, 8324 int length,
8399 int* length_return) { 8325 int* length_return) {
8400 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { 8326 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
(...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after
9020 } 8946 }
9021 8947
9022 private: 8948 private:
9023 State state_1_; 8949 State state_1_;
9024 State state_2_; 8950 State state_2_;
9025 DISALLOW_IMPLICIT_CONSTRUCTORS(StringComparator); 8951 DISALLOW_IMPLICIT_CONSTRUCTORS(StringComparator);
9026 }; 8952 };
9027 8953
9028 8954
9029 bool String::SlowEquals(String* other) { 8955 bool String::SlowEquals(String* other) {
8956 DisallowHeapAllocation no_gc;
9030 // Fast check: negative check with lengths. 8957 // Fast check: negative check with lengths.
9031 int len = length(); 8958 int len = length();
9032 if (len != other->length()) return false; 8959 if (len != other->length()) return false;
9033 if (len == 0) return true; 8960 if (len == 0) return true;
9034 8961
9035 // Fast check: if hash code is computed for both strings 8962 // Fast check: if hash code is computed for both strings
9036 // a fast negative check can be performed. 8963 // a fast negative check can be performed.
9037 if (HasHashCode() && other->HasHashCode()) { 8964 if (HasHashCode() && other->HasHashCode()) {
9038 #ifdef ENABLE_SLOW_ASSERTS 8965 #ifdef ENABLE_SLOW_ASSERTS
9039 if (FLAG_enable_slow_asserts) { 8966 if (FLAG_enable_slow_asserts) {
9040 if (Hash() != other->Hash()) { 8967 if (Hash() != other->Hash()) {
9041 bool found_difference = false; 8968 bool found_difference = false;
9042 for (int i = 0; i < len; i++) { 8969 for (int i = 0; i < len; i++) {
9043 if (Get(i) != other->Get(i)) { 8970 if (Get(i) != other->Get(i)) {
9044 found_difference = true; 8971 found_difference = true;
9045 break; 8972 break;
9046 } 8973 }
9047 } 8974 }
9048 ASSERT(found_difference); 8975 ASSERT(found_difference);
9049 } 8976 }
9050 } 8977 }
9051 #endif 8978 #endif
9052 if (Hash() != other->Hash()) return false; 8979 if (Hash() != other->Hash()) return false;
9053 } 8980 }
9054 8981
9055 // We know the strings are both non-empty. Compare the first chars 8982 // We know the strings are both non-empty. Compare the first chars
9056 // before we try to flatten the strings. 8983 // before we try to flatten the strings.
9057 if (this->Get(0) != other->Get(0)) return false; 8984 if (this->Get(0) != other->Get(0)) return false;
9058 8985
9059 String* lhs = this->TryFlattenGetString();
9060 String* rhs = other->TryFlattenGetString();
9061
9062 // TODO(dcarney): Compare all types of flat strings with a Visitor. 8986 // TODO(dcarney): Compare all types of flat strings with a Visitor.
9063 if (StringShape(lhs).IsSequentialAscii() && 8987 if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
9064 StringShape(rhs).IsSequentialAscii()) { 8988 const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
9065 const uint8_t* str1 = SeqOneByteString::cast(lhs)->GetChars(); 8989 const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
9066 const uint8_t* str2 = SeqOneByteString::cast(rhs)->GetChars();
9067 return CompareRawStringContents(str1, str2, len); 8990 return CompareRawStringContents(str1, str2, len);
9068 } 8991 }
9069 8992
9070 Isolate* isolate = GetIsolate(); 8993 Isolate* isolate = GetIsolate();
9071 StringComparator comparator(isolate->objects_string_compare_iterator_a(), 8994 StringComparator comparator(isolate->objects_string_compare_iterator_a(),
9072 isolate->objects_string_compare_iterator_b()); 8995 isolate->objects_string_compare_iterator_b());
9073 8996
9074 return comparator.Equals(static_cast<unsigned>(len), lhs, rhs); 8997 return comparator.Equals(static_cast<unsigned>(len), this, other);
9075 } 8998 }
9076 8999
9077 9000
9001 bool String::SlowEquals(Handle<String> one, Handle<String> two) {
9002 // Fast check: negative check with lengths.
9003 int one_length = one->length();
9004 if (one_length != two->length()) return false;
9005 if (one_length == 0) return true;
9006
9007 // Fast check: if hash code is computed for both strings
9008 // a fast negative check can be performed.
9009 if (one->HasHashCode() && two->HasHashCode()) {
9010 #ifdef ENABLE_SLOW_ASSERTS
9011 if (FLAG_enable_slow_asserts) {
9012 if (one->Hash() != two->Hash()) {
9013 bool found_difference = false;
9014 for (int i = 0; i < one_length; i++) {
9015 if (one->Get(i) != two->Get(i)) {
9016 found_difference = true;
9017 break;
9018 }
9019 }
9020 ASSERT(found_difference);
9021 }
9022 }
9023 #endif
9024 if (one->Hash() != two->Hash()) return false;
9025 }
9026
9027 // We know the strings are both non-empty. Compare the first chars
9028 // before we try to flatten the strings.
9029 if (one->Get(0) != two->Get(0)) return false;
9030
9031 one = String::Flatten(one);
9032 two = String::Flatten(two);
9033
9034 DisallowHeapAllocation no_gc;
9035 String::FlatContent flat1 = one->GetFlatContent();
9036 String::FlatContent flat2 = two->GetFlatContent();
9037
9038 if (flat1.IsAscii() && flat2.IsAscii()) {
9039 return CompareRawStringContents(flat1.ToOneByteVector().start(),
9040 flat2.ToOneByteVector().start(),
9041 one_length);
9042 } else {
9043 for (int i = 0; i < one_length; i++) {
9044 if (flat1.Get(i) != flat2.Get(i)) return false;
9045 }
9046 return true;
9047 }
9048 }
9049
9050
9078 bool String::MarkAsUndetectable() { 9051 bool String::MarkAsUndetectable() {
9079 if (StringShape(this).IsInternalized()) return false; 9052 if (StringShape(this).IsInternalized()) return false;
9080 9053
9081 Map* map = this->map(); 9054 Map* map = this->map();
9082 Heap* heap = GetHeap(); 9055 Heap* heap = GetHeap();
9083 if (map == heap->string_map()) { 9056 if (map == heap->string_map()) {
9084 this->set_map(heap->undetectable_string_map()); 9057 this->set_map(heap->undetectable_string_map());
9085 return true; 9058 return true;
9086 } else if (map == heap->ascii_string_map()) { 9059 } else if (map == heap->ascii_string_map()) {
9087 this->set_map(heap->undetectable_ascii_string_map()); 9060 this->set_map(heap->undetectable_ascii_string_map());
(...skipping 7641 matching lines...) Expand 10 before | Expand all | Expand 10 after
16729 #define ERROR_MESSAGES_TEXTS(C, T) T, 16702 #define ERROR_MESSAGES_TEXTS(C, T) T,
16730 static const char* error_messages_[] = { 16703 static const char* error_messages_[] = {
16731 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) 16704 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
16732 }; 16705 };
16733 #undef ERROR_MESSAGES_TEXTS 16706 #undef ERROR_MESSAGES_TEXTS
16734 return error_messages_[reason]; 16707 return error_messages_[reason];
16735 } 16708 }
16736 16709
16737 16710
16738 } } // namespace v8::internal 16711 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698