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

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

Powered by Google App Engine
This is Rietveld 408576698