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

Side by Side Diff: runtime/vm/object.cc

Issue 304253002: Hash tables templates, wrapping Array. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 11 matching lines...) Expand all
22 #include "vm/dart_entry.h" 22 #include "vm/dart_entry.h"
23 #include "vm/datastream.h" 23 #include "vm/datastream.h"
24 #include "vm/debugger.h" 24 #include "vm/debugger.h"
25 #include "vm/deopt_instructions.h" 25 #include "vm/deopt_instructions.h"
26 #include "vm/disassembler.h" 26 #include "vm/disassembler.h"
27 #include "vm/double_conversion.h" 27 #include "vm/double_conversion.h"
28 #include "vm/exceptions.h" 28 #include "vm/exceptions.h"
29 #include "vm/flow_graph_builder.h" 29 #include "vm/flow_graph_builder.h"
30 #include "vm/flow_graph_compiler.h" 30 #include "vm/flow_graph_compiler.h"
31 #include "vm/growable_array.h" 31 #include "vm/growable_array.h"
32 #include "vm/hash_table.h"
32 #include "vm/heap.h" 33 #include "vm/heap.h"
33 #include "vm/intermediate_language.h" 34 #include "vm/intermediate_language.h"
34 #include "vm/intrinsifier.h" 35 #include "vm/intrinsifier.h"
35 #include "vm/longjump.h" 36 #include "vm/longjump.h"
36 #include "vm/object_id_ring.h" 37 #include "vm/object_id_ring.h"
37 #include "vm/object_store.h" 38 #include "vm/object_store.h"
38 #include "vm/parser.h" 39 #include "vm/parser.h"
39 #include "vm/reusable_handles.h" 40 #include "vm/reusable_handles.h"
40 #include "vm/runtime_entry.h" 41 #include "vm/runtime_entry.h"
41 #include "vm/scopes.h" 42 #include "vm/scopes.h"
(...skipping 8444 matching lines...) Expand 10 before | Expand all | Expand 10 after
8486 obj = LookupLocalObject(accessor_name); 8487 obj = LookupLocalObject(accessor_name);
8487 if (obj.IsNull()) { 8488 if (obj.IsNull()) {
8488 obj = LookupImportedObject(name); 8489 obj = LookupImportedObject(name);
8489 } 8490 }
8490 } 8491 }
8491 AddToResolvedNamesCache(name, obj); 8492 AddToResolvedNamesCache(name, obj);
8492 return obj.raw(); 8493 return obj.raw();
8493 } 8494 }
8494 8495
8495 8496
8496 static intptr_t ResolvedNameCacheSize(const Array& cache) { 8497 class StringEqualsTraits {
8497 return (cache.Length() - 1) / 2; 8498 public:
8498 } 8499 static bool IsMatch(const Object& a, const Object& b) {
8500 return String::Cast(a).Equals(String::Cast(b));
8501 }
8502 static uword Hash(const Object& obj) {
8503 return String::Cast(obj).Hash();
8504 }
8505 };
8506 typedef UnorderedHashMap<StringEqualsTraits> ResolvedNamesMap;
8499 8507
8500 8508
8501 // Returns true if the name is found in the cache, false no cache hit. 8509 // Returns true if the name is found in the cache, false no cache hit.
8502 // obj is set to the cached entry. It may be null, indicating that the 8510 // obj is set to the cached entry. It may be null, indicating that the
8503 // name does not resolve to anything in this library. 8511 // name does not resolve to anything in this library.
8504 bool Library::LookupResolvedNamesCache(const String& name, 8512 bool Library::LookupResolvedNamesCache(const String& name,
8505 Object* obj) const { 8513 Object* obj) const {
8506 const Array& cache = Array::Handle(resolved_names()); 8514 ResolvedNamesMap cache(Array::Handle(resolved_names()));
8507 const intptr_t cache_size = ResolvedNameCacheSize(cache); 8515 bool present = false;
8508 intptr_t index = name.Hash() % cache_size; 8516 *obj = cache.GetOrNull(name, &present);
8509 String& entry_name = String::Handle(); 8517 ASSERT(cache.Release() == resolved_names());
siva 2014/06/13 19:51:19 Strange that you are calling Release which has a s
koda 2014/06/23 19:44:56 Done.
8510 entry_name ^= cache.At(index); 8518 return present;
8511 while (!entry_name.IsNull()) {
8512 if (entry_name.Equals(name)) {
8513 CompilerStats::num_lib_cache_hit++;
8514 *obj = cache.At(index + cache_size);
8515 return true;
8516 }
8517 index = (index + 1) % cache_size;
8518 entry_name ^= cache.At(index);
8519 }
8520 *obj = Object::null();
8521 return false;
8522 }
8523
8524
8525 void Library::GrowResolvedNamesCache() const {
8526 const Array& old_cache = Array::Handle(resolved_names());
8527 const intptr_t old_cache_size = ResolvedNameCacheSize(old_cache);
8528
8529 // Create empty new cache and add entries from the old cache.
8530 const intptr_t new_cache_size = old_cache_size * 3 / 2;
8531 InitResolvedNamesCache(new_cache_size);
8532 String& name = String::Handle();
8533 Object& entry = Object::Handle();
8534 for (intptr_t i = 0; i < old_cache_size; i++) {
8535 name ^= old_cache.At(i);
8536 if (!name.IsNull()) {
8537 entry = old_cache.At(i + old_cache_size);
8538 AddToResolvedNamesCache(name, entry);
8539 }
8540 }
8541 } 8519 }
8542 8520
8543 8521
8544 // Add a name to the resolved name cache. This name resolves to the 8522 // Add a name to the resolved name cache. This name resolves to the
8545 // given object in this library scope. obj may be null, which means 8523 // given object in this library scope. obj may be null, which means
8546 // the name does not resolve to anything in this library scope. 8524 // the name does not resolve to anything in this library scope.
8547 void Library::AddToResolvedNamesCache(const String& name, 8525 void Library::AddToResolvedNamesCache(const String& name,
8548 const Object& obj) const { 8526 const Object& obj) const {
8549 if (!FLAG_use_lib_cache) { 8527 if (!FLAG_use_lib_cache) {
8550 return; 8528 return;
8551 } 8529 }
8552 ASSERT(!Field::IsGetterName(name) && !Field::IsSetterName(name)); 8530 ResolvedNamesMap cache(Array::Handle(resolved_names()));
8553 const Array& cache = Array::Handle(resolved_names()); 8531 cache.UpdateOrInsert(name, obj);
8554 // let N = cache.Length(); 8532 StorePointer(&raw_ptr()->resolved_names_, cache.Release());
8555 // The entry cache[N-1] is used as a counter
8556 // The array entries [0..N-2] are used as cache entries.
8557 // cache[i] contains the name of the entry
8558 // cache[i+(N-1)/2] contains the resolved entity, or NULL if that name
8559 // is not present in the library.
8560 const intptr_t counter_index = cache.Length() - 1;
8561 intptr_t cache_size = ResolvedNameCacheSize(cache);
8562 intptr_t index = name.Hash() % cache_size;
8563 String& entry_name = String::Handle();
8564 entry_name ^= cache.At(index);
8565 // An empty spot will be found because we keep the hash set at most 75% full.
8566 while (!entry_name.IsNull()) {
8567 index = (index + 1) % cache_size;
8568 entry_name ^= cache.At(index);
8569 }
8570 // Insert the object at the empty slot.
8571 cache.SetAt(index, name);
8572 ASSERT(cache.At(index + cache_size) == Object::null());
8573 cache.SetAt(index + cache_size, obj);
8574
8575 // One more element added.
8576 intptr_t num_used = Smi::Value(Smi::RawCast(cache.At(counter_index))) + 1;
8577 cache.SetAt(counter_index, Smi::Handle(Smi::New(num_used)));
8578 CompilerStats::num_names_cached++;
8579
8580 // Rehash if symbol_table is 75% full.
8581 if (num_used > ((cache_size / 4) * 3)) {
8582 CompilerStats::num_names_cached -= num_used;
8583 GrowResolvedNamesCache();
8584 }
8585 } 8533 }
8586 8534
8587 8535
8588 void Library::InvalidateResolvedName(const String& name) const { 8536 void Library::InvalidateResolvedName(const String& name) const {
8589 Object& entry = Object::Handle(); 8537 Object& entry = Object::Handle();
8590 if (LookupResolvedNamesCache(name, &entry)) { 8538 if (LookupResolvedNamesCache(name, &entry)) {
8539 // TODO(koda): Support deleted sentinel in snapshots and remove only 'name'.
8591 InvalidateResolvedNamesCache(); 8540 InvalidateResolvedNamesCache();
8592 } 8541 }
8593 } 8542 }
8594 8543
8595 8544
8596 void Library::InvalidateResolvedNamesCache() const { 8545 void Library::InvalidateResolvedNamesCache() const {
8597 const intptr_t kInvalidatedCacheSize = 16; 8546 const intptr_t kInvalidatedCacheSize = 16;
8598 InitResolvedNamesCache(kInvalidatedCacheSize); 8547 InitResolvedNamesCache(kInvalidatedCacheSize);
8599 } 8548 }
8600 8549
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
9097 9046
9098 static RawArray* NewDictionary(intptr_t initial_size) { 9047 static RawArray* NewDictionary(intptr_t initial_size) {
9099 const Array& dict = Array::Handle(Array::New(initial_size + 1, Heap::kOld)); 9048 const Array& dict = Array::Handle(Array::New(initial_size + 1, Heap::kOld));
9100 // The last element of the dictionary specifies the number of in use slots. 9049 // The last element of the dictionary specifies the number of in use slots.
9101 dict.SetAt(initial_size, Smi::Handle(Smi::New(0))); 9050 dict.SetAt(initial_size, Smi::Handle(Smi::New(0)));
9102 return dict.raw(); 9051 return dict.raw();
9103 } 9052 }
9104 9053
9105 9054
9106 void Library::InitResolvedNamesCache(intptr_t size) const { 9055 void Library::InitResolvedNamesCache(intptr_t size) const {
9107 // Need space for 'size' names and 'size' resolved object entries. 9056 Array& cache = Array::Handle(HashTables::New<ResolvedNamesMap>(size));
siva 2014/06/13 19:51:19 const Array& cache = ...;
koda 2014/06/23 19:44:56 Done.
9108 StorePointer(&raw_ptr()->resolved_names_, NewDictionary(2 * size)); 9057 StorePointer(&raw_ptr()->resolved_names_, cache.raw());
9109 } 9058 }
9110 9059
9111 9060
9112 void Library::InitClassDictionary() const { 9061 void Library::InitClassDictionary() const {
9113 // TODO(iposva): Find reasonable initial size. 9062 // TODO(iposva): Find reasonable initial size.
9114 const int kInitialElementCount = 16; 9063 const int kInitialElementCount = 16;
9115 StorePointer(&raw_ptr()->dictionary_, NewDictionary(kInitialElementCount)); 9064 StorePointer(&raw_ptr()->dictionary_, NewDictionary(kInitialElementCount));
9116 } 9065 }
9117 9066
9118 9067
(...skipping 9864 matching lines...) Expand 10 before | Expand all | Expand 10 after
18983 return tag_label.ToCString(); 18932 return tag_label.ToCString();
18984 } 18933 }
18985 18934
18986 18935
18987 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { 18936 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
18988 Instance::PrintJSONImpl(stream, ref); 18937 Instance::PrintJSONImpl(stream, ref);
18989 } 18938 }
18990 18939
18991 18940
18992 } // namespace dart 18941 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698