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 |