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

Side by Side Diff: src/objects.cc

Issue 7385006: Reintroduced dictionary that can use objects as keys. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Incorporated review from Vitaly Repeshko. 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 2946 matching lines...) Expand 10 before | Expand all | Expand 10 after
2957 PrintF("Object elements have been normalized:\n"); 2957 PrintF("Object elements have been normalized:\n");
2958 Print(); 2958 Print();
2959 } 2959 }
2960 #endif 2960 #endif
2961 2961
2962 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); 2962 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
2963 return dictionary; 2963 return dictionary;
2964 } 2964 }
2965 2965
2966 2966
2967 MaybeObject* JSObject::GetHiddenProperties(bool create_if_needed) {
2968 Isolate* isolate = GetIsolate();
2969 Heap* heap = isolate->heap();
2970 Object* holder = BypassGlobalProxy();
2971 if (holder->IsUndefined()) return heap->undefined_value();
2972 JSObject* obj = JSObject::cast(holder);
2973 if (obj->HasFastProperties()) {
2974 // If the object has fast properties, check whether the first slot
2975 // in the descriptor array matches the hidden symbol. Since the
2976 // hidden symbols hash code is zero (and no other string has hash
2977 // code zero) it will always occupy the first entry if present.
2978 DescriptorArray* descriptors = obj->map()->instance_descriptors();
2979 if ((descriptors->number_of_descriptors() > 0) &&
2980 (descriptors->GetKey(0) == heap->hidden_symbol()) &&
2981 descriptors->IsProperty(0)) {
2982 ASSERT(descriptors->GetType(0) == FIELD);
2983 return obj->FastPropertyAt(descriptors->GetFieldIndex(0));
2984 }
2985 }
2986
2987 // Only attempt to find the hidden properties in the local object and not
2988 // in the prototype chain. Note that HasLocalProperty() can cause a GC in
Vitaly Repeshko 2011/07/26 13:53:14 The comment about HasLocalProperty should be moved
Michael Starzinger 2011/07/26 22:30:23 Fixed.
2989 // the general case in the presence of interceptors.
2990 if (!obj->HasHiddenPropertiesObject()) {
2991 // Hidden properties object not found. Allocate a new hidden properties
2992 // object if requested. Otherwise return the undefined value.
2993 if (create_if_needed) {
2994 Object* hidden_obj;
2995 { MaybeObject* maybe_obj = heap->AllocateJSObject(
2996 isolate->context()->global_context()->object_function());
2997 if (!maybe_obj->ToObject(&hidden_obj)) return maybe_obj;
2998 }
2999 return obj->SetHiddenPropertiesObject(hidden_obj);
3000 } else {
3001 return heap->undefined_value();
3002 }
3003 }
3004 return obj->GetHiddenPropertiesObject();
3005 }
3006
3007
3008 MaybeObject* JSObject::GetIdentityHash() {
3009 Isolate* isolate = GetIsolate();
3010 Object* hidden_props_obj;
3011 { MaybeObject* maybe_obj = GetHiddenProperties(true);
3012 if (!maybe_obj->ToObject(&hidden_props_obj)) return maybe_obj;
3013 }
3014 if (!hidden_props_obj->IsJSObject()) {
3015 // We failed to create hidden properties. That's a detached
3016 // global proxy.
3017 ASSERT(hidden_props_obj->IsUndefined());
3018 return Smi::FromInt(0);
3019 }
3020 JSObject* hidden_props = JSObject::cast(hidden_props_obj);
3021 String* hash_symbol = isolate->heap()->identity_hash_symbol();
3022 if (hidden_props->HasLocalProperty(hash_symbol)) {
3023 MaybeObject* hash = hidden_props->GetProperty(hash_symbol);
3024 return Smi::cast(hash->ToObjectChecked());
3025 }
3026
3027 int hash_value;
3028 int attempts = 0;
3029 do {
3030 // Generate a random 32-bit hash value but limit range to fit
3031 // within a smi.
3032 hash_value = V8::Random(isolate) & Smi::kMaxValue;
3033 attempts++;
3034 } while (hash_value == 0 && attempts < 30);
3035 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
3036
3037 Smi* hash = Smi::FromInt(hash_value);
3038 { MaybeObject* result = hidden_props->SetLocalPropertyIgnoreAttributes(
3039 hash_symbol,
3040 hash,
3041 static_cast<PropertyAttributes>(None));
3042 if (result->IsFailure()) return result;
3043 }
3044 return hash;
3045 }
3046
3047
2967 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, 3048 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
2968 DeleteMode mode) { 3049 DeleteMode mode) {
2969 // Check local property, ignore interceptor. 3050 // Check local property, ignore interceptor.
2970 LookupResult result; 3051 LookupResult result;
2971 LocalLookupRealNamedProperty(name, &result); 3052 LocalLookupRealNamedProperty(name, &result);
2972 if (!result.IsProperty()) return GetHeap()->true_value(); 3053 if (!result.IsProperty()) return GetHeap()->true_value();
2973 3054
2974 // Normalize object if needed. 3055 // Normalize object if needed.
2975 Object* obj; 3056 Object* obj;
2976 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 3057 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
(...skipping 7389 matching lines...) Expand 10 before | Expand all | Expand 10 after
10366 template class HashTable<SymbolTableShape, HashTableKey*>; 10447 template class HashTable<SymbolTableShape, HashTableKey*>;
10367 10448
10368 template class HashTable<CompilationCacheShape, HashTableKey*>; 10449 template class HashTable<CompilationCacheShape, HashTableKey*>;
10369 10450
10370 template class HashTable<MapCacheShape, HashTableKey*>; 10451 template class HashTable<MapCacheShape, HashTableKey*>;
10371 10452
10372 template class Dictionary<StringDictionaryShape, String*>; 10453 template class Dictionary<StringDictionaryShape, String*>;
10373 10454
10374 template class Dictionary<NumberDictionaryShape, uint32_t>; 10455 template class Dictionary<NumberDictionaryShape, uint32_t>;
10375 10456
10457 template class Dictionary<ObjectDictionaryShape, JSObject*>;
10458
10376 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Allocate( 10459 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Allocate(
10377 int); 10460 int);
10378 10461
10379 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate( 10462 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate(
10380 int); 10463 int);
10381 10464
10465 template MaybeObject* Dictionary<ObjectDictionaryShape, JSObject*>::Allocate(
10466 int);
10467
10382 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::AtPut( 10468 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::AtPut(
10383 uint32_t, Object*); 10469 uint32_t, Object*);
10384 10470
10385 template Object* Dictionary<NumberDictionaryShape, uint32_t>::SlowReverseLookup( 10471 template Object* Dictionary<NumberDictionaryShape, uint32_t>::SlowReverseLookup(
10386 Object*); 10472 Object*);
10387 10473
10388 template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup( 10474 template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup(
10389 Object*); 10475 Object*);
10390 10476
10391 template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo( 10477 template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo(
(...skipping 976 matching lines...) Expand 10 before | Expand all | Expand 10 after
11368 // Insert element at empty or deleted entry 11454 // Insert element at empty or deleted entry
11369 if (!details.IsDeleted() && details.index() == 0 && Shape::kIsEnumerable) { 11455 if (!details.IsDeleted() && details.index() == 0 && Shape::kIsEnumerable) {
11370 // Assign an enumeration index to the property and update 11456 // Assign an enumeration index to the property and update
11371 // SetNextEnumerationIndex. 11457 // SetNextEnumerationIndex.
11372 int index = NextEnumerationIndex(); 11458 int index = NextEnumerationIndex();
11373 details = PropertyDetails(details.attributes(), details.type(), index); 11459 details = PropertyDetails(details.attributes(), details.type(), index);
11374 SetNextEnumerationIndex(index + 1); 11460 SetNextEnumerationIndex(index + 1);
11375 } 11461 }
11376 SetEntry(entry, k, value, details); 11462 SetEntry(entry, k, value, details);
11377 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() 11463 ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
11378 || Dictionary<Shape, Key>::KeyAt(entry)->IsString())); 11464 || Dictionary<Shape, Key>::KeyAt(entry)->IsString()
11465 || Dictionary<Shape, Key>::KeyAt(entry)->IsJSObject()));
11379 HashTable<Shape, Key>::ElementAdded(); 11466 HashTable<Shape, Key>::ElementAdded();
11380 return this; 11467 return this;
11381 } 11468 }
11382 11469
11383 11470
11384 void NumberDictionary::UpdateMaxNumberKey(uint32_t key) { 11471 void NumberDictionary::UpdateMaxNumberKey(uint32_t key) {
11385 // If the dictionary requires slow elements an element has already 11472 // If the dictionary requires slow elements an element has already
11386 // been added at a high index. 11473 // been added at a high index.
11387 if (requires_slow_elements()) return; 11474 if (requires_slow_elements()) return;
11388 // Check if this index is high enough that we should require slow 11475 // Check if this index is high enough that we should require slow
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
11673 ASSERT(obj->IsJSObject()); 11760 ASSERT(obj->IsJSObject());
11674 11761
11675 descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); 11762 descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
11676 // Check that it really works. 11763 // Check that it really works.
11677 ASSERT(obj->HasFastProperties()); 11764 ASSERT(obj->HasFastProperties());
11678 11765
11679 return obj; 11766 return obj;
11680 } 11767 }
11681 11768
11682 11769
11770 int ObjectDictionary::FindEntry(JSObject* key) {
11771 // If the object does not have an identity hash, it was never used as a key.
11772 MaybeObject* maybe_hash = key->GetIdentityHash();
Vitaly Repeshko 2011/07/26 13:53:14 It'd be nice to avoid allocating a hidden properti
Michael Starzinger 2011/07/26 22:30:23 Fixed (partially, didn't create an enum so far). I
Vitaly Repeshko 2011/07/27 15:42:26 Why do you want to add the enum in a separate CL?
Michael Starzinger 2011/07/28 01:23:18 Fixed. Ok. :)
11773 if (maybe_hash->IsFailure()) return kNotFound;
11774 return Dictionary<ObjectDictionaryShape, JSObject*>::FindEntry(key);
11775 }
11776
11777
11778 MaybeObject* ObjectDictionary::Add(JSObject* key, Object* value) {
11779 // Make sure the key object has an identity hash code.
11780 MaybeObject* maybe_hash = key->GetIdentityHash();
11781 if (maybe_hash->IsFailure()) return maybe_hash;
11782 PropertyDetails details(NONE, NORMAL);
11783 return Dictionary<ObjectDictionaryShape, JSObject*>::Add(key, value, details);
11784 }
11785
11786
11683 #ifdef ENABLE_DEBUGGER_SUPPORT 11787 #ifdef ENABLE_DEBUGGER_SUPPORT
11684 // Check if there is a break point at this code position. 11788 // Check if there is a break point at this code position.
11685 bool DebugInfo::HasBreakPoint(int code_position) { 11789 bool DebugInfo::HasBreakPoint(int code_position) {
11686 // Get the break point info object for this code position. 11790 // Get the break point info object for this code position.
11687 Object* break_point_info = GetBreakPointInfo(code_position); 11791 Object* break_point_info = GetBreakPointInfo(code_position);
11688 11792
11689 // If there is no break point info object or no break points in the break 11793 // If there is no break point info object or no break points in the break
11690 // point info object there is no break point at this code position. 11794 // point info object there is no break point at this code position.
11691 if (break_point_info->IsUndefined()) return false; 11795 if (break_point_info->IsUndefined()) return false;
11692 return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0; 11796 return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
11927 if (break_point_objects()->IsUndefined()) return 0; 12031 if (break_point_objects()->IsUndefined()) return 0;
11928 // Single beak point. 12032 // Single beak point.
11929 if (!break_point_objects()->IsFixedArray()) return 1; 12033 if (!break_point_objects()->IsFixedArray()) return 1;
11930 // Multiple break points. 12034 // Multiple break points.
11931 return FixedArray::cast(break_point_objects())->length(); 12035 return FixedArray::cast(break_point_objects())->length();
11932 } 12036 }
11933 #endif 12037 #endif
11934 12038
11935 12039
11936 } } // namespace v8::internal 12040 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698