Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 7259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7270 (insertion_index == descriptors->number_of_descriptors() - 1) | 7270 (insertion_index == descriptors->number_of_descriptors() - 1) |
| 7271 ? SIMPLE_TRANSITION | 7271 ? SIMPLE_TRANSITION |
| 7272 : FULL_TRANSITION; | 7272 : FULL_TRANSITION; |
| 7273 return CopyReplaceDescriptors(map, new_descriptors, flag, key, simple_flag); | 7273 return CopyReplaceDescriptors(map, new_descriptors, flag, key, simple_flag); |
| 7274 } | 7274 } |
| 7275 | 7275 |
| 7276 | 7276 |
| 7277 void Map::UpdateCodeCache(Handle<Map> map, | 7277 void Map::UpdateCodeCache(Handle<Map> map, |
| 7278 Handle<Name> name, | 7278 Handle<Name> name, |
| 7279 Handle<Code> code) { | 7279 Handle<Code> code) { |
| 7280 Isolate* isolate = map->GetIsolate(); | 7280 Isolate* isolate = map->GetIsolate(); |
|
ulan
2014/04/15 15:17:19
Note that map->code_cache is cleared on GC.
Could
| |
| 7281 CALL_HEAP_FUNCTION_VOID(isolate, | 7281 // Allocate the code cache if not present. |
| 7282 map->UpdateCodeCache(*name, *code)); | 7282 if (map->code_cache()->IsFixedArray()) { |
| 7283 Handle<Object> result = isolate->factory()->NewCodeCache(); | |
| 7284 map->set_code_cache(*result); | |
| 7285 } | |
| 7286 | |
| 7287 // Update the code cache. | |
| 7288 Handle<CodeCache> code_cache(CodeCache::cast(map->code_cache()), isolate); | |
| 7289 CodeCache::Update(code_cache, name, code); | |
| 7283 } | 7290 } |
| 7284 | 7291 |
| 7285 | 7292 |
| 7286 MaybeObject* Map::UpdateCodeCache(Name* name, Code* code) { | |
| 7287 // Allocate the code cache if not present. | |
| 7288 if (code_cache()->IsFixedArray()) { | |
| 7289 Object* result; | |
| 7290 { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache(); | |
| 7291 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 7292 } | |
| 7293 set_code_cache(result); | |
| 7294 } | |
| 7295 | |
| 7296 // Update the code cache. | |
| 7297 return CodeCache::cast(code_cache())->Update(name, code); | |
| 7298 } | |
| 7299 | |
| 7300 | |
| 7301 Object* Map::FindInCodeCache(Name* name, Code::Flags flags) { | 7293 Object* Map::FindInCodeCache(Name* name, Code::Flags flags) { |
| 7302 // Do a lookup if a code cache exists. | 7294 // Do a lookup if a code cache exists. |
| 7303 if (!code_cache()->IsFixedArray()) { | 7295 if (!code_cache()->IsFixedArray()) { |
| 7304 return CodeCache::cast(code_cache())->Lookup(name, flags); | 7296 return CodeCache::cast(code_cache())->Lookup(name, flags); |
| 7305 } else { | 7297 } else { |
| 7306 return GetHeap()->undefined_value(); | 7298 return GetHeap()->undefined_value(); |
| 7307 } | 7299 } |
| 7308 } | 7300 } |
| 7309 | 7301 |
| 7310 | 7302 |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7524 } else { | 7516 } else { |
| 7525 TraversableMap* parent = current->GetAndResetParent(); | 7517 TraversableMap* parent = current->GetAndResetParent(); |
| 7526 callback(current, data); | 7518 callback(current, data); |
| 7527 if (current == this) break; | 7519 if (current == this) break; |
| 7528 current = parent; | 7520 current = parent; |
| 7529 } | 7521 } |
| 7530 } | 7522 } |
| 7531 } | 7523 } |
| 7532 | 7524 |
| 7533 | 7525 |
| 7534 MaybeObject* CodeCache::Update(Name* name, Code* code) { | 7526 void CodeCache::Update( |
| 7527 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) { | |
| 7535 // The number of monomorphic stubs for normal load/store/call IC's can grow to | 7528 // The number of monomorphic stubs for normal load/store/call IC's can grow to |
| 7536 // a large number and therefore they need to go into a hash table. They are | 7529 // a large number and therefore they need to go into a hash table. They are |
| 7537 // used to load global properties from cells. | 7530 // used to load global properties from cells. |
| 7538 if (code->type() == Code::NORMAL) { | 7531 if (code->type() == Code::NORMAL) { |
| 7539 // Make sure that a hash table is allocated for the normal load code cache. | 7532 // Make sure that a hash table is allocated for the normal load code cache. |
| 7540 if (normal_type_cache()->IsUndefined()) { | 7533 if (code_cache->normal_type_cache()->IsUndefined()) { |
| 7541 Object* result; | 7534 Handle<Object> result = |
| 7542 { MaybeObject* maybe_result = | 7535 CodeCacheHashTable::New(code_cache->GetIsolate(), |
| 7543 CodeCacheHashTable::Allocate(GetHeap(), | 7536 CodeCacheHashTable::kInitialSize); |
| 7544 CodeCacheHashTable::kInitialSize); | 7537 code_cache->set_normal_type_cache(*result); |
| 7545 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 7546 } | |
| 7547 set_normal_type_cache(result); | |
| 7548 } | 7538 } |
| 7549 return UpdateNormalTypeCache(name, code); | 7539 UpdateNormalTypeCache(code_cache, name, code); |
| 7550 } else { | 7540 } else { |
| 7551 ASSERT(default_cache()->IsFixedArray()); | 7541 ASSERT(code_cache->default_cache()->IsFixedArray()); |
| 7552 return UpdateDefaultCache(name, code); | 7542 UpdateDefaultCache(code_cache, name, code); |
| 7553 } | 7543 } |
| 7554 } | 7544 } |
| 7555 | 7545 |
| 7556 | 7546 |
| 7557 MaybeObject* CodeCache::UpdateDefaultCache(Name* name, Code* code) { | 7547 void CodeCache::UpdateDefaultCache( |
| 7548 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) { | |
| 7558 // When updating the default code cache we disregard the type encoded in the | 7549 // When updating the default code cache we disregard the type encoded in the |
| 7559 // flags. This allows call constant stubs to overwrite call field | 7550 // flags. This allows call constant stubs to overwrite call field |
| 7560 // stubs, etc. | 7551 // stubs, etc. |
| 7561 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags()); | 7552 Code::Flags flags = Code::RemoveTypeFromFlags(code->flags()); |
| 7562 | 7553 |
| 7563 // First check whether we can update existing code cache without | 7554 // First check whether we can update existing code cache without |
| 7564 // extending it. | 7555 // extending it. |
| 7565 FixedArray* cache = default_cache(); | 7556 Handle<FixedArray> cache = handle(code_cache->default_cache()); |
| 7566 int length = cache->length(); | 7557 int length = cache->length(); |
| 7567 int deleted_index = -1; | 7558 { |
| 7568 for (int i = 0; i < length; i += kCodeCacheEntrySize) { | 7559 DisallowHeapAllocation no_alloc; |
| 7569 Object* key = cache->get(i); | 7560 int deleted_index = -1; |
| 7570 if (key->IsNull()) { | 7561 for (int i = 0; i < length; i += kCodeCacheEntrySize) { |
| 7571 if (deleted_index < 0) deleted_index = i; | 7562 Object* key = cache->get(i); |
| 7572 continue; | 7563 if (key->IsNull()) { |
| 7564 if (deleted_index < 0) deleted_index = i; | |
| 7565 continue; | |
| 7566 } | |
| 7567 if (key->IsUndefined()) { | |
| 7568 if (deleted_index >= 0) i = deleted_index; | |
| 7569 cache->set(i + kCodeCacheEntryNameOffset, *name); | |
| 7570 cache->set(i + kCodeCacheEntryCodeOffset, *code); | |
| 7571 return; | |
| 7572 } | |
| 7573 if (name->Equals(Name::cast(key))) { | |
| 7574 Code::Flags found = | |
| 7575 Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags(); | |
| 7576 if (Code::RemoveTypeFromFlags(found) == flags) { | |
| 7577 cache->set(i + kCodeCacheEntryCodeOffset, *code); | |
| 7578 return; | |
| 7579 } | |
| 7580 } | |
| 7573 } | 7581 } |
| 7574 if (key->IsUndefined()) { | 7582 |
| 7575 if (deleted_index >= 0) i = deleted_index; | 7583 // Reached the end of the code cache. If there were deleted |
| 7576 cache->set(i + kCodeCacheEntryNameOffset, name); | 7584 // elements, reuse the space for the first of them. |
| 7577 cache->set(i + kCodeCacheEntryCodeOffset, code); | 7585 if (deleted_index >= 0) { |
| 7578 return this; | 7586 cache->set(deleted_index + kCodeCacheEntryNameOffset, *name); |
| 7579 } | 7587 cache->set(deleted_index + kCodeCacheEntryCodeOffset, *code); |
| 7580 if (name->Equals(Name::cast(key))) { | 7588 return; |
| 7581 Code::Flags found = | |
| 7582 Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags(); | |
| 7583 if (Code::RemoveTypeFromFlags(found) == flags) { | |
| 7584 cache->set(i + kCodeCacheEntryCodeOffset, code); | |
| 7585 return this; | |
| 7586 } | |
| 7587 } | 7589 } |
| 7588 } | 7590 } |
| 7589 | 7591 |
| 7590 // Reached the end of the code cache. If there were deleted | |
| 7591 // elements, reuse the space for the first of them. | |
| 7592 if (deleted_index >= 0) { | |
| 7593 cache->set(deleted_index + kCodeCacheEntryNameOffset, name); | |
| 7594 cache->set(deleted_index + kCodeCacheEntryCodeOffset, code); | |
| 7595 return this; | |
| 7596 } | |
| 7597 | |
| 7598 // Extend the code cache with some new entries (at least one). Must be a | 7592 // Extend the code cache with some new entries (at least one). Must be a |
| 7599 // multiple of the entry size. | 7593 // multiple of the entry size. |
| 7600 int new_length = length + ((length >> 1)) + kCodeCacheEntrySize; | 7594 int new_length = length + ((length >> 1)) + kCodeCacheEntrySize; |
| 7601 new_length = new_length - new_length % kCodeCacheEntrySize; | 7595 new_length = new_length - new_length % kCodeCacheEntrySize; |
| 7602 ASSERT((new_length % kCodeCacheEntrySize) == 0); | 7596 ASSERT((new_length % kCodeCacheEntrySize) == 0); |
| 7603 Object* result; | 7597 cache = FixedArray::CopySize(cache, new_length); |
| 7604 { MaybeObject* maybe_result = cache->CopySize(new_length); | |
| 7605 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 7606 } | |
| 7607 | 7598 |
| 7608 // Add the (name, code) pair to the new cache. | 7599 // Add the (name, code) pair to the new cache. |
| 7609 cache = FixedArray::cast(result); | 7600 cache->set(length + kCodeCacheEntryNameOffset, *name); |
| 7610 cache->set(length + kCodeCacheEntryNameOffset, name); | 7601 cache->set(length + kCodeCacheEntryCodeOffset, *code); |
| 7611 cache->set(length + kCodeCacheEntryCodeOffset, code); | 7602 code_cache->set_default_cache(*cache); |
| 7612 set_default_cache(cache); | |
| 7613 return this; | |
| 7614 } | 7603 } |
| 7615 | 7604 |
| 7616 | 7605 |
| 7617 MaybeObject* CodeCache::UpdateNormalTypeCache(Name* name, Code* code) { | 7606 void CodeCache::UpdateNormalTypeCache( |
| 7607 Handle<CodeCache> code_cache, Handle<Name> name, Handle<Code> code) { | |
| 7618 // Adding a new entry can cause a new cache to be allocated. | 7608 // Adding a new entry can cause a new cache to be allocated. |
| 7619 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); | 7609 Handle<CodeCacheHashTable> cache( |
| 7620 Object* new_cache; | 7610 CodeCacheHashTable::cast(code_cache->normal_type_cache())); |
| 7621 { MaybeObject* maybe_new_cache = cache->Put(name, code); | 7611 Handle<Object> new_cache = CodeCacheHashTable::Put(cache, name, code); |
| 7622 if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache; | 7612 code_cache->set_normal_type_cache(*new_cache); |
| 7623 } | |
| 7624 set_normal_type_cache(new_cache); | |
| 7625 return this; | |
| 7626 } | 7613 } |
| 7627 | 7614 |
| 7628 | 7615 |
| 7629 Object* CodeCache::Lookup(Name* name, Code::Flags flags) { | 7616 Object* CodeCache::Lookup(Name* name, Code::Flags flags) { |
| 7630 Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags)); | 7617 Object* result = LookupDefaultCache(name, Code::RemoveTypeFromFlags(flags)); |
| 7631 if (result->IsCode()) { | 7618 if (result->IsCode()) { |
| 7632 if (Code::cast(result)->flags() == flags) return result; | 7619 if (Code::cast(result)->flags() == flags) return result; |
| 7633 return GetHeap()->undefined_value(); | 7620 return GetHeap()->undefined_value(); |
| 7634 } | 7621 } |
| 7635 return LookupNormalTypeCache(name, flags); | 7622 return LookupNormalTypeCache(name, flags); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7781 if (!maybe_k->ToObject(&k)) return maybe_k; | 7768 if (!maybe_k->ToObject(&k)) return maybe_k; |
| 7782 } | 7769 } |
| 7783 | 7770 |
| 7784 cache->set(EntryToIndex(entry), k); | 7771 cache->set(EntryToIndex(entry), k); |
| 7785 cache->set(EntryToIndex(entry) + 1, code); | 7772 cache->set(EntryToIndex(entry) + 1, code); |
| 7786 cache->ElementAdded(); | 7773 cache->ElementAdded(); |
| 7787 return cache; | 7774 return cache; |
| 7788 } | 7775 } |
| 7789 | 7776 |
| 7790 | 7777 |
| 7778 Handle<CodeCacheHashTable> CodeCacheHashTable::Put( | |
| 7779 Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) { | |
| 7780 Isolate* isolate = cache->GetIsolate(); | |
| 7781 CALL_HEAP_FUNCTION(isolate, | |
| 7782 cache->Put(*name, *code), | |
| 7783 CodeCacheHashTable); | |
| 7784 } | |
| 7785 | |
| 7786 | |
| 7791 int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) { | 7787 int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) { |
| 7792 CodeCacheHashTableKey key(name, flags); | 7788 CodeCacheHashTableKey key(name, flags); |
| 7793 int entry = FindEntry(&key); | 7789 int entry = FindEntry(&key); |
| 7794 return (entry == kNotFound) ? -1 : entry; | 7790 return (entry == kNotFound) ? -1 : entry; |
| 7795 } | 7791 } |
| 7796 | 7792 |
| 7797 | 7793 |
| 7798 void CodeCacheHashTable::RemoveByIndex(int index) { | 7794 void CodeCacheHashTable::RemoveByIndex(int index) { |
| 7799 ASSERT(index >= 0); | 7795 ASSERT(index >= 0); |
| 7800 Heap* heap = GetHeap(); | 7796 Heap* heap = GetHeap(); |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8050 // be an immortal immutable object. | 8046 // be an immortal immutable object. |
| 8051 result->set_map_no_write_barrier(map()); | 8047 result->set_map_no_write_barrier(map()); |
| 8052 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); | 8048 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 8053 for (int i = 0; i < len; i++) { | 8049 for (int i = 0; i < len; i++) { |
| 8054 result->set(i, get(i), mode); | 8050 result->set(i, get(i), mode); |
| 8055 } | 8051 } |
| 8056 return result; | 8052 return result; |
| 8057 } | 8053 } |
| 8058 | 8054 |
| 8059 | 8055 |
| 8056 Handle<FixedArray> FixedArray::CopySize( | |
| 8057 Handle<FixedArray> array, int new_length, PretenureFlag pretenure) { | |
| 8058 Isolate* isolate = array->GetIsolate(); | |
| 8059 CALL_HEAP_FUNCTION(isolate, | |
| 8060 array->CopySize(new_length, pretenure), | |
| 8061 FixedArray); | |
| 8062 } | |
| 8063 | |
| 8064 | |
| 8060 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) { | 8065 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) { |
| 8061 DisallowHeapAllocation no_gc; | 8066 DisallowHeapAllocation no_gc; |
| 8062 WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc); | 8067 WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc); |
| 8063 for (int index = 0; index < len; index++) { | 8068 for (int index = 0; index < len; index++) { |
| 8064 dest->set(dest_pos+index, get(pos+index), mode); | 8069 dest->set(dest_pos+index, get(pos+index), mode); |
| 8065 } | 8070 } |
| 8066 } | 8071 } |
| 8067 | 8072 |
| 8068 | 8073 |
| 8069 #ifdef DEBUG | 8074 #ifdef DEBUG |
| (...skipping 8524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 16594 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16599 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 16595 static const char* error_messages_[] = { | 16600 static const char* error_messages_[] = { |
| 16596 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16601 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 16597 }; | 16602 }; |
| 16598 #undef ERROR_MESSAGES_TEXTS | 16603 #undef ERROR_MESSAGES_TEXTS |
| 16599 return error_messages_[reason]; | 16604 return error_messages_[reason]; |
| 16600 } | 16605 } |
| 16601 | 16606 |
| 16602 | 16607 |
| 16603 } } // namespace v8::internal | 16608 } } // namespace v8::internal |
| OLD | NEW |