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: src/compilation-cache.cc

Issue 113445: Add multiple generations (5) to the script compilation cache... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 7 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 2008 the V8 project authors. All rights reserved. 1 // Copyright 2008 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 14 matching lines...) Expand all
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "compilation-cache.h" 30 #include "compilation-cache.h"
31 31
32 namespace v8 { namespace internal { 32 namespace v8 { namespace internal {
33 33
34 enum { 34 enum {
35 NUMBER_OF_ENTRY_KINDS = CompilationCache::LAST_ENTRY + 1 35 // The number of script generations tell how many GCs a script can
36 // survive in the compilation cache, before it will be flushed if it
37 // hasn't been used.
38 NUMBER_OF_SCRIPT_GENERATIONS = 5,
39
40 // The compilation cache consists of tables - one for each entry
41 // kind plus extras for the script generations.
42 NUMBER_OF_TABLE_ENTRIES =
43 CompilationCache::LAST_ENTRY + NUMBER_OF_SCRIPT_GENERATIONS
36 }; 44 };
37 45
38 46
39 // Keep separate tables for the different entry kinds. 47 // Keep separate tables for the different entry kinds.
40 static Object* tables[NUMBER_OF_ENTRY_KINDS] = { 0, }; 48 static Object* tables[NUMBER_OF_TABLE_ENTRIES] = { 0, };
41 49
42 50
43 static Handle<CompilationCacheTable> AllocateTable(int size) { 51 static Handle<CompilationCacheTable> AllocateTable(int size) {
44 CALL_HEAP_FUNCTION(CompilationCacheTable::Allocate(size), 52 CALL_HEAP_FUNCTION(CompilationCacheTable::Allocate(size),
45 CompilationCacheTable); 53 CompilationCacheTable);
46 } 54 }
47 55
48 56
49 static Handle<CompilationCacheTable> GetTable(CompilationCache::Entry entry) { 57 static Handle<CompilationCacheTable> GetTable(CompilationCache::Entry entry) {
50 Handle<CompilationCacheTable> result; 58 Handle<CompilationCacheTable> result;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 // Do the fast bailout checks first. 122 // Do the fast bailout checks first.
115 if (line_offset != script->line_offset()->value()) return false; 123 if (line_offset != script->line_offset()->value()) return false;
116 if (column_offset != script->column_offset()->value()) return false; 124 if (column_offset != script->column_offset()->value()) return false;
117 // Check that both names are strings. If not, no match. 125 // Check that both names are strings. If not, no match.
118 if (!name->IsString() || !script->name()->IsString()) return false; 126 if (!name->IsString() || !script->name()->IsString()) return false;
119 // Compare the two name strings for equality. 127 // Compare the two name strings for equality.
120 return String::cast(*name)->Equals(String::cast(script->name())); 128 return String::cast(*name)->Equals(String::cast(script->name()));
121 } 129 }
122 130
123 131
124 static Handle<JSFunction> Lookup(Handle<String> source, 132 // TODO(245): Need to allow identical code from different contexts to
125 CompilationCache::Entry entry) { 133 // be cached in the same script generation. Currently the first use
126 // Make sure not to leak the table into the surrounding handle 134 // will be cached, but subsequent code from different source / line
127 // scope. Otherwise, we risk keeping old tables around even after 135 // won't.
128 // having cleared the cache. 136 Handle<JSFunction> CompilationCache::LookupScript(Handle<String> source,
129 Object* result; 137 Handle<Object> name,
138 int line_offset,
139 int column_offset) {
140 Object* result = NULL;
141 Entry generation = SCRIPT; // First generation.
142
143 // Probe the script generation tables. Make sure not to leak handles
144 // into the caller's handle scope.
130 { HandleScope scope; 145 { HandleScope scope;
131 Handle<CompilationCacheTable> table = GetTable(entry); 146 while (generation < SCRIPT + NUMBER_OF_SCRIPT_GENERATIONS) {
132 result = table->Lookup(*source); 147 Handle<CompilationCacheTable> table = GetTable(generation);
148 Handle<Object> probe(table->Lookup(*source));
149 if (probe->IsJSFunction()) {
150 Handle<JSFunction> boilerplate = Handle<JSFunction>::cast(probe);
151 // Break when we've found a suitable boilerplate function that
152 // matches the origin.
153 if (HasOrigin(boilerplate, name, line_offset, column_offset)) {
154 result = *boilerplate;
155 break;
156 }
157 }
158 // Go to the next generation.
159 generation = static_cast<Entry>(generation + 1);
160 }
133 } 161 }
134 if (result->IsJSFunction()) { 162
135 return Handle<JSFunction>(JSFunction::cast(result)); 163 // Once outside the menacles of the handle scope, we need to recheck
164 // to see if we actually found a cached script. If so, we return a
165 // handle created in the caller's handle scope.
166 if (result != NULL) {
167 Handle<JSFunction> boilerplate(JSFunction::cast(result));
168 ASSERT(HasOrigin(boilerplate, name, line_offset, column_offset));
169 // If the script was found in a later generation, we promote it to
170 // the first generation to let it survive longer in the cache.
171 if (generation != SCRIPT) PutScript(source, boilerplate);
172 Counters::compilation_cache_hits.Increment();
173 return boilerplate;
136 } else { 174 } else {
175 Counters::compilation_cache_misses.Increment();
137 return Handle<JSFunction>::null(); 176 return Handle<JSFunction>::null();
138 } 177 }
139 } 178 }
140 179
141 180
142 // TODO(245): Need to allow identical code from different contexts to be
143 // cached. Currently the first use will be cached, but subsequent code
144 // from different source / line won't.
145 Handle<JSFunction> CompilationCache::LookupScript(Handle<String> source,
146 Handle<Object> name,
147 int line_offset,
148 int column_offset) {
149 Handle<JSFunction> result = Lookup(source, SCRIPT);
150 if (result.is_null()) {
151 Counters::compilation_cache_misses.Increment();
152 } else if (HasOrigin(result, name, line_offset, column_offset)) {
153 Counters::compilation_cache_hits.Increment();
154 } else {
155 result = Handle<JSFunction>::null();
156 Counters::compilation_cache_misses.Increment();
157 }
158 return result;
159 }
160
161
162 Handle<JSFunction> CompilationCache::LookupEval(Handle<String> source, 181 Handle<JSFunction> CompilationCache::LookupEval(Handle<String> source,
163 Handle<Context> context, 182 Handle<Context> context,
164 Entry entry) { 183 Entry entry) {
165 ASSERT(entry == EVAL_GLOBAL || entry == EVAL_CONTEXTUAL); 184 ASSERT(entry == EVAL_GLOBAL || entry == EVAL_CONTEXTUAL);
166 Handle<JSFunction> result = Lookup(source, context, entry); 185 Handle<JSFunction> result = Lookup(source, context, entry);
167 if (result.is_null()) { 186 if (result.is_null()) {
168 Counters::compilation_cache_misses.Increment(); 187 Counters::compilation_cache_misses.Increment();
169 } else { 188 } else {
170 Counters::compilation_cache_hits.Increment(); 189 Counters::compilation_cache_hits.Increment();
171 } 190 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 void CompilationCache::PutRegExp(Handle<String> source, 228 void CompilationCache::PutRegExp(Handle<String> source,
210 JSRegExp::Flags flags, 229 JSRegExp::Flags flags,
211 Handle<FixedArray> data) { 230 Handle<FixedArray> data) {
212 HandleScope scope; 231 HandleScope scope;
213 Handle<CompilationCacheTable> table = GetTable(REGEXP); 232 Handle<CompilationCacheTable> table = GetTable(REGEXP);
214 CALL_HEAP_FUNCTION_VOID(table->PutRegExp(*source, flags, *data)); 233 CALL_HEAP_FUNCTION_VOID(table->PutRegExp(*source, flags, *data));
215 } 234 }
216 235
217 236
218 void CompilationCache::Clear() { 237 void CompilationCache::Clear() {
219 for (int i = 0; i < NUMBER_OF_ENTRY_KINDS; i++) { 238 for (int i = 0; i < NUMBER_OF_TABLE_ENTRIES; i++) {
220 tables[i] = Heap::undefined_value(); 239 tables[i] = Heap::undefined_value();
221 } 240 }
222 } 241 }
223 242
224 243
225 void CompilationCache::Iterate(ObjectVisitor* v) { 244 void CompilationCache::Iterate(ObjectVisitor* v) {
226 v->VisitPointers(&tables[0], &tables[NUMBER_OF_ENTRY_KINDS]); 245 v->VisitPointers(&tables[0], &tables[NUMBER_OF_TABLE_ENTRIES]);
246 }
247
248
249 void CompilationCache::MarkCompactPrologue() {
250 ASSERT(LAST_ENTRY == SCRIPT);
251 for (int i = NUMBER_OF_TABLE_ENTRIES - 1; i > SCRIPT; i--) {
252 tables[i] = tables[i - 1];
253 }
254 for (int j = 0; j <= LAST_ENTRY; j++) {
255 tables[j] = Heap::undefined_value();
256 }
227 } 257 }
228 258
229 259
230 } } // namespace v8::internal 260 } } // namespace v8::internal
OLDNEW
« src/compilation-cache.h ('K') | « src/compilation-cache.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698