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

Side by Side Diff: src/objects.cc

Issue 1846963002: Use a dictionary-mode code cache on the map rather than a dual system. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comment Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« 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 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/objects.h" 5 #include "src/objects.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <iomanip> 8 #include <iomanip>
9 #include <sstream> 9 #include <sstream>
10 10
(...skipping 10046 matching lines...) Expand 10 before | Expand all | Expand 10 after
10057 simple_flag); 10057 simple_flag);
10058 } 10058 }
10059 10059
10060 10060
10061 void Map::UpdateCodeCache(Handle<Map> map, 10061 void Map::UpdateCodeCache(Handle<Map> map,
10062 Handle<Name> name, 10062 Handle<Name> name,
10063 Handle<Code> code) { 10063 Handle<Code> code) {
10064 Isolate* isolate = map->GetIsolate(); 10064 Isolate* isolate = map->GetIsolate();
10065 HandleScope scope(isolate); 10065 HandleScope scope(isolate);
10066 // Allocate the code cache if not present. 10066 // Allocate the code cache if not present.
10067 if (map->code_cache()->IsFixedArray()) { 10067 if (!map->has_code_cache()) {
10068 Handle<Object> result = isolate->factory()->NewCodeCache(); 10068 Handle<Object> result =
10069 CodeCacheHashTable::New(isolate, CodeCacheHashTable::kInitialSize);
10069 map->set_code_cache(*result); 10070 map->set_code_cache(*result);
10070 } 10071 }
10071 10072
10072 // Update the code cache. 10073 // Update the code cache.
10073 Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate); 10074 Handle<CodeCacheHashTable> cache(CodeCacheHashTable::cast(map->code_cache()),
10074 CodeCache::Update(code_cache, name, code); 10075 isolate);
10076 Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
10077 map->set_code_cache(*new_cache);
10078 }
10079
10080 Code* Map::LookupInCodeCache(Name* name, Code::Flags flags) {
10081 if (!has_code_cache()) return nullptr;
10082 return CodeCacheHashTable::cast(code_cache())->Lookup(name, flags);
10075 } 10083 }
10076 10084
10077 10085
10078 Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
10079 // Do a lookup if a code cache exists.
10080 if (!code_cache()->IsFixedArray()) {
10081 return CodeCache::cast(code_cache())->Lookup(name, flags);
10082 } else {
10083 return GetHeap()->undefined_value();
10084 }
10085 }
10086
10087
10088 int Map::IndexInCodeCache(Object* name, Code* code) {
10089 // Get the internal index if a code cache exists.
10090 if (!code_cache()->IsFixedArray()) {
10091 return CodeCache::cast(code_cache())->GetIndex(name, code);
10092 }
10093 return -1;
10094 }
10095
10096
10097 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
10098 // No GC is supposed to happen between a call to IndexInCodeCache and
10099 // RemoveFromCodeCache so the code cache must be there.
10100 DCHECK(!code_cache()->IsFixedArray());
10101 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
10102 }
10103
10104
10105 void CodeCache::Update(
10106 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
10107 // The number of monomorphic stubs for normal load/store/call IC's can grow to
10108 // a large number and therefore they need to go into a hash table. They are
10109 // used to load global properties from cells.
10110 if (code->type() == Code::NORMAL) {
10111 // Make sure that a hash table is allocated for the normal load code cache.
10112 if (code_cache->normal_type_cache()->IsUndefined()) {
10113 Handle<Object> result =
10114 CodeCacheHashTable::New(code_cache->GetIsolate(),
10115 CodeCacheHashTable::kInitialSize);
10116 code_cache->set_normal_type_cache(*result);
10117 }
10118 UpdateNormalTypeCache(code_cache, name, code);
10119 } else {
10120 DCHECK(code_cache->default_cache()->IsFixedArray());
10121 UpdateDefaultCache(code_cache, name, code);
10122 }
10123 }
10124
10125
10126 void CodeCache::UpdateDefaultCache(
10127 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
10128 Isolate* isolate = code_cache->GetIsolate();
10129 // When updating the default code cache we disregard the type encoded in the
10130 // flags. This allows call constant stubs to overwrite call field
10131 // stubs, etc.
10132 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
10133
10134 // First check whether we can update existing code cache without
10135 // extending it.
10136 Handle<FixedArray> cache = handle(code_cache->default_cache());
10137 int length = cache->length();
10138 {
10139 DisallowHeapAllocation no_alloc;
10140 int deleted_index = -1;
10141 Object* null = isolate->heap()->null_value();
10142 Object* undefined = isolate->heap()->undefined_value();
10143 DCHECK(name->IsUniqueName());
10144 for (int i = 0; i < length; i += kCodeCacheEntrySize) {
10145 Object* key = cache->get(i);
10146 if (key == null) {
10147 if (deleted_index < 0) deleted_index = i;
10148 continue;
10149 }
10150 if (key == undefined) {
10151 if (deleted_index >= 0) i = deleted_index;
10152 cache->set(i + kCodeCacheEntryNameOffset, *name);
10153 cache->set(i + kCodeCacheEntryCodeOffset, *code);
10154 return;
10155 }
10156 DCHECK(key->IsUniqueName());
10157 if (*name == key) {
10158 Code::Flags found =
10159 Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
10160 if (Code::RemoveTypeFromFlags(found) == flags) {
10161 cache->set(i + kCodeCacheEntryCodeOffset, *code);
10162 return;
10163 }
10164 }
10165 }
10166
10167 // Reached the end of the code cache. If there were deleted
10168 // elements, reuse the space for the first of them.
10169 if (deleted_index >= 0) {
10170 cache->set(deleted_index + kCodeCacheEntryNameOffset, *name);
10171 cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code);
10172 return;
10173 }
10174 }
10175
10176 // Extend the code cache with some new entries (at least one). Must be a
10177 // multiple of the entry size.
10178 int new_length = length + (length >> 1) + kCodeCacheEntrySize;
10179 new_length = new_length - new_length % kCodeCacheEntrySize;
10180 DCHECK((new_length % kCodeCacheEntrySize) == 0);
10181 cache = isolate->factory()->CopyFixedArrayAndGrow(cache, new_length - length);
10182
10183 // Add the (name, code) pair to the new cache.
10184 cache->set(length + kCodeCacheEntryNameOffset, *name);
10185 cache->set(length + kCodeCacheEntryCodeOffset, *code);
10186 code_cache->set_default_cache(*cache);
10187 }
10188
10189
10190 void CodeCache::UpdateNormalTypeCache(
10191 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) {
10192 // Adding a new entry can cause a new cache to be allocated.
10193 Handle<CodeCacheHashTable> cache(
10194 CodeCacheHashTable::cast(code_cache->normal_type_cache()));
10195 Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code);
10196 code_cache->set_normal_type_cache(*new_cache);
10197 }
10198
10199
10200 Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
10201 Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags));
10202 if (result->IsCode()) {
10203 if (Code::cast(result)->flags() == flags) return result;
10204 return GetHeap()->undefined_value();
10205 }
10206 return LookupNormalTypeCache(name, flags);
10207 }
10208
10209
10210 Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
10211 FixedArray* cache = default_cache();
10212 Heap* heap = GetHeap();
10213 Object* null = heap->null_value();
10214 Object* undefined = heap->undefined_value();
10215 int length = cache->length();
10216 DCHECK(name->IsUniqueName());
10217 for (int i = 0; i < length; i += kCodeCacheEntrySize) {
10218 Object* key = cache->get(i + kCodeCacheEntryNameOffset);
10219 // Skip deleted elements.
10220 if (key == null) continue;
10221 if (key == undefined) return key;
10222 DCHECK(key->IsUniqueName());
10223 if (name == key) {
10224 Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
10225 if (Code::RemoveTypeFromFlags(code->flags()) == flags) {
10226 return code;
10227 }
10228 }
10229 }
10230 return GetHeap()->undefined_value();
10231 }
10232
10233
10234 Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
10235 if (!normal_type_cache()->IsUndefined()) {
10236 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
10237 return cache->Lookup(name, flags);
10238 } else {
10239 return GetHeap()->undefined_value();
10240 }
10241 }
10242
10243
10244 int CodeCache::GetIndex(Object* name, Code* code) {
10245 if (code->type() == Code::NORMAL) {
10246 if (normal_type_cache()->IsUndefined()) return -1;
10247 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
10248 return cache->GetIndex(Name::cast(name), code->flags());
10249 }
10250
10251 FixedArray* array = default_cache();
10252 int len = array->length();
10253 for (int i = 0; i < len; i += kCodeCacheEntrySize) {
10254 if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
10255 }
10256 return -1;
10257 }
10258
10259
10260 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
10261 if (code->type() == Code::NORMAL) {
10262 DCHECK(!normal_type_cache()->IsUndefined());
10263 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
10264 DCHECK(cache->GetIndex(Name::cast(name), code->flags()) == index);
10265 cache->RemoveByIndex(index);
10266 } else {
10267 FixedArray* array = default_cache();
10268 DCHECK(array->length() >= index && array->get(index)->IsCode());
10269 // Use null instead of undefined for deleted elements to distinguish
10270 // deleted elements from unused elements. This distinction is used
10271 // when looking up in the cache and when updating the cache.
10272 DCHECK_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
10273 array->set_null(index - 1); // Name.
10274 array->set_null(index); // Code.
10275 }
10276 }
10277
10278
10279 // The key in the code cache hash table consists of the property name and the 10086 // The key in the code cache hash table consists of the property name and the
10280 // code object. The actual match is on the name and the code flags. If a key 10087 // code object. The actual match is on the name and the code flags. If a key
10281 // is created using the flags and not a code object it can only be used for 10088 // is created using the flags and not a code object it can only be used for
10282 // lookup not to create a new entry. 10089 // lookup not to create a new entry.
10283 class CodeCacheHashTableKey : public HashTableKey { 10090 class CodeCacheHashTableKey : public HashTableKey {
10284 public: 10091 public:
10285 CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags) 10092 CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
10286 : name_(name), flags_(flags), code_() { } 10093 : name_(name), flags_(flags), code_() {
10094 DCHECK(name_->IsUniqueName());
10095 }
10287 10096
10288 CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code) 10097 CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
10289 : name_(name), flags_(code->flags()), code_(code) { } 10098 : name_(name), flags_(code->flags()), code_(code) {
10099 DCHECK(name_->IsUniqueName());
10100 }
10290 10101
10291 bool IsMatch(Object* other) override { 10102 bool IsMatch(Object* other) override {
10292 if (!other->IsFixedArray()) return false; 10103 DCHECK(other->IsFixedArray());
10293 FixedArray* pair = FixedArray::cast(other); 10104 FixedArray* pair = FixedArray::cast(other);
10294 Name* name = Name::cast(pair->get(0)); 10105 Name* name = Name::cast(pair->get(0));
10295 Code::Flags flags = Code::cast(pair->get(1))->flags(); 10106 Code::Flags flags = Code::cast(pair->get(1))->flags();
10296 if (flags != flags_) { 10107 if (flags != flags_) return false;
10297 return false; 10108 DCHECK(name->IsUniqueName());
10298 } 10109 return *name_ == name;
10299 return name_->Equals(name);
10300 } 10110 }
10301 10111
10302 static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) { 10112 static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
10303 return name->Hash() ^ flags; 10113 return name->Hash() ^ flags;
10304 } 10114 }
10305 10115
10306 uint32_t Hash() override { return NameFlagsHashHelper(*name_, flags_); } 10116 uint32_t Hash() override { return NameFlagsHashHelper(*name_, flags_); }
10307 10117
10308 uint32_t HashForObject(Object* obj) override { 10118 uint32_t HashForObject(Object* obj) override {
10309 FixedArray* pair = FixedArray::cast(obj); 10119 FixedArray* pair = FixedArray::cast(obj);
(...skipping 11 matching lines...) Expand all
10321 } 10131 }
10322 10132
10323 private: 10133 private:
10324 Handle<Name> name_; 10134 Handle<Name> name_;
10325 Code::Flags flags_; 10135 Code::Flags flags_;
10326 // TODO(jkummerow): We should be able to get by without this. 10136 // TODO(jkummerow): We should be able to get by without this.
10327 MaybeHandle<Code> code_; 10137 MaybeHandle<Code> code_;
10328 }; 10138 };
10329 10139
10330 10140
10331 Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
10332 DisallowHeapAllocation no_alloc;
10333 CodeCacheHashTableKey key(handle(name), flags);
10334 int entry = FindEntry(&key);
10335 if (entry == kNotFound) return GetHeap()->undefined_value();
10336 return get(EntryToIndex(entry) + 1);
10337 }
10338
10339
10340 Handle<CodeCacheHashTable> CodeCacheHashTable::Put( 10141 Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
10341 Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) { 10142 Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
10342 CodeCacheHashTableKey key(name, code); 10143 CodeCacheHashTableKey key(name, code);
10343 10144
10344 Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key); 10145 Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
10345 10146
10346 int entry = new_cache->FindInsertionEntry(key.Hash()); 10147 int entry = new_cache->FindInsertionEntry(key.Hash());
10347 Handle<Object> k = key.AsHandle(cache->GetIsolate()); 10148 Handle<Object> k = key.AsHandle(cache->GetIsolate());
10348 10149
10349 new_cache->set(EntryToIndex(entry), *k); 10150 new_cache->set(EntryToIndex(entry), *k);
10350 new_cache->set(EntryToIndex(entry) + 1, *code);
10351 new_cache->ElementAdded(); 10151 new_cache->ElementAdded();
10352 return new_cache; 10152 return new_cache;
10353 } 10153 }
10354 10154
10355 10155 Code* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
10356 int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
10357 DisallowHeapAllocation no_alloc; 10156 DisallowHeapAllocation no_alloc;
10358 CodeCacheHashTableKey key(handle(name), flags); 10157 CodeCacheHashTableKey key(handle(name), flags);
10359 int entry = FindEntry(&key); 10158 int entry = FindEntry(&key);
10360 return (entry == kNotFound) ? -1 : entry; 10159 if (entry == kNotFound) return nullptr;
10160 return Code::cast(FixedArray::cast(get(EntryToIndex(entry)))->get(1));
10361 } 10161 }
10362 10162
10363
10364 void CodeCacheHashTable::RemoveByIndex(int index) {
10365 DCHECK(index >= 0);
10366 Heap* heap = GetHeap();
10367 set(EntryToIndex(index), heap->the_hole_value());
10368 set(EntryToIndex(index) + 1, heap->the_hole_value());
10369 ElementRemoved();
10370 }
10371
10372
10373 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> code_cache,
10374 MapHandleList* maps,
10375 Code::Flags flags,
10376 Handle<Code> code) {
10377 Isolate* isolate = code_cache->GetIsolate();
10378 if (code_cache->cache()->IsUndefined()) {
10379 Handle<PolymorphicCodeCacheHashTable> result =
10380 PolymorphicCodeCacheHashTable::New(
10381 isolate,
10382 PolymorphicCodeCacheHashTable::kInitialSize);
10383 code_cache->set_cache(*result);
10384 } else {
10385 // This entry shouldn't be contained in the cache yet.
10386 DCHECK(PolymorphicCodeCacheHashTable::cast(code_cache->cache())
10387 ->Lookup(maps, flags)->IsUndefined());
10388 }
10389 Handle<PolymorphicCodeCacheHashTable> hash_table =
10390 handle(PolymorphicCodeCacheHashTable::cast(code_cache->cache()));
10391 Handle<PolymorphicCodeCacheHashTable> new_cache =
10392 PolymorphicCodeCacheHashTable::Put(hash_table, maps, flags, code);
10393 code_cache->set_cache(*new_cache);
10394 }
10395
10396
10397 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
10398 Code::Flags flags) {
10399 if (!cache()->IsUndefined()) {
10400 PolymorphicCodeCacheHashTable* hash_table =
10401 PolymorphicCodeCacheHashTable::cast(cache());
10402 return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
10403 } else {
10404 return GetIsolate()->factory()->undefined_value();
10405 }
10406 }
10407
10408
10409 // Despite their name, object of this class are not stored in the actual
10410 // hash table; instead they're temporarily used for lookups. It is therefore
10411 // safe to have a weak (non-owning) pointer to a MapList as a member field.
10412 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
10413 public:
10414 // Callers must ensure that |maps| outlives the newly constructed object.
10415 PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
10416 : maps_(maps),
10417 code_flags_(code_flags) {}
10418
10419 bool IsMatch(Object* other) override {
10420 MapHandleList other_maps(kDefaultListAllocationSize);
10421 int other_flags;
10422 FromObject(other, &other_flags, &other_maps);
10423 if (code_flags_ != other_flags) return false;
10424 if (maps_->length() != other_maps.length()) return false;
10425 // Compare just the hashes first because it's faster.
10426 int this_hash = MapsHashHelper(maps_, code_flags_);
10427 int other_hash = MapsHashHelper(&other_maps, other_flags);
10428 if (this_hash != other_hash) return false;
10429
10430 // Full comparison: for each map in maps_, look for an equivalent map in
10431 // other_maps. This implementation is slow, but probably good enough for
10432 // now because the lists are short (<= 4 elements currently).
10433 for (int i = 0; i < maps_->length(); ++i) {
10434 bool match_found = false;
10435 for (int j = 0; j < other_maps.length(); ++j) {
10436 if (*(maps_->at(i)) == *(other_maps.at(j))) {
10437 match_found = true;
10438 break;
10439 }
10440 }
10441 if (!match_found) return false;
10442 }
10443 return true;
10444 }
10445
10446 static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
10447 uint32_t hash = code_flags;
10448 for (int i = 0; i < maps->length(); ++i) {
10449 hash ^= maps->at(i)->Hash();
10450 }
10451 return hash;
10452 }
10453
10454 uint32_t Hash() override { return MapsHashHelper(maps_, code_flags_); }
10455
10456 uint32_t HashForObject(Object* obj) override {
10457 MapHandleList other_maps(kDefaultListAllocationSize);
10458 int other_flags;
10459 FromObject(obj, &other_flags, &other_maps);
10460 return MapsHashHelper(&other_maps, other_flags);
10461 }
10462
10463 MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
10464 // The maps in |maps_| must be copied to a newly allocated FixedArray,
10465 // both because the referenced MapList is short-lived, and because C++
10466 // objects can't be stored in the heap anyway.
10467 Handle<FixedArray> list =
10468 isolate->factory()->NewUninitializedFixedArray(maps_->length() + 1);
10469 list->set(0, Smi::FromInt(code_flags_));
10470 for (int i = 0; i < maps_->length(); ++i) {
10471 list->set(i + 1, *maps_->at(i));
10472 }
10473 return list;
10474 }
10475
10476 private:
10477 static MapHandleList* FromObject(Object* obj,
10478 int* code_flags,
10479 MapHandleList* maps) {
10480 FixedArray* list = FixedArray::cast(obj);
10481 maps->Rewind(0);
10482 *code_flags = Smi::cast(list->get(0))->value();
10483 for (int i = 1; i < list->length(); ++i) {
10484 maps->Add(Handle<Map>(Map::cast(list->get(i))));
10485 }
10486 return maps;
10487 }
10488
10489 MapHandleList* maps_; // weak.
10490 int code_flags_;
10491 static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
10492 };
10493
10494
10495 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
10496 int code_kind) {
10497 DisallowHeapAllocation no_alloc;
10498 PolymorphicCodeCacheHashTableKey key(maps, code_kind);
10499 int entry = FindEntry(&key);
10500 if (entry == kNotFound) return GetHeap()->undefined_value();
10501 return get(EntryToIndex(entry) + 1);
10502 }
10503
10504
10505 Handle<PolymorphicCodeCacheHashTable> PolymorphicCodeCacheHashTable::Put(
10506 Handle<PolymorphicCodeCacheHashTable> hash_table,
10507 MapHandleList* maps,
10508 int code_kind,
10509 Handle<Code> code) {
10510 PolymorphicCodeCacheHashTableKey key(maps, code_kind);
10511 Handle<PolymorphicCodeCacheHashTable> cache =
10512 EnsureCapacity(hash_table, 1, &key);
10513 int entry = cache->FindInsertionEntry(key.Hash());
10514
10515 Handle<Object> obj = key.AsHandle(hash_table->GetIsolate());
10516 cache->set(EntryToIndex(entry), *obj);
10517 cache->set(EntryToIndex(entry) + 1, *code);
10518 cache->ElementAdded();
10519 return cache;
10520 }
10521
10522
10523 void FixedArray::Shrink(int new_length) { 10163 void FixedArray::Shrink(int new_length) {
10524 DCHECK(0 <= new_length && new_length <= length()); 10164 DCHECK(0 <= new_length && new_length <= length());
10525 if (new_length < length()) { 10165 if (new_length < length()) {
10526 GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( 10166 GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
10527 this, length() - new_length); 10167 this, length() - new_length);
10528 } 10168 }
10529 } 10169 }
10530 10170
10531 10171
10532 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) { 10172 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
(...skipping 4263 matching lines...) Expand 10 before | Expand all | Expand 10 after
14796 << handler_offset << " (prediction=" << prediction << ")\n"; 14436 << handler_offset << " (prediction=" << prediction << ")\n";
14797 } 14437 }
14798 } 14438 }
14799 14439
14800 14440
14801 const char* Code::ICState2String(InlineCacheState state) { 14441 const char* Code::ICState2String(InlineCacheState state) {
14802 switch (state) { 14442 switch (state) {
14803 case UNINITIALIZED: return "UNINITIALIZED"; 14443 case UNINITIALIZED: return "UNINITIALIZED";
14804 case PREMONOMORPHIC: return "PREMONOMORPHIC"; 14444 case PREMONOMORPHIC: return "PREMONOMORPHIC";
14805 case MONOMORPHIC: return "MONOMORPHIC"; 14445 case MONOMORPHIC: return "MONOMORPHIC";
14806 case PROTOTYPE_FAILURE: 14446 case RECOMPUTE_HANDLER:
14807 return "PROTOTYPE_FAILURE"; 14447 return "RECOMPUTE_HANDLER";
14808 case POLYMORPHIC: return "POLYMORPHIC"; 14448 case POLYMORPHIC: return "POLYMORPHIC";
14809 case MEGAMORPHIC: return "MEGAMORPHIC"; 14449 case MEGAMORPHIC: return "MEGAMORPHIC";
14810 case GENERIC: return "GENERIC"; 14450 case GENERIC: return "GENERIC";
14811 case DEBUG_STUB: return "DEBUG_STUB"; 14451 case DEBUG_STUB: return "DEBUG_STUB";
14812 } 14452 }
14813 UNREACHABLE(); 14453 UNREACHABLE();
14814 return NULL; 14454 return NULL;
14815 } 14455 }
14816 14456
14817 14457
14818 const char* Code::StubType2String(StubType type) {
14819 switch (type) {
14820 case NORMAL: return "NORMAL";
14821 case FAST: return "FAST";
14822 }
14823 UNREACHABLE(); // keep the compiler happy
14824 return NULL;
14825 }
14826
14827
14828 void Code::PrintExtraICState(std::ostream& os, // NOLINT 14458 void Code::PrintExtraICState(std::ostream& os, // NOLINT
14829 Kind kind, ExtraICState extra) { 14459 Kind kind, ExtraICState extra) {
14830 os << "extra_ic_state = "; 14460 os << "extra_ic_state = ";
14831 if ((kind == STORE_IC || kind == KEYED_STORE_IC) && 14461 if ((kind == STORE_IC || kind == KEYED_STORE_IC) &&
14832 is_strict(static_cast<LanguageMode>(extra))) { 14462 is_strict(static_cast<LanguageMode>(extra))) {
14833 os << "STRICT\n"; 14463 os << "STRICT\n";
14834 } else { 14464 } else {
14835 os << extra << "\n"; 14465 os << extra << "\n";
14836 } 14466 }
14837 } 14467 }
14838 14468
14839 14469
14840 void Code::Disassemble(const char* name, std::ostream& os) { // NOLINT 14470 void Code::Disassemble(const char* name, std::ostream& os) { // NOLINT
14841 os << "kind = " << Kind2String(kind()) << "\n"; 14471 os << "kind = " << Kind2String(kind()) << "\n";
14842 if (IsCodeStubOrIC()) { 14472 if (IsCodeStubOrIC()) {
14843 const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this)); 14473 const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this));
14844 os << "major_key = " << (n == NULL ? "null" : n) << "\n"; 14474 os << "major_key = " << (n == NULL ? "null" : n) << "\n";
14845 } 14475 }
14846 if (is_inline_cache_stub()) { 14476 if (is_inline_cache_stub()) {
14847 os << "ic_state = " << ICState2String(ic_state()) << "\n"; 14477 os << "ic_state = " << ICState2String(ic_state()) << "\n";
14848 PrintExtraICState(os, kind(), extra_ic_state()); 14478 PrintExtraICState(os, kind(), extra_ic_state());
14849 if (ic_state() == MONOMORPHIC) {
14850 os << "type = " << StubType2String(type()) << "\n";
14851 }
14852 if (is_compare_ic_stub()) { 14479 if (is_compare_ic_stub()) {
14853 DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC); 14480 DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
14854 CompareICStub stub(stub_key(), GetIsolate()); 14481 CompareICStub stub(stub_key(), GetIsolate());
14855 os << "compare_state = " << CompareICState::GetStateName(stub.left()) 14482 os << "compare_state = " << CompareICState::GetStateName(stub.left())
14856 << "*" << CompareICState::GetStateName(stub.right()) << " -> " 14483 << "*" << CompareICState::GetStateName(stub.right()) << " -> "
14857 << CompareICState::GetStateName(stub.state()) << "\n"; 14484 << CompareICState::GetStateName(stub.state()) << "\n";
14858 os << "compare_operation = " << Token::Name(stub.op()) << "\n"; 14485 os << "compare_operation = " << Token::Name(stub.op()) << "\n";
14859 } 14486 }
14860 } 14487 }
14861 if ((name != nullptr) && (name[0] != '\0')) { 14488 if ((name != nullptr) && (name[0] != '\0')) {
(...skipping 2297 matching lines...) Expand 10 before | Expand all | Expand 10 after
17159 16786
17160 // Copy prefix to new array. 16787 // Copy prefix to new array.
17161 for (int i = kPrefixStartIndex; 16788 for (int i = kPrefixStartIndex;
17162 i < kPrefixStartIndex + Shape::kPrefixSize; 16789 i < kPrefixStartIndex + Shape::kPrefixSize;
17163 i++) { 16790 i++) {
17164 new_table->set(i, get(i), mode); 16791 new_table->set(i, get(i), mode);
17165 } 16792 }
17166 16793
17167 // Rehash the elements. 16794 // Rehash the elements.
17168 int capacity = this->Capacity(); 16795 int capacity = this->Capacity();
16796 Heap* heap = new_table->GetHeap();
16797 Object* the_hole = heap->the_hole_value();
16798 Object* undefined = heap->undefined_value();
17169 for (int i = 0; i < capacity; i++) { 16799 for (int i = 0; i < capacity; i++) {
17170 uint32_t from_index = EntryToIndex(i); 16800 uint32_t from_index = EntryToIndex(i);
17171 Object* k = this->get(from_index); 16801 Object* k = this->get(from_index);
17172 if (IsKey(k)) { 16802 if (k != the_hole && k != undefined) {
17173 uint32_t hash = this->HashForObject(key, k); 16803 uint32_t hash = this->HashForObject(key, k);
17174 uint32_t insertion_index = 16804 uint32_t insertion_index =
17175 EntryToIndex(new_table->FindInsertionEntry(hash)); 16805 EntryToIndex(new_table->FindInsertionEntry(hash));
17176 for (int j = 0; j < Shape::kEntrySize; j++) { 16806 for (int j = 0; j < Shape::kEntrySize; j++) {
17177 new_table->set(insertion_index + j, get(from_index + j), mode); 16807 new_table->set(insertion_index + j, get(from_index + j), mode);
17178 } 16808 }
17179 } 16809 }
17180 } 16810 }
17181 new_table->SetNumberOfElements(NumberOfElements()); 16811 new_table->SetNumberOfElements(NumberOfElements());
17182 new_table->SetNumberOfDeletedElements(0); 16812 new_table->SetNumberOfDeletedElements(0);
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
17326 return new_table; 16956 return new_table;
17327 } 16957 }
17328 16958
17329 16959
17330 template<typename Derived, typename Shape, typename Key> 16960 template<typename Derived, typename Shape, typename Key>
17331 uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) { 16961 uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) {
17332 uint32_t capacity = Capacity(); 16962 uint32_t capacity = Capacity();
17333 uint32_t entry = FirstProbe(hash, capacity); 16963 uint32_t entry = FirstProbe(hash, capacity);
17334 uint32_t count = 1; 16964 uint32_t count = 1;
17335 // EnsureCapacity will guarantee the hash table is never full. 16965 // EnsureCapacity will guarantee the hash table is never full.
16966 Heap* heap = GetHeap();
16967 Object* the_hole = heap->the_hole_value();
16968 Object* undefined = heap->undefined_value();
17336 while (true) { 16969 while (true) {
17337 Object* element = KeyAt(entry); 16970 Object* element = KeyAt(entry);
17338 if (element->IsUndefined() || element->IsTheHole()) break; 16971 if (element == the_hole || element == undefined) break;
17339 entry = NextProbe(entry, count++, capacity); 16972 entry = NextProbe(entry, count++, capacity);
17340 } 16973 }
17341 return entry; 16974 return entry;
17342 } 16975 }
17343 16976
17344 16977
17345 // Force instantiation of template instances class. 16978 // Force instantiation of template instances class.
17346 // Please note this list is compiler dependent. 16979 // Please note this list is compiler dependent.
17347 16980
17348 template class HashTable<StringTable, StringTableShape, HashTableKey*>; 16981 template class HashTable<StringTable, StringTableShape, HashTableKey*>;
(...skipping 1463 matching lines...) Expand 10 before | Expand all | Expand 10 after
18812 // and point the bucket to the new entry. 18445 // and point the bucket to the new entry.
18813 table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry)); 18446 table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
18814 table->SetNumberOfElements(nof + 1); 18447 table->SetNumberOfElements(nof + 1);
18815 return table; 18448 return table;
18816 } 18449 }
18817 18450
18818 18451
18819 template<class Derived, class Iterator, int entrysize> 18452 template<class Derived, class Iterator, int entrysize>
18820 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash( 18453 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
18821 Handle<Derived> table, int new_capacity) { 18454 Handle<Derived> table, int new_capacity) {
18455 Isolate* isolate = table->GetIsolate();
18456 Heap* heap = isolate->heap();
18822 DCHECK(!table->IsObsolete()); 18457 DCHECK(!table->IsObsolete());
18823 18458
18824 Handle<Derived> new_table = 18459 Handle<Derived> new_table = Allocate(
18825 Allocate(table->GetIsolate(), 18460 isolate, new_capacity, heap->InNewSpace(*table) ? NOT_TENURED : TENURED);
18826 new_capacity,
18827 table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
18828 int nof = table->NumberOfElements(); 18461 int nof = table->NumberOfElements();
18829 int nod = table->NumberOfDeletedElements(); 18462 int nod = table->NumberOfDeletedElements();
18830 int new_buckets = new_table->NumberOfBuckets(); 18463 int new_buckets = new_table->NumberOfBuckets();
18831 int new_entry = 0; 18464 int new_entry = 0;
18832 int removed_holes_index = 0; 18465 int removed_holes_index = 0;
18833 18466
18467 DisallowHeapAllocation no_gc;
18468 Object* the_hole = heap->the_hole_value();
18834 for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) { 18469 for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
18835 Object* key = table->KeyAt(old_entry); 18470 Object* key = table->KeyAt(old_entry);
18836 if (key->IsTheHole()) { 18471 if (key == the_hole) {
18837 table->SetRemovedIndexAt(removed_holes_index++, old_entry); 18472 table->SetRemovedIndexAt(removed_holes_index++, old_entry);
18838 continue; 18473 continue;
18839 } 18474 }
18840 18475
18841 Object* hash = key->GetHash(); 18476 Object* hash = key->GetHash();
18842 int bucket = Smi::cast(hash)->value() & (new_buckets - 1); 18477 int bucket = Smi::cast(hash)->value() & (new_buckets - 1);
18843 Object* chain_entry = new_table->get(kHashTableStartIndex + bucket); 18478 Object* chain_entry = new_table->get(kHashTableStartIndex + bucket);
18844 new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry)); 18479 new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
18845 int new_index = new_table->EntryToIndex(new_entry); 18480 int new_index = new_table->EntryToIndex(new_entry);
18846 int old_index = table->EntryToIndex(old_entry); 18481 int old_index = table->EntryToIndex(old_entry);
(...skipping 916 matching lines...) Expand 10 before | Expand all | Expand 10 after
19763 if (cell->value() != *new_value) { 19398 if (cell->value() != *new_value) {
19764 cell->set_value(*new_value); 19399 cell->set_value(*new_value);
19765 Isolate* isolate = cell->GetIsolate(); 19400 Isolate* isolate = cell->GetIsolate();
19766 cell->dependent_code()->DeoptimizeDependentCodeGroup( 19401 cell->dependent_code()->DeoptimizeDependentCodeGroup(
19767 isolate, DependentCode::kPropertyCellChangedGroup); 19402 isolate, DependentCode::kPropertyCellChangedGroup);
19768 } 19403 }
19769 } 19404 }
19770 19405
19771 } // namespace internal 19406 } // namespace internal
19772 } // namespace v8 19407 } // namespace v8
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