| 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 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 return true; // An Ape, an ABCBook. | 611 return true; // An Ape, an ABCBook. |
| 612 } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) && | 612 } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) && |
| 613 (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' || | 613 (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' || |
| 614 c0 == 'S' || c0 == 'X')) { | 614 c0 == 'S' || c0 == 'X')) { |
| 615 return true; // An MP3File, an M. | 615 return true; // An MP3File, an M. |
| 616 } | 616 } |
| 617 return false; | 617 return false; |
| 618 } | 618 } |
| 619 | 619 |
| 620 | 620 |
| 621 Object* String::TryFlatten() { | 621 Object* String::SlowTryFlatten(PretenureFlag pretenure) { |
| 622 #ifdef DEBUG | 622 #ifdef DEBUG |
| 623 // Do not attempt to flatten in debug mode when allocation is not | 623 // Do not attempt to flatten in debug mode when allocation is not |
| 624 // allowed. This is to avoid an assertion failure when allocating. | 624 // allowed. This is to avoid an assertion failure when allocating. |
| 625 // Flattening strings is the only case where we always allow | 625 // Flattening strings is the only case where we always allow |
| 626 // allocation because no GC is performed if the allocation fails. | 626 // allocation because no GC is performed if the allocation fails. |
| 627 if (!Heap::IsAllocationAllowed()) return this; | 627 if (!Heap::IsAllocationAllowed()) return this; |
| 628 #endif | 628 #endif |
| 629 | 629 |
| 630 switch (StringShape(this).representation_tag()) { | 630 switch (StringShape(this).representation_tag()) { |
| 631 case kConsStringTag: { | 631 case kConsStringTag: { |
| 632 ConsString* cs = ConsString::cast(this); | 632 ConsString* cs = ConsString::cast(this); |
| 633 if (cs->second()->length() == 0) { | 633 if (cs->second()->length() == 0) { |
| 634 return this; | 634 return this; |
| 635 } | 635 } |
| 636 // There's little point in putting the flat string in new space if the | 636 // There's little point in putting the flat string in new space if the |
| 637 // cons string is in old space. It can never get GCed until there is | 637 // cons string is in old space. It can never get GCed until there is |
| 638 // an old space GC. | 638 // an old space GC. |
| 639 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED; | 639 PretenureFlag tenure = Heap::InNewSpace(this) ? pretenure : TENURED; |
| 640 int len = length(); | 640 int len = length(); |
| 641 Object* object; | 641 Object* object; |
| 642 String* result; | 642 String* result; |
| 643 if (IsAsciiRepresentation()) { | 643 if (IsAsciiRepresentation()) { |
| 644 object = Heap::AllocateRawAsciiString(len, tenure); | 644 object = Heap::AllocateRawAsciiString(len, tenure); |
| 645 if (object->IsFailure()) return object; | 645 if (object->IsFailure()) return object; |
| 646 result = String::cast(object); | 646 result = String::cast(object); |
| 647 String* first = cs->first(); | 647 String* first = cs->first(); |
| 648 int first_length = first->length(); | 648 int first_length = first->length(); |
| 649 char* dest = SeqAsciiString::cast(result)->GetChars(); | 649 char* dest = SeqAsciiString::cast(result)->GetChars(); |
| (...skipping 1461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2111 ASSERT(!IsGlobalObject()); | 2111 ASSERT(!IsGlobalObject()); |
| 2112 | 2112 |
| 2113 // Allocate new content. | 2113 // Allocate new content. |
| 2114 int property_count = map()->NumberOfDescribedProperties(); | 2114 int property_count = map()->NumberOfDescribedProperties(); |
| 2115 if (expected_additional_properties > 0) { | 2115 if (expected_additional_properties > 0) { |
| 2116 property_count += expected_additional_properties; | 2116 property_count += expected_additional_properties; |
| 2117 } else { | 2117 } else { |
| 2118 property_count += 2; // Make space for two more properties. | 2118 property_count += 2; // Make space for two more properties. |
| 2119 } | 2119 } |
| 2120 Object* obj = | 2120 Object* obj = |
| 2121 StringDictionary::Allocate(property_count * 2); | 2121 StringDictionary::Allocate(property_count); |
| 2122 if (obj->IsFailure()) return obj; | 2122 if (obj->IsFailure()) return obj; |
| 2123 StringDictionary* dictionary = StringDictionary::cast(obj); | 2123 StringDictionary* dictionary = StringDictionary::cast(obj); |
| 2124 | 2124 |
| 2125 DescriptorArray* descs = map()->instance_descriptors(); | 2125 DescriptorArray* descs = map()->instance_descriptors(); |
| 2126 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 2126 for (int i = 0; i < descs->number_of_descriptors(); i++) { |
| 2127 PropertyDetails details = descs->GetDetails(i); | 2127 PropertyDetails details = descs->GetDetails(i); |
| 2128 switch (details.type()) { | 2128 switch (details.type()) { |
| 2129 case CONSTANT_FUNCTION: { | 2129 case CONSTANT_FUNCTION: { |
| 2130 PropertyDetails d = | 2130 PropertyDetails d = |
| 2131 PropertyDetails(details.attributes(), NORMAL, details.index()); | 2131 PropertyDetails(details.attributes(), NORMAL, details.index()); |
| (...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2694 AssertNoContextChange ncc; | 2694 AssertNoContextChange ncc; |
| 2695 | 2695 |
| 2696 // Check access rights if needed. | 2696 // Check access rights if needed. |
| 2697 if (IsAccessCheckNeeded() && | 2697 if (IsAccessCheckNeeded() && |
| 2698 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 2698 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 2699 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 2699 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 2700 return Heap::undefined_value(); | 2700 return Heap::undefined_value(); |
| 2701 } | 2701 } |
| 2702 | 2702 |
| 2703 // Try to flatten before operating on the string. | 2703 // Try to flatten before operating on the string. |
| 2704 name->TryFlattenIfNotFlat(); | 2704 name->TryFlatten(); |
| 2705 | 2705 |
| 2706 // Check if there is an API defined callback object which prohibits | 2706 // Check if there is an API defined callback object which prohibits |
| 2707 // callback overwriting in this object or it's prototype chain. | 2707 // callback overwriting in this object or it's prototype chain. |
| 2708 // This mechanism is needed for instance in a browser setting, where | 2708 // This mechanism is needed for instance in a browser setting, where |
| 2709 // certain accessors such as window.location should not be allowed | 2709 // certain accessors such as window.location should not be allowed |
| 2710 // to be overwritten because allowing overwriting could potentially | 2710 // to be overwritten because allowing overwriting could potentially |
| 2711 // cause security problems. | 2711 // cause security problems. |
| 2712 LookupResult callback_result; | 2712 LookupResult callback_result; |
| 2713 LookupCallback(name, &callback_result); | 2713 LookupCallback(name, &callback_result); |
| 2714 if (callback_result.IsFound()) { | 2714 if (callback_result.IsFound()) { |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2959 Object* new_map = CopyDropDescriptors(); | 2959 Object* new_map = CopyDropDescriptors(); |
| 2960 if (new_map->IsFailure()) return new_map; | 2960 if (new_map->IsFailure()) return new_map; |
| 2961 Object* descriptors = instance_descriptors()->RemoveTransitions(); | 2961 Object* descriptors = instance_descriptors()->RemoveTransitions(); |
| 2962 if (descriptors->IsFailure()) return descriptors; | 2962 if (descriptors->IsFailure()) return descriptors; |
| 2963 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); | 2963 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); |
| 2964 return cast(new_map); | 2964 return cast(new_map); |
| 2965 } | 2965 } |
| 2966 | 2966 |
| 2967 | 2967 |
| 2968 Object* Map::UpdateCodeCache(String* name, Code* code) { | 2968 Object* Map::UpdateCodeCache(String* name, Code* code) { |
| 2969 // Allocate the code cache if not present. |
| 2970 if (code_cache()->IsFixedArray()) { |
| 2971 Object* result = Heap::AllocateCodeCache(); |
| 2972 if (result->IsFailure()) return result; |
| 2973 set_code_cache(result); |
| 2974 } |
| 2975 |
| 2976 // Update the code cache. |
| 2977 return CodeCache::cast(code_cache())->Update(name, code); |
| 2978 } |
| 2979 |
| 2980 |
| 2981 Object* Map::FindInCodeCache(String* name, Code::Flags flags) { |
| 2982 // Do a lookup if a code cache exists. |
| 2983 if (!code_cache()->IsFixedArray()) { |
| 2984 return CodeCache::cast(code_cache())->Lookup(name, flags); |
| 2985 } else { |
| 2986 return Heap::undefined_value(); |
| 2987 } |
| 2988 } |
| 2989 |
| 2990 |
| 2991 int Map::IndexInCodeCache(String* name, Code* code) { |
| 2992 // Get the internal index if a code cache exists. |
| 2993 if (!code_cache()->IsFixedArray()) { |
| 2994 return CodeCache::cast(code_cache())->GetIndex(name, code); |
| 2995 } |
| 2996 return -1; |
| 2997 } |
| 2998 |
| 2999 |
| 3000 void Map::RemoveFromCodeCache(String* name, Code* code, int index) { |
| 3001 // No GC is supposed to happen between a call to IndexInCodeCache and |
| 3002 // RemoveFromCodeCache so the code cache must be there. |
| 3003 ASSERT(!code_cache()->IsFixedArray()); |
| 3004 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); |
| 3005 } |
| 3006 |
| 3007 |
| 3008 Object* CodeCache::Update(String* name, Code* code) { |
| 2969 ASSERT(code->ic_state() == MONOMORPHIC); | 3009 ASSERT(code->ic_state() == MONOMORPHIC); |
| 2970 FixedArray* cache = code_cache(); | |
| 2971 | 3010 |
| 2972 // When updating the code cache we disregard the type encoded in the | 3011 // The number of monomorphic stubs for normal load/store/call IC's can grow to |
| 3012 // a large number and therefore they need to go into a hash table. They are |
| 3013 // used to load global properties from cells. |
| 3014 if (code->type() == NORMAL) { |
| 3015 // Make sure that a hash table is allocated for the normal load code cache. |
| 3016 if (normal_type_cache()->IsUndefined()) { |
| 3017 Object* result = |
| 3018 CodeCacheHashTable::Allocate(CodeCacheHashTable::kInitialSize); |
| 3019 if (result->IsFailure()) return result; |
| 3020 set_normal_type_cache(result); |
| 3021 } |
| 3022 return UpdateNormalTypeCache(name, code); |
| 3023 } else { |
| 3024 ASSERT(default_cache()->IsFixedArray()); |
| 3025 return UpdateDefaultCache(name, code); |
| 3026 } |
| 3027 } |
| 3028 |
| 3029 |
| 3030 Object* CodeCache::UpdateDefaultCache(String* name, Code* code) { |
| 3031 // When updating the default code cache we disregard the type encoded in the |
| 2973 // flags. This allows call constant stubs to overwrite call field | 3032 // flags. This allows call constant stubs to overwrite call field |
| 2974 // stubs, etc. | 3033 // stubs, etc. |
| 2975 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags()); | 3034 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags()); |
| 2976 | 3035 |
| 2977 // First check whether we can update existing code cache without | 3036 // First check whether we can update existing code cache without |
| 2978 // extending it. | 3037 // extending it. |
| 3038 FixedArray* cache = default_cache(); |
| 2979 int length = cache->length(); | 3039 int length = cache->length(); |
| 2980 int deleted_index = -1; | 3040 int deleted_index = -1; |
| 2981 for (int i = 0; i < length; i += 2) { | 3041 for (int i = 0; i < length; i += kCodeCacheEntrySize) { |
| 2982 Object* key = cache->get(i); | 3042 Object* key = cache->get(i); |
| 2983 if (key->IsNull()) { | 3043 if (key->IsNull()) { |
| 2984 if (deleted_index < 0) deleted_index = i; | 3044 if (deleted_index < 0) deleted_index = i; |
| 2985 continue; | 3045 continue; |
| 2986 } | 3046 } |
| 2987 if (key->IsUndefined()) { | 3047 if (key->IsUndefined()) { |
| 2988 if (deleted_index >= 0) i = deleted_index; | 3048 if (deleted_index >= 0) i = deleted_index; |
| 2989 cache->set(i + 0, name); | 3049 cache->set(i + kCodeCacheEntryNameOffset, name); |
| 2990 cache->set(i + 1, code); | 3050 cache->set(i + kCodeCacheEntryCodeOffset, code); |
| 2991 return this; | 3051 return this; |
| 2992 } | 3052 } |
| 2993 if (name->Equals(String::cast(key))) { | 3053 if (name->Equals(String::cast(key))) { |
| 2994 Code::Flags found = Code::cast(cache->get(i + 1))->flags(); | 3054 Code::Flags found = |
| 3055 Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags(); |
| 2995 if (Code::RemoveTypeFromFlags(found) == flags) { | 3056 if (Code::RemoveTypeFromFlags(found) == flags) { |
| 2996 cache->set(i + 1, code); | 3057 cache->set(i + kCodeCacheEntryCodeOffset, code); |
| 2997 return this; | 3058 return this; |
| 2998 } | 3059 } |
| 2999 } | 3060 } |
| 3000 } | 3061 } |
| 3001 | 3062 |
| 3002 // Reached the end of the code cache. If there were deleted | 3063 // Reached the end of the code cache. If there were deleted |
| 3003 // elements, reuse the space for the first of them. | 3064 // elements, reuse the space for the first of them. |
| 3004 if (deleted_index >= 0) { | 3065 if (deleted_index >= 0) { |
| 3005 cache->set(deleted_index + 0, name); | 3066 cache->set(deleted_index + kCodeCacheEntryNameOffset, name); |
| 3006 cache->set(deleted_index + 1, code); | 3067 cache->set(deleted_index + kCodeCacheEntryCodeOffset, code); |
| 3007 return this; | 3068 return this; |
| 3008 } | 3069 } |
| 3009 | 3070 |
| 3010 // Extend the code cache with some new entries (at least one). | 3071 // Extend the code cache with some new entries (at least one). Must be a |
| 3011 int new_length = length + ((length >> 1) & ~1) + 2; | 3072 // multiple of the entry size. |
| 3012 ASSERT((new_length & 1) == 0); // must be a multiple of two | 3073 int new_length = length + ((length >> 1)) + kCodeCacheEntrySize; |
| 3074 new_length = new_length - new_length % kCodeCacheEntrySize; |
| 3075 ASSERT((new_length % kCodeCacheEntrySize) == 0); |
| 3013 Object* result = cache->CopySize(new_length); | 3076 Object* result = cache->CopySize(new_length); |
| 3014 if (result->IsFailure()) return result; | 3077 if (result->IsFailure()) return result; |
| 3015 | 3078 |
| 3016 // Add the (name, code) pair to the new cache. | 3079 // Add the (name, code) pair to the new cache. |
| 3017 cache = FixedArray::cast(result); | 3080 cache = FixedArray::cast(result); |
| 3018 cache->set(length + 0, name); | 3081 cache->set(length + kCodeCacheEntryNameOffset, name); |
| 3019 cache->set(length + 1, code); | 3082 cache->set(length + kCodeCacheEntryCodeOffset, code); |
| 3020 set_code_cache(cache); | 3083 set_default_cache(cache); |
| 3021 return this; | 3084 return this; |
| 3022 } | 3085 } |
| 3023 | 3086 |
| 3024 | 3087 |
| 3025 Object* Map::FindInCodeCache(String* name, Code::Flags flags) { | 3088 Object* CodeCache::UpdateNormalTypeCache(String* name, Code* code) { |
| 3026 FixedArray* cache = code_cache(); | 3089 // Adding a new entry can cause a new cache to be allocated. |
| 3090 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); |
| 3091 Object* new_cache = cache->Put(name, code); |
| 3092 if (new_cache->IsFailure()) return new_cache; |
| 3093 set_normal_type_cache(new_cache); |
| 3094 return this; |
| 3095 } |
| 3096 |
| 3097 |
| 3098 Object* CodeCache::Lookup(String* name, Code::Flags flags) { |
| 3099 if (Code::ExtractTypeFromFlags(flags) == NORMAL) { |
| 3100 return LookupNormalTypeCache(name, flags); |
| 3101 } else { |
| 3102 return LookupDefaultCache(name, flags); |
| 3103 } |
| 3104 } |
| 3105 |
| 3106 |
| 3107 Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) { |
| 3108 FixedArray* cache = default_cache(); |
| 3027 int length = cache->length(); | 3109 int length = cache->length(); |
| 3028 for (int i = 0; i < length; i += 2) { | 3110 for (int i = 0; i < length; i += kCodeCacheEntrySize) { |
| 3029 Object* key = cache->get(i); | 3111 Object* key = cache->get(i + kCodeCacheEntryNameOffset); |
| 3030 // Skip deleted elements. | 3112 // Skip deleted elements. |
| 3031 if (key->IsNull()) continue; | 3113 if (key->IsNull()) continue; |
| 3032 if (key->IsUndefined()) return key; | 3114 if (key->IsUndefined()) return key; |
| 3033 if (name->Equals(String::cast(key))) { | 3115 if (name->Equals(String::cast(key))) { |
| 3034 Code* code = Code::cast(cache->get(i + 1)); | 3116 Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset)); |
| 3035 if (code->flags() == flags) return code; | 3117 if (code->flags() == flags) { |
| 3118 return code; |
| 3119 } |
| 3036 } | 3120 } |
| 3037 } | 3121 } |
| 3038 return Heap::undefined_value(); | 3122 return Heap::undefined_value(); |
| 3039 } | 3123 } |
| 3040 | 3124 |
| 3041 | 3125 |
| 3042 int Map::IndexInCodeCache(Code* code) { | 3126 Object* CodeCache::LookupNormalTypeCache(String* name, Code::Flags flags) { |
| 3043 FixedArray* array = code_cache(); | 3127 if (!normal_type_cache()->IsUndefined()) { |
| 3128 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); |
| 3129 return cache->Lookup(name, flags); |
| 3130 } else { |
| 3131 return Heap::undefined_value(); |
| 3132 } |
| 3133 } |
| 3134 |
| 3135 |
| 3136 int CodeCache::GetIndex(String* name, Code* code) { |
| 3137 // This is not used for normal load/store/call IC's. |
| 3138 if (code->type() == NORMAL) { |
| 3139 if (normal_type_cache()->IsUndefined()) return -1; |
| 3140 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); |
| 3141 return cache->GetIndex(name, code->flags()); |
| 3142 } |
| 3143 |
| 3144 FixedArray* array = default_cache(); |
| 3044 int len = array->length(); | 3145 int len = array->length(); |
| 3045 for (int i = 0; i < len; i += 2) { | 3146 for (int i = 0; i < len; i += kCodeCacheEntrySize) { |
| 3046 if (array->get(i + 1) == code) return i + 1; | 3147 if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1; |
| 3047 } | 3148 } |
| 3048 return -1; | 3149 return -1; |
| 3049 } | 3150 } |
| 3050 | 3151 |
| 3051 | 3152 |
| 3052 void Map::RemoveFromCodeCache(int index) { | 3153 void CodeCache::RemoveByIndex(String* name, Code* code, int index) { |
| 3053 FixedArray* array = code_cache(); | 3154 if (code->type() == NORMAL) { |
| 3054 ASSERT(array->length() >= index && array->get(index)->IsCode()); | 3155 ASSERT(!normal_type_cache()->IsUndefined()); |
| 3055 // Use null instead of undefined for deleted elements to distinguish | 3156 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); |
| 3056 // deleted elements from unused elements. This distinction is used | 3157 ASSERT(cache->GetIndex(name, code->flags()) == index); |
| 3057 // when looking up in the cache and when updating the cache. | 3158 cache->RemoveByIndex(index); |
| 3058 array->set_null(index - 1); // key | 3159 } else { |
| 3059 array->set_null(index); // code | 3160 FixedArray* array = default_cache(); |
| 3161 ASSERT(array->length() >= index && array->get(index)->IsCode()); |
| 3162 // Use null instead of undefined for deleted elements to distinguish |
| 3163 // deleted elements from unused elements. This distinction is used |
| 3164 // when looking up in the cache and when updating the cache. |
| 3165 ASSERT_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset); |
| 3166 array->set_null(index - 1); // Name. |
| 3167 array->set_null(index); // Code. |
| 3168 } |
| 3169 } |
| 3170 |
| 3171 |
| 3172 // The key in the code cache hash table consists of the property name and the |
| 3173 // code object. The actual match is on the name and the code flags. If a key |
| 3174 // is created using the flags and not a code object it can only be used for |
| 3175 // lookup not to create a new entry. |
| 3176 class CodeCacheHashTableKey : public HashTableKey { |
| 3177 public: |
| 3178 CodeCacheHashTableKey(String* name, Code::Flags flags) |
| 3179 : name_(name), flags_(flags), code_(NULL) { } |
| 3180 |
| 3181 CodeCacheHashTableKey(String* name, Code* code) |
| 3182 : name_(name), |
| 3183 flags_(code->flags()), |
| 3184 code_(code) { } |
| 3185 |
| 3186 |
| 3187 bool IsMatch(Object* other) { |
| 3188 if (!other->IsFixedArray()) return false; |
| 3189 FixedArray* pair = FixedArray::cast(other); |
| 3190 String* name = String::cast(pair->get(0)); |
| 3191 Code::Flags flags = Code::cast(pair->get(1))->flags(); |
| 3192 if (flags != flags_) { |
| 3193 return false; |
| 3194 } |
| 3195 return name_->Equals(name); |
| 3196 } |
| 3197 |
| 3198 static uint32_t NameFlagsHashHelper(String* name, Code::Flags flags) { |
| 3199 return name->Hash() ^ flags; |
| 3200 } |
| 3201 |
| 3202 uint32_t Hash() { return NameFlagsHashHelper(name_, flags_); } |
| 3203 |
| 3204 uint32_t HashForObject(Object* obj) { |
| 3205 FixedArray* pair = FixedArray::cast(obj); |
| 3206 String* name = String::cast(pair->get(0)); |
| 3207 Code* code = Code::cast(pair->get(1)); |
| 3208 return NameFlagsHashHelper(name, code->flags()); |
| 3209 } |
| 3210 |
| 3211 Object* AsObject() { |
| 3212 ASSERT(code_ != NULL); |
| 3213 Object* obj = Heap::AllocateFixedArray(2); |
| 3214 if (obj->IsFailure()) return obj; |
| 3215 FixedArray* pair = FixedArray::cast(obj); |
| 3216 pair->set(0, name_); |
| 3217 pair->set(1, code_); |
| 3218 return pair; |
| 3219 } |
| 3220 |
| 3221 private: |
| 3222 String* name_; |
| 3223 Code::Flags flags_; |
| 3224 Code* code_; |
| 3225 }; |
| 3226 |
| 3227 |
| 3228 Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) { |
| 3229 CodeCacheHashTableKey key(name, flags); |
| 3230 int entry = FindEntry(&key); |
| 3231 if (entry == kNotFound) return Heap::undefined_value(); |
| 3232 return get(EntryToIndex(entry) + 1); |
| 3233 } |
| 3234 |
| 3235 |
| 3236 Object* CodeCacheHashTable::Put(String* name, Code* code) { |
| 3237 CodeCacheHashTableKey key(name, code); |
| 3238 Object* obj = EnsureCapacity(1, &key); |
| 3239 if (obj->IsFailure()) return obj; |
| 3240 |
| 3241 // Don't use this, as the table might have grown. |
| 3242 CodeCacheHashTable* cache = reinterpret_cast<CodeCacheHashTable*>(obj); |
| 3243 |
| 3244 int entry = cache->FindInsertionEntry(key.Hash()); |
| 3245 Object* k = key.AsObject(); |
| 3246 if (k->IsFailure()) return k; |
| 3247 |
| 3248 cache->set(EntryToIndex(entry), k); |
| 3249 cache->set(EntryToIndex(entry) + 1, code); |
| 3250 cache->ElementAdded(); |
| 3251 return cache; |
| 3252 } |
| 3253 |
| 3254 |
| 3255 int CodeCacheHashTable::GetIndex(String* name, Code::Flags flags) { |
| 3256 CodeCacheHashTableKey key(name, flags); |
| 3257 int entry = FindEntry(&key); |
| 3258 return (entry == kNotFound) ? -1 : entry; |
| 3259 } |
| 3260 |
| 3261 |
| 3262 void CodeCacheHashTable::RemoveByIndex(int index) { |
| 3263 ASSERT(index >= 0); |
| 3264 set(EntryToIndex(index), Heap::null_value()); |
| 3265 set(EntryToIndex(index) + 1, Heap::null_value()); |
| 3266 ElementRemoved(); |
| 3060 } | 3267 } |
| 3061 | 3268 |
| 3062 | 3269 |
| 3063 void FixedArray::FixedArrayIterateBody(ObjectVisitor* v) { | 3270 void FixedArray::FixedArrayIterateBody(ObjectVisitor* v) { |
| 3064 IteratePointers(v, kHeaderSize, kHeaderSize + length() * kPointerSize); | 3271 IteratePointers(v, kHeaderSize, kHeaderSize + length() * kPointerSize); |
| 3065 } | 3272 } |
| 3066 | 3273 |
| 3067 | 3274 |
| 3068 static bool HasKey(FixedArray* array, Object* key) { | 3275 static bool HasKey(FixedArray* array, Object* key) { |
| 3069 int len0 = array->length(); | 3276 int len0 = array->length(); |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3356 | 3563 |
| 3357 return new_descriptors; | 3564 return new_descriptors; |
| 3358 } | 3565 } |
| 3359 | 3566 |
| 3360 | 3567 |
| 3361 void DescriptorArray::Sort() { | 3568 void DescriptorArray::Sort() { |
| 3362 // In-place heap sort. | 3569 // In-place heap sort. |
| 3363 int len = number_of_descriptors(); | 3570 int len = number_of_descriptors(); |
| 3364 | 3571 |
| 3365 // Bottom-up max-heap construction. | 3572 // Bottom-up max-heap construction. |
| 3366 for (int i = 1; i < len; ++i) { | 3573 // Index of the last node with children |
| 3367 int child_index = i; | 3574 const int max_parent_index = (len / 2) - 1; |
| 3368 while (child_index > 0) { | 3575 for (int i = max_parent_index; i >= 0; --i) { |
| 3369 int parent_index = ((child_index + 1) >> 1) - 1; | 3576 int parent_index = i; |
| 3370 uint32_t parent_hash = GetKey(parent_index)->Hash(); | 3577 const uint32_t parent_hash = GetKey(i)->Hash(); |
| 3578 while (parent_index <= max_parent_index) { |
| 3579 int child_index = 2 * parent_index + 1; |
| 3371 uint32_t child_hash = GetKey(child_index)->Hash(); | 3580 uint32_t child_hash = GetKey(child_index)->Hash(); |
| 3372 if (parent_hash < child_hash) { | 3581 if (child_index + 1 < len) { |
| 3373 Swap(parent_index, child_index); | 3582 uint32_t right_child_hash = GetKey(child_index + 1)->Hash(); |
| 3374 } else { | 3583 if (right_child_hash > child_hash) { |
| 3375 break; | 3584 child_index++; |
| 3585 child_hash = right_child_hash; |
| 3586 } |
| 3376 } | 3587 } |
| 3377 child_index = parent_index; | 3588 if (child_hash <= parent_hash) break; |
| 3589 Swap(parent_index, child_index); |
| 3590 // Now element at child_index could be < its children. |
| 3591 parent_index = child_index; // parent_hash remains correct. |
| 3378 } | 3592 } |
| 3379 } | 3593 } |
| 3380 | 3594 |
| 3381 // Extract elements and create sorted array. | 3595 // Extract elements and create sorted array. |
| 3382 for (int i = len - 1; i > 0; --i) { | 3596 for (int i = len - 1; i > 0; --i) { |
| 3383 // Put max element at the back of the array. | 3597 // Put max element at the back of the array. |
| 3384 Swap(0, i); | 3598 Swap(0, i); |
| 3385 // Sift down the new top element. | 3599 // Sift down the new top element. |
| 3386 int parent_index = 0; | 3600 int parent_index = 0; |
| 3387 while (true) { | 3601 const uint32_t parent_hash = GetKey(parent_index)->Hash(); |
| 3388 int child_index = ((parent_index + 1) << 1) - 1; | 3602 const int max_parent_index = (i / 2) - 1; |
| 3389 if (child_index >= i) break; | 3603 while (parent_index <= max_parent_index) { |
| 3390 uint32_t child1_hash = GetKey(child_index)->Hash(); | 3604 int child_index = parent_index * 2 + 1; |
| 3391 uint32_t child2_hash = GetKey(child_index + 1)->Hash(); | 3605 uint32_t child_hash = GetKey(child_index)->Hash(); |
| 3392 uint32_t parent_hash = GetKey(parent_index)->Hash(); | 3606 if (child_index + 1 < i) { |
| 3393 if (child_index + 1 >= i || child1_hash > child2_hash) { | 3607 uint32_t right_child_hash = GetKey(child_index + 1)->Hash(); |
| 3394 if (parent_hash > child1_hash) break; | 3608 if (right_child_hash > child_hash) { |
| 3395 Swap(parent_index, child_index); | 3609 child_index++; |
| 3396 parent_index = child_index; | 3610 child_hash = right_child_hash; |
| 3397 } else { | 3611 } |
| 3398 if (parent_hash > child2_hash) break; | |
| 3399 Swap(parent_index, child_index + 1); | |
| 3400 parent_index = child_index + 1; | |
| 3401 } | 3612 } |
| 3613 if (child_hash <= parent_hash) break; |
| 3614 Swap(parent_index, child_index); |
| 3615 parent_index = child_index; |
| 3402 } | 3616 } |
| 3403 } | 3617 } |
| 3404 | 3618 |
| 3405 SLOW_ASSERT(IsSortedNoDuplicates()); | 3619 SLOW_ASSERT(IsSortedNoDuplicates()); |
| 3406 } | 3620 } |
| 3407 | 3621 |
| 3408 | 3622 |
| 3409 int DescriptorArray::BinarySearch(String* name, int low, int high) { | 3623 int DescriptorArray::BinarySearch(String* name, int low, int high) { |
| 3410 uint32_t hash = name->Hash(); | 3624 uint32_t hash = name->Hash(); |
| 3411 | 3625 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3472 return true; | 3686 return true; |
| 3473 } | 3687 } |
| 3474 | 3688 |
| 3475 | 3689 |
| 3476 int String::Utf8Length() { | 3690 int String::Utf8Length() { |
| 3477 if (IsAsciiRepresentation()) return length(); | 3691 if (IsAsciiRepresentation()) return length(); |
| 3478 // Attempt to flatten before accessing the string. It probably | 3692 // Attempt to flatten before accessing the string. It probably |
| 3479 // doesn't make Utf8Length faster, but it is very likely that | 3693 // doesn't make Utf8Length faster, but it is very likely that |
| 3480 // the string will be accessed later (for example by WriteUtf8) | 3694 // the string will be accessed later (for example by WriteUtf8) |
| 3481 // so it's still a good idea. | 3695 // so it's still a good idea. |
| 3482 TryFlattenIfNotFlat(); | 3696 TryFlatten(); |
| 3483 Access<StringInputBuffer> buffer(&string_input_buffer); | 3697 Access<StringInputBuffer> buffer(&string_input_buffer); |
| 3484 buffer->Reset(0, this); | 3698 buffer->Reset(0, this); |
| 3485 int result = 0; | 3699 int result = 0; |
| 3486 while (buffer->has_more()) | 3700 while (buffer->has_more()) |
| 3487 result += unibrow::Utf8::Length(buffer->GetNext()); | 3701 result += unibrow::Utf8::Length(buffer->GetNext()); |
| 3488 return result; | 3702 return result; |
| 3489 } | 3703 } |
| 3490 | 3704 |
| 3491 | 3705 |
| 3492 Vector<const char> String::ToAsciiVector() { | 3706 Vector<const char> String::ToAsciiVector() { |
| (...skipping 1070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4563 // Process the remaining characters without updating the array | 4777 // Process the remaining characters without updating the array |
| 4564 // index. | 4778 // index. |
| 4565 while (buffer->has_more()) { | 4779 while (buffer->has_more()) { |
| 4566 hasher.AddCharacterNoIndex(buffer->GetNext()); | 4780 hasher.AddCharacterNoIndex(buffer->GetNext()); |
| 4567 } | 4781 } |
| 4568 | 4782 |
| 4569 return hasher.GetHashField(); | 4783 return hasher.GetHashField(); |
| 4570 } | 4784 } |
| 4571 | 4785 |
| 4572 | 4786 |
| 4573 Object* String::SubString(int start, int end) { | 4787 Object* String::SubString(int start, int end, PretenureFlag pretenure) { |
| 4574 if (start == 0 && end == length()) return this; | 4788 if (start == 0 && end == length()) return this; |
| 4575 Object* result = Heap::AllocateSubString(this, start, end); | 4789 Object* result = Heap::AllocateSubString(this, start, end, pretenure); |
| 4576 return result; | 4790 return result; |
| 4577 } | 4791 } |
| 4578 | 4792 |
| 4579 | 4793 |
| 4580 void String::PrintOn(FILE* file) { | 4794 void String::PrintOn(FILE* file) { |
| 4581 int length = this->length(); | 4795 int length = this->length(); |
| 4582 for (int i = 0; i < length; i++) { | 4796 for (int i = 0; i < length; i++) { |
| 4583 fprintf(file, "%c", Get(i)); | 4797 fprintf(file, "%c", Get(i)); |
| 4584 } | 4798 } |
| 4585 } | 4799 } |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4877 start_position(), | 5091 start_position(), |
| 4878 start_position() + max_length); | 5092 start_position() + max_length); |
| 4879 accumulator->Add("...\n"); | 5093 accumulator->Add("...\n"); |
| 4880 } else { | 5094 } else { |
| 4881 accumulator->Put(script_source, start_position(), end_position()); | 5095 accumulator->Put(script_source, start_position(), end_position()); |
| 4882 } | 5096 } |
| 4883 } | 5097 } |
| 4884 | 5098 |
| 4885 | 5099 |
| 4886 void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) { | 5100 void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) { |
| 4887 IteratePointers(v, kNameOffset, kConstructStubOffset + kPointerSize); | 5101 IteratePointers(v, |
| 4888 IteratePointers(v, kInstanceClassNameOffset, kScriptOffset + kPointerSize); | 5102 kNameOffset, |
| 4889 IteratePointers(v, kDebugInfoOffset, kInferredNameOffset + kPointerSize); | 5103 kThisPropertyAssignmentsOffset + kPointerSize); |
| 4890 IteratePointers(v, kThisPropertyAssignmentsOffset, | |
| 4891 kThisPropertyAssignmentsOffset + kPointerSize); | |
| 4892 } | 5104 } |
| 4893 | 5105 |
| 4894 | 5106 |
| 4895 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) { | 5107 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) { |
| 4896 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); | 5108 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); |
| 4897 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 5109 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
| 4898 Object* old_target = target; | 5110 Object* old_target = target; |
| 4899 VisitPointer(&target); | 5111 VisitPointer(&target); |
| 4900 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. | 5112 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. |
| 4901 } | 5113 } |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5052 const char* Code::Kind2String(Kind kind) { | 5264 const char* Code::Kind2String(Kind kind) { |
| 5053 switch (kind) { | 5265 switch (kind) { |
| 5054 case FUNCTION: return "FUNCTION"; | 5266 case FUNCTION: return "FUNCTION"; |
| 5055 case STUB: return "STUB"; | 5267 case STUB: return "STUB"; |
| 5056 case BUILTIN: return "BUILTIN"; | 5268 case BUILTIN: return "BUILTIN"; |
| 5057 case LOAD_IC: return "LOAD_IC"; | 5269 case LOAD_IC: return "LOAD_IC"; |
| 5058 case KEYED_LOAD_IC: return "KEYED_LOAD_IC"; | 5270 case KEYED_LOAD_IC: return "KEYED_LOAD_IC"; |
| 5059 case STORE_IC: return "STORE_IC"; | 5271 case STORE_IC: return "STORE_IC"; |
| 5060 case KEYED_STORE_IC: return "KEYED_STORE_IC"; | 5272 case KEYED_STORE_IC: return "KEYED_STORE_IC"; |
| 5061 case CALL_IC: return "CALL_IC"; | 5273 case CALL_IC: return "CALL_IC"; |
| 5274 case BINARY_OP_IC: return "BINARY_OP_IC"; |
| 5062 } | 5275 } |
| 5063 UNREACHABLE(); | 5276 UNREACHABLE(); |
| 5064 return NULL; | 5277 return NULL; |
| 5065 } | 5278 } |
| 5066 | 5279 |
| 5067 | 5280 |
| 5068 const char* Code::ICState2String(InlineCacheState state) { | 5281 const char* Code::ICState2String(InlineCacheState state) { |
| 5069 switch (state) { | 5282 switch (state) { |
| 5070 case UNINITIALIZED: return "UNINITIALIZED"; | 5283 case UNINITIALIZED: return "UNINITIALIZED"; |
| 5071 case PREMONOMORPHIC: return "PREMONOMORPHIC"; | 5284 case PREMONOMORPHIC: return "PREMONOMORPHIC"; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5173 Object* obj = NormalizeElements(); | 5386 Object* obj = NormalizeElements(); |
| 5174 if (obj->IsFailure()) return obj; | 5387 if (obj->IsFailure()) return obj; |
| 5175 | 5388 |
| 5176 // Update length for JSArrays. | 5389 // Update length for JSArrays. |
| 5177 if (IsJSArray()) JSArray::cast(this)->set_length(len); | 5390 if (IsJSArray()) JSArray::cast(this)->set_length(len); |
| 5178 break; | 5391 break; |
| 5179 } | 5392 } |
| 5180 case DICTIONARY_ELEMENTS: { | 5393 case DICTIONARY_ELEMENTS: { |
| 5181 if (IsJSArray()) { | 5394 if (IsJSArray()) { |
| 5182 uint32_t old_length = | 5395 uint32_t old_length = |
| 5183 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); | 5396 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); |
| 5184 element_dictionary()->RemoveNumberEntries(new_length, old_length), | 5397 element_dictionary()->RemoveNumberEntries(new_length, old_length), |
| 5185 JSArray::cast(this)->set_length(len); | 5398 JSArray::cast(this)->set_length(len); |
| 5186 } | 5399 } |
| 5187 break; | 5400 break; |
| 5188 } | 5401 } |
| 5189 default: | 5402 default: |
| 5190 UNREACHABLE(); | 5403 UNREACHABLE(); |
| 5191 break; | 5404 break; |
| 5192 } | 5405 } |
| 5193 return this; | 5406 return this; |
| (...skipping 1635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6829 | 7042 |
| 6830 template<typename Shape, typename Key> | 7043 template<typename Shape, typename Key> |
| 6831 void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) { | 7044 void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) { |
| 6832 IteratePointers(v, | 7045 IteratePointers(v, |
| 6833 kElementsStartOffset, | 7046 kElementsStartOffset, |
| 6834 kHeaderSize + length() * kPointerSize); | 7047 kHeaderSize + length() * kPointerSize); |
| 6835 } | 7048 } |
| 6836 | 7049 |
| 6837 | 7050 |
| 6838 template<typename Shape, typename Key> | 7051 template<typename Shape, typename Key> |
| 6839 Object* HashTable<Shape, Key>::Allocate(int at_least_space_for) { | 7052 Object* HashTable<Shape, Key>::Allocate(int at_least_space_for, |
| 6840 int capacity = RoundUpToPowerOf2(at_least_space_for); | 7053 PretenureFlag pretenure) { |
| 6841 if (capacity < 4) { | 7054 const int kMinCapacity = 32; |
| 6842 capacity = 4; // Guarantee min capacity. | 7055 int capacity = RoundUpToPowerOf2(at_least_space_for * 2); |
| 7056 if (capacity < kMinCapacity) { |
| 7057 capacity = kMinCapacity; // Guarantee min capacity. |
| 6843 } else if (capacity > HashTable::kMaxCapacity) { | 7058 } else if (capacity > HashTable::kMaxCapacity) { |
| 6844 return Failure::OutOfMemoryException(); | 7059 return Failure::OutOfMemoryException(); |
| 6845 } | 7060 } |
| 6846 | 7061 |
| 6847 Object* obj = Heap::AllocateHashTable(EntryToIndex(capacity)); | 7062 Object* obj = Heap::AllocateHashTable(EntryToIndex(capacity), pretenure); |
| 6848 if (!obj->IsFailure()) { | 7063 if (!obj->IsFailure()) { |
| 6849 HashTable::cast(obj)->SetNumberOfElements(0); | 7064 HashTable::cast(obj)->SetNumberOfElements(0); |
| 6850 HashTable::cast(obj)->SetNumberOfDeletedElements(0); | 7065 HashTable::cast(obj)->SetNumberOfDeletedElements(0); |
| 6851 HashTable::cast(obj)->SetCapacity(capacity); | 7066 HashTable::cast(obj)->SetCapacity(capacity); |
| 6852 } | 7067 } |
| 6853 return obj; | 7068 return obj; |
| 6854 } | 7069 } |
| 6855 | 7070 |
| 6856 | 7071 |
| 6857 // Find entry for key otherwise return kNotFound. | 7072 // Find entry for key otherwise return kNotFound. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 6872 | 7087 |
| 6873 | 7088 |
| 6874 template<typename Shape, typename Key> | 7089 template<typename Shape, typename Key> |
| 6875 Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { | 7090 Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { |
| 6876 int capacity = Capacity(); | 7091 int capacity = Capacity(); |
| 6877 int nof = NumberOfElements() + n; | 7092 int nof = NumberOfElements() + n; |
| 6878 int nod = NumberOfDeletedElements(); | 7093 int nod = NumberOfDeletedElements(); |
| 6879 // Return if: | 7094 // Return if: |
| 6880 // 50% is still free after adding n elements and | 7095 // 50% is still free after adding n elements and |
| 6881 // at most 50% of the free elements are deleted elements. | 7096 // at most 50% of the free elements are deleted elements. |
| 6882 if ((nof + (nof >> 1) <= capacity) && | 7097 if (nod <= (capacity - nof) >> 1) { |
| 6883 (nod <= (capacity - nof) >> 1)) return this; | 7098 int needed_free = nof >> 1; |
| 7099 if (nof + needed_free <= capacity) return this; |
| 7100 } |
| 6884 | 7101 |
| 6885 Object* obj = Allocate(nof * 2); | 7102 const int kMinCapacityForPretenure = 256; |
| 7103 bool pretenure = |
| 7104 (capacity > kMinCapacityForPretenure) && !Heap::InNewSpace(this); |
| 7105 Object* obj = Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED); |
| 6886 if (obj->IsFailure()) return obj; | 7106 if (obj->IsFailure()) return obj; |
| 6887 | 7107 |
| 6888 AssertNoAllocation no_gc; | 7108 AssertNoAllocation no_gc; |
| 6889 HashTable* table = HashTable::cast(obj); | 7109 HashTable* table = HashTable::cast(obj); |
| 6890 WriteBarrierMode mode = table->GetWriteBarrierMode(no_gc); | 7110 WriteBarrierMode mode = table->GetWriteBarrierMode(no_gc); |
| 6891 | 7111 |
| 6892 // Copy prefix to new array. | 7112 // Copy prefix to new array. |
| 6893 for (int i = kPrefixStartIndex; | 7113 for (int i = kPrefixStartIndex; |
| 6894 i < kPrefixStartIndex + Shape::kPrefixSize; | 7114 i < kPrefixStartIndex + Shape::kPrefixSize; |
| 6895 i++) { | 7115 i++) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 6907 table->set(insertion_index + j, get(from_index + j), mode); | 7127 table->set(insertion_index + j, get(from_index + j), mode); |
| 6908 } | 7128 } |
| 6909 } | 7129 } |
| 6910 } | 7130 } |
| 6911 table->SetNumberOfElements(NumberOfElements()); | 7131 table->SetNumberOfElements(NumberOfElements()); |
| 6912 table->SetNumberOfDeletedElements(0); | 7132 table->SetNumberOfDeletedElements(0); |
| 6913 return table; | 7133 return table; |
| 6914 } | 7134 } |
| 6915 | 7135 |
| 6916 | 7136 |
| 6917 | |
| 6918 template<typename Shape, typename Key> | 7137 template<typename Shape, typename Key> |
| 6919 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) { | 7138 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) { |
| 6920 uint32_t capacity = Capacity(); | 7139 uint32_t capacity = Capacity(); |
| 6921 uint32_t entry = FirstProbe(hash, capacity); | 7140 uint32_t entry = FirstProbe(hash, capacity); |
| 6922 uint32_t count = 1; | 7141 uint32_t count = 1; |
| 6923 // EnsureCapacity will guarantee the hash table is never full. | 7142 // EnsureCapacity will guarantee the hash table is never full. |
| 6924 while (true) { | 7143 while (true) { |
| 6925 Object* element = KeyAt(entry); | 7144 Object* element = KeyAt(entry); |
| 6926 if (element->IsUndefined() || element->IsNull()) break; | 7145 if (element->IsUndefined() || element->IsNull()) break; |
| 6927 entry = NextProbe(entry, count++, capacity); | 7146 entry = NextProbe(entry, count++, capacity); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7017 // elements. | 7236 // elements. |
| 7018 NumberDictionary* dict = element_dictionary(); | 7237 NumberDictionary* dict = element_dictionary(); |
| 7019 HeapNumber* result_double = NULL; | 7238 HeapNumber* result_double = NULL; |
| 7020 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { | 7239 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 7021 // Allocate space for result before we start mutating the object. | 7240 // Allocate space for result before we start mutating the object. |
| 7022 Object* new_double = Heap::AllocateHeapNumber(0.0); | 7241 Object* new_double = Heap::AllocateHeapNumber(0.0); |
| 7023 if (new_double->IsFailure()) return new_double; | 7242 if (new_double->IsFailure()) return new_double; |
| 7024 result_double = HeapNumber::cast(new_double); | 7243 result_double = HeapNumber::cast(new_double); |
| 7025 } | 7244 } |
| 7026 | 7245 |
| 7027 int capacity = dict->Capacity(); | 7246 Object* obj = NumberDictionary::Allocate(dict->NumberOfElements()); |
| 7028 Object* obj = NumberDictionary::Allocate(dict->Capacity()); | |
| 7029 if (obj->IsFailure()) return obj; | 7247 if (obj->IsFailure()) return obj; |
| 7030 NumberDictionary* new_dict = NumberDictionary::cast(obj); | 7248 NumberDictionary* new_dict = NumberDictionary::cast(obj); |
| 7031 | 7249 |
| 7032 AssertNoAllocation no_alloc; | 7250 AssertNoAllocation no_alloc; |
| 7033 | 7251 |
| 7034 uint32_t pos = 0; | 7252 uint32_t pos = 0; |
| 7035 uint32_t undefs = 0; | 7253 uint32_t undefs = 0; |
| 7254 int capacity = dict->Capacity(); |
| 7036 for (int i = 0; i < capacity; i++) { | 7255 for (int i = 0; i < capacity; i++) { |
| 7037 Object* k = dict->KeyAt(i); | 7256 Object* k = dict->KeyAt(i); |
| 7038 if (dict->IsKey(k)) { | 7257 if (dict->IsKey(k)) { |
| 7039 ASSERT(k->IsNumber()); | 7258 ASSERT(k->IsNumber()); |
| 7040 ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0); | 7259 ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0); |
| 7041 ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0); | 7260 ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0); |
| 7042 ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32); | 7261 ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32); |
| 7043 Object* value = dict->ValueAt(i); | 7262 Object* value = dict->ValueAt(i); |
| 7044 PropertyDetails details = dict->DetailsAt(i); | 7263 PropertyDetails details = dict->DetailsAt(i); |
| 7045 if (details.type() == CALLBACKS) { | 7264 if (details.type() == CALLBACKS) { |
| (...skipping 1248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8294 if (break_point_objects()->IsUndefined()) return 0; | 8513 if (break_point_objects()->IsUndefined()) return 0; |
| 8295 // Single beak point. | 8514 // Single beak point. |
| 8296 if (!break_point_objects()->IsFixedArray()) return 1; | 8515 if (!break_point_objects()->IsFixedArray()) return 1; |
| 8297 // Multiple break points. | 8516 // Multiple break points. |
| 8298 return FixedArray::cast(break_point_objects())->length(); | 8517 return FixedArray::cast(break_point_objects())->length(); |
| 8299 } | 8518 } |
| 8300 #endif | 8519 #endif |
| 8301 | 8520 |
| 8302 | 8521 |
| 8303 } } // namespace v8::internal | 8522 } } // namespace v8::internal |
| OLD | NEW |