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

Side by Side Diff: vm/symbols.cc

Issue 10783035: Create frequently used symbols in the vm isolate (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 5 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
« no previous file with comments | « vm/symbols.h ('k') | vm/unit_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include "vm/symbols.h"
6
7 #include "vm/isolate.h"
8 #include "vm/object.h"
9 #include "vm/object_store.h"
10 #include "vm/raw_object.h"
11 #include "vm/unicode.h"
12 #include "vm/visitor.h"
13
14 namespace dart {
15
16 const char* Symbols::kDot = ".";
17 RawString* Symbols::dot_ = String::null();
18
19
20 void Symbols::InitOnce(Isolate* isolate) {
21 // Should only be run by the vm isolate.
22 ASSERT(isolate == Dart::vm_isolate());
23
24 // Create and setup a symbol table in the vm isolate.
25 SetupSymbolTable(isolate);
26
27 // Create all predefined symbols.
28 const Array& symbol_table =
29 Array::Handle(isolate->object_store()->symbol_table());
30 OneByteString& str = OneByteString::Handle();
31
32 str = OneByteString::New(kDot, Heap::kOld);
33 Add(symbol_table, str); // "."
34 dot_ = str.raw();
35 }
36
37
38 void Symbols::SetupSymbolTable(Isolate* isolate) {
39 ASSERT(isolate != NULL);
40
41 // Setup the symbol table used within the String class.
42 const Array& array = Array::Handle(Array::New(kInitialSymbolTableSize + 1));
43
44 // Last element contains the count of used slots.
45 array.SetAt(kInitialSymbolTableSize, Smi::Handle(Smi::New(0)));
46 isolate->object_store()->set_symbol_table(array);
47 }
48
49
50 void Symbols::Add(const Array& symbol_table, const String& str) {
51 // Should only be run by the vm isolate.
52 ASSERT(Isolate::Current() == Dart::vm_isolate());
53 intptr_t hash = str.Hash();
54 intptr_t index = FindIndex(symbol_table, str, 0, str.Length(), hash);
55 ASSERT(symbol_table.At(index) == String::null());
56 InsertIntoSymbolTable(symbol_table, str, index);
57 }
58
59
60 RawString* Symbols::New(const char* str) {
61 intptr_t width = 0;
62 intptr_t len = Utf8::CodePointCount(str, &width);
63 intptr_t size = len * width;
64 Zone* zone = Isolate::Current()->current_zone();
65 if (len == 0) {
66 return Symbols::New(reinterpret_cast<uint8_t*>(NULL), 0);
67 } else if (width == 1) {
68 uint8_t* characters = reinterpret_cast<uint8_t*>(zone->Allocate(size));
69 Utf8::Decode(str, characters, len);
70 return New(characters, len);
71 } else if (width == 2) {
72 uint16_t* characters = reinterpret_cast<uint16_t*>(zone->Allocate(size));
73 Utf8::Decode(str, characters, len);
74 return New(characters, len);
75 }
76 ASSERT(width == 4);
77 uint32_t* characters = reinterpret_cast<uint32_t*>(zone->Allocate(size));
78 Utf8::Decode(str, characters, len);
79 return New(characters, len);
80 }
81
82
83 template<typename T>
84 RawString* Symbols::New(const T* characters, intptr_t len) {
85 Isolate* isolate = Isolate::Current();
86 ASSERT(isolate != Dart::vm_isolate());
87 String& symbol = String::Handle(isolate, String::null());
88 Array& symbol_table = Array::Handle(isolate, Array::null());
89
90 // Calculate the String hash for this sequence of characters.
91 intptr_t hash = String::Hash(characters, len);
92
93 // First check if a symbol exists in the vm isolate for these characters.
94 symbol_table = Dart::vm_isolate()->object_store()->symbol_table();
95 intptr_t index = FindIndex(symbol_table, characters, len, hash);
96 symbol ^= symbol_table.At(index);
97 if (symbol.IsNull()) {
98 // Now try in the symbol table of the current isolate.
99 symbol_table = isolate->object_store()->symbol_table();
100 index = FindIndex(symbol_table, characters, len, hash);
101 // Since we leave enough room in the table to guarantee, that we find an
102 // empty spot, index is the insertion point if symbol is null.
103 symbol ^= symbol_table.At(index);
104 if (symbol.IsNull()) {
105 // Allocate new result string.
106 symbol = String::New(characters, len, Heap::kOld);
107 symbol.SetHash(hash); // Remember the calculated hash value.
108 InsertIntoSymbolTable(symbol_table, symbol, index);
109 }
110 }
111 ASSERT(symbol.IsSymbol());
112 return symbol.raw();
113 }
114
115 template RawString* Symbols::New(const uint8_t* characters, intptr_t len);
116 template RawString* Symbols::New(const uint16_t* characters, intptr_t len);
117 template RawString* Symbols::New(const uint32_t* characters, intptr_t len);
118
119
120 RawString* Symbols::New(const String& str) {
121 if (str.IsSymbol()) {
122 return str.raw();
123 }
124 return New(str, 0, str.Length());
125 }
126
127
128 RawString* Symbols::New(const String& str, intptr_t begin_index, intptr_t len) {
129 ASSERT(begin_index >= 0);
130 ASSERT(len >= 0);
131 ASSERT((begin_index + len) <= str.Length());
132 Isolate* isolate = Isolate::Current();
133 ASSERT(isolate != Dart::vm_isolate());
134 String& symbol = String::Handle(isolate, String::null());
135 Array& symbol_table = Array::Handle(isolate, Array::null());
136
137 // Calculate the String hash for this sequence of characters.
138 intptr_t hash = (begin_index == 0 && len == str.Length()) ? str.Hash() :
139 String::Hash(str, begin_index, len);
140
141 // First check if a symbol exists in the vm isolate for these characters.
142 symbol_table = Dart::vm_isolate()->object_store()->symbol_table();
143 intptr_t index = FindIndex(symbol_table, str, begin_index, len, hash);
144 symbol ^= symbol_table.At(index);
145 if (symbol.IsNull()) {
146 // Now try in the symbol table of the current isolate.
147 symbol_table = isolate->object_store()->symbol_table();
148 index = FindIndex(symbol_table, str, begin_index, len, hash);
149 // Since we leave enough room in the table to guarantee, that we find an
150 // empty spot, index is the insertion point if symbol is null.
151 symbol ^= symbol_table.At(index);
152 if (symbol.IsNull()) {
153 if (str.IsOld() && begin_index == 0 && len == str.Length()) {
154 // Reuse the incoming str as the symbol value.
155 symbol = str.raw();
156 } else {
157 // Allocate a copy in old space.
158 symbol = String::SubString(str, begin_index, len, Heap::kOld);
159 symbol.SetHash(hash);
160 }
161 InsertIntoSymbolTable(symbol_table, symbol, index);
162 }
163 }
164 ASSERT(symbol.IsSymbol());
165 return symbol.raw();
166 }
167
168
169 void Symbols::GrowSymbolTable(const Array& symbol_table) {
170 // TODO(iposva): Avoid exponential growth.
171 intptr_t table_size = symbol_table.Length() - 1;
172 intptr_t new_table_size = table_size * 2;
173 Array& new_symbol_table = Array::Handle(Array::New(new_table_size + 1));
174 // Copy all elements from the original symbol table to the newly allocated
175 // array.
176 String& element = String::Handle();
177 Object& new_element = Object::Handle();
178 for (intptr_t i = 0; i < table_size; i++) {
179 element ^= symbol_table.At(i);
180 if (!element.IsNull()) {
181 intptr_t hash = element.Hash();
182 intptr_t index = hash % new_table_size;
183 new_element = new_symbol_table.At(index);
184 while (!new_element.IsNull()) {
185 index = (index + 1) % new_table_size; // Move to next element.
186 new_element = new_symbol_table.At(index);
187 }
188 new_symbol_table.SetAt(index, element);
189 }
190 }
191 // Copy used count.
192 new_element = symbol_table.At(table_size);
193 new_symbol_table.SetAt(new_table_size, new_element);
194 // Remember the new symbol table now.
195 Isolate::Current()->object_store()->set_symbol_table(new_symbol_table);
196 }
197
198
199 void Symbols::InsertIntoSymbolTable(const Array& symbol_table,
200 const String& symbol,
201 intptr_t index) {
202 intptr_t table_size = symbol_table.Length() - 1;
203 symbol.SetCanonical(); // Mark object as being canonical.
204 symbol_table.SetAt(index, symbol); // Remember the new symbol.
205 Smi& used = Smi::Handle();
206 used ^= symbol_table.At(table_size);
207 intptr_t used_elements = used.Value() + 1; // One more element added.
208 used = Smi::New(used_elements);
209 symbol_table.SetAt(table_size, used); // Update used count.
210
211 // Rehash if symbol_table is 75% full.
212 if (used_elements > ((table_size / 4) * 3)) {
213 GrowSymbolTable(symbol_table);
214 }
215 }
216
217
218 template<typename T>
219 intptr_t Symbols::FindIndex(const Array& symbol_table,
220 const T* characters,
221 intptr_t len,
222 intptr_t hash) {
223 // Last element of the array is the number of used elements.
224 intptr_t table_size = symbol_table.Length() - 1;
225 intptr_t index = hash % table_size;
226
227 String& symbol = String::Handle();
228 symbol ^= symbol_table.At(index);
229 while (!symbol.IsNull() && !symbol.Equals(characters, len)) {
230 index = (index + 1) % table_size; // Move to next element.
231 symbol ^= symbol_table.At(index);
232 }
233 return index; // Index of symbol if found or slot into which to add symbol.
234 }
235
236
237 template intptr_t Symbols::FindIndex(const Array& symbol_table,
238 const uint8_t* characters,
239 intptr_t len,
240 intptr_t hash);
241 template intptr_t Symbols::FindIndex(const Array& symbol_table,
242 const uint16_t* characters,
243 intptr_t len,
244 intptr_t hash);
245 template intptr_t Symbols::FindIndex(const Array& symbol_table,
246 const uint32_t* characters,
247 intptr_t len,
248 intptr_t hash);
249
250
251 intptr_t Symbols::FindIndex(const Array& symbol_table,
252 const String& str,
253 intptr_t begin_index,
254 intptr_t len,
255 intptr_t hash) {
256 // Last element of the array is the number of used elements.
257 intptr_t table_size = symbol_table.Length() - 1;
258 intptr_t index = hash % table_size;
259
260 String& symbol = String::Handle();
261 symbol ^= symbol_table.At(index);
262 while (!symbol.IsNull() && !symbol.Equals(str, begin_index, len)) {
263 index = (index + 1) % table_size; // Move to next element.
264 symbol ^= symbol_table.At(index);
265 }
266 return index; // Index of symbol if found or slot into which to add symbol.
267 }
268
269 } // namespace dart
OLDNEW
« no previous file with comments | « vm/symbols.h ('k') | vm/unit_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698