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

Side by Side Diff: src/objects.cc

Issue 844006: Merge changes up to V8 version 2.1.3 into the partial snapshots (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: Created 10 years, 9 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-debug.cc » ('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 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698