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

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

Powered by Google App Engine
This is Rietveld 408576698