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

Side by Side Diff: src/compilation-cache.cc

Issue 1113009: Merge 4205:4215 from bleeding_edge to partial_snapshots branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: Created 10 years, 9 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 | « src/compilation-cache.h ('k') | src/compiler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationSubCache); 96 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationSubCache);
97 }; 97 };
98 98
99 99
100 // Sub-cache for scripts. 100 // Sub-cache for scripts.
101 class CompilationCacheScript : public CompilationSubCache { 101 class CompilationCacheScript : public CompilationSubCache {
102 public: 102 public:
103 explicit CompilationCacheScript(int generations) 103 explicit CompilationCacheScript(int generations)
104 : CompilationSubCache(generations) { } 104 : CompilationSubCache(generations) { }
105 105
106 Handle<JSFunction> Lookup(Handle<String> source, 106 Handle<SharedFunctionInfo> Lookup(Handle<String> source,
107 Handle<Object> name, 107 Handle<Object> name,
108 int line_offset, 108 int line_offset,
109 int column_offset); 109 int column_offset);
110 void Put(Handle<String> source, Handle<JSFunction> boilerplate); 110 void Put(Handle<String> source, Handle<SharedFunctionInfo> function_info);
111 111
112 private: 112 private:
113 // Note: Returns a new hash table if operation results in expansion. 113 // Note: Returns a new hash table if operation results in expansion.
114 Handle<CompilationCacheTable> TablePut(Handle<String> source, 114 Handle<CompilationCacheTable> TablePut(
115 Handle<JSFunction> boilerplate); 115 Handle<String> source, Handle<SharedFunctionInfo> function_info);
116 116
117 bool HasOrigin(Handle<JSFunction> boilerplate, 117 bool HasOrigin(Handle<SharedFunctionInfo> function_info,
118 Handle<Object> name, 118 Handle<Object> name,
119 int line_offset, 119 int line_offset,
120 int column_offset); 120 int column_offset);
121 121
122 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheScript); 122 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheScript);
123 }; 123 };
124 124
125 125
126 // Sub-cache for eval scripts. 126 // Sub-cache for eval scripts.
127 class CompilationCacheEval: public CompilationSubCache { 127 class CompilationCacheEval: public CompilationSubCache {
128 public: 128 public:
129 explicit CompilationCacheEval(int generations) 129 explicit CompilationCacheEval(int generations)
130 : CompilationSubCache(generations) { } 130 : CompilationSubCache(generations) { }
131 131
132 Handle<JSFunction> Lookup(Handle<String> source, Handle<Context> context); 132 Handle<SharedFunctionInfo> Lookup(Handle<String> source,
133 Handle<Context> context);
133 134
134 void Put(Handle<String> source, 135 void Put(Handle<String> source,
135 Handle<Context> context, 136 Handle<Context> context,
136 Handle<JSFunction> boilerplate); 137 Handle<SharedFunctionInfo> function_info);
137 138
138 private: 139 private:
139 // Note: Returns a new hash table if operation results in expansion. 140 // Note: Returns a new hash table if operation results in expansion.
140 Handle<CompilationCacheTable> TablePut(Handle<String> source, 141 Handle<CompilationCacheTable> TablePut(
141 Handle<Context> context, 142 Handle<String> source,
142 Handle<JSFunction> boilerplate); 143 Handle<Context> context,
144 Handle<SharedFunctionInfo> function_info);
143 145
144 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval); 146 DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval);
145 }; 147 };
146 148
147 149
148 // Sub-cache for regular expressions. 150 // Sub-cache for regular expressions.
149 class CompilationCacheRegExp: public CompilationSubCache { 151 class CompilationCacheRegExp: public CompilationSubCache {
150 public: 152 public:
151 explicit CompilationCacheRegExp(int generations) 153 explicit CompilationCacheRegExp(int generations)
152 : CompilationSubCache(generations) { } 154 : CompilationSubCache(generations) { }
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 222
221 223
222 void CompilationSubCache::Clear() { 224 void CompilationSubCache::Clear() {
223 MemsetPointer(tables_, Heap::undefined_value(), generations_); 225 MemsetPointer(tables_, Heap::undefined_value(), generations_);
224 } 226 }
225 227
226 228
227 // We only re-use a cached function for some script source code if the 229 // We only re-use a cached function for some script source code if the
228 // script originates from the same place. This is to avoid issues 230 // script originates from the same place. This is to avoid issues
229 // when reporting errors, etc. 231 // when reporting errors, etc.
230 bool CompilationCacheScript::HasOrigin(Handle<JSFunction> boilerplate, 232 bool CompilationCacheScript::HasOrigin(
231 Handle<Object> name, 233 Handle<SharedFunctionInfo> function_info,
232 int line_offset, 234 Handle<Object> name,
233 int column_offset) { 235 int line_offset,
236 int column_offset) {
234 Handle<Script> script = 237 Handle<Script> script =
235 Handle<Script>(Script::cast(boilerplate->shared()->script())); 238 Handle<Script>(Script::cast(function_info->script()));
236 // If the script name isn't set, the boilerplate script should have 239 // If the script name isn't set, the boilerplate script should have
237 // an undefined name to have the same origin. 240 // an undefined name to have the same origin.
238 if (name.is_null()) { 241 if (name.is_null()) {
239 return script->name()->IsUndefined(); 242 return script->name()->IsUndefined();
240 } 243 }
241 // Do the fast bailout checks first. 244 // Do the fast bailout checks first.
242 if (line_offset != script->line_offset()->value()) return false; 245 if (line_offset != script->line_offset()->value()) return false;
243 if (column_offset != script->column_offset()->value()) return false; 246 if (column_offset != script->column_offset()->value()) return false;
244 // Check that both names are strings. If not, no match. 247 // Check that both names are strings. If not, no match.
245 if (!name->IsString() || !script->name()->IsString()) return false; 248 if (!name->IsString() || !script->name()->IsString()) return false;
246 // Compare the two name strings for equality. 249 // Compare the two name strings for equality.
247 return String::cast(*name)->Equals(String::cast(script->name())); 250 return String::cast(*name)->Equals(String::cast(script->name()));
248 } 251 }
249 252
250 253
251 // TODO(245): Need to allow identical code from different contexts to 254 // TODO(245): Need to allow identical code from different contexts to
252 // be cached in the same script generation. Currently the first use 255 // be cached in the same script generation. Currently the first use
253 // will be cached, but subsequent code from different source / line 256 // will be cached, but subsequent code from different source / line
254 // won't. 257 // won't.
255 Handle<JSFunction> CompilationCacheScript::Lookup(Handle<String> source, 258 Handle<SharedFunctionInfo> CompilationCacheScript::Lookup(Handle<String> source,
256 Handle<Object> name, 259 Handle<Object> name,
257 int line_offset, 260 int line_offset,
258 int column_offset) { 261 int column_offset) {
259 Object* result = NULL; 262 Object* result = NULL;
260 int generation; 263 int generation;
261 264
262 // Probe the script generation tables. Make sure not to leak handles 265 // Probe the script generation tables. Make sure not to leak handles
263 // into the caller's handle scope. 266 // into the caller's handle scope.
264 { HandleScope scope; 267 { HandleScope scope;
265 for (generation = 0; generation < generations(); generation++) { 268 for (generation = 0; generation < generations(); generation++) {
266 Handle<CompilationCacheTable> table = GetTable(generation); 269 Handle<CompilationCacheTable> table = GetTable(generation);
267 Handle<Object> probe(table->Lookup(*source)); 270 Handle<Object> probe(table->Lookup(*source));
268 if (probe->IsJSFunction()) { 271 if (probe->IsSharedFunctionInfo()) {
269 Handle<JSFunction> boilerplate = Handle<JSFunction>::cast(probe); 272 Handle<SharedFunctionInfo> function_info =
273 Handle<SharedFunctionInfo>::cast(probe);
270 // Break when we've found a suitable boilerplate function that 274 // Break when we've found a suitable boilerplate function that
271 // matches the origin. 275 // matches the origin.
272 if (HasOrigin(boilerplate, name, line_offset, column_offset)) { 276 if (HasOrigin(function_info, name, line_offset, column_offset)) {
273 result = *boilerplate; 277 result = *function_info;
274 break; 278 break;
275 } 279 }
276 } 280 }
277 } 281 }
278 } 282 }
279 283
280 static void* script_histogram = StatsTable::CreateHistogram( 284 static void* script_histogram = StatsTable::CreateHistogram(
281 "V8.ScriptCache", 285 "V8.ScriptCache",
282 0, 286 0,
283 kScriptGenerations, 287 kScriptGenerations,
284 kScriptGenerations + 1); 288 kScriptGenerations + 1);
285 289
286 if (script_histogram != NULL) { 290 if (script_histogram != NULL) {
287 // The level NUMBER_OF_SCRIPT_GENERATIONS is equivalent to a cache miss. 291 // The level NUMBER_OF_SCRIPT_GENERATIONS is equivalent to a cache miss.
288 StatsTable::AddHistogramSample(script_histogram, generation); 292 StatsTable::AddHistogramSample(script_histogram, generation);
289 } 293 }
290 294
291 // Once outside the manacles of the handle scope, we need to recheck 295 // Once outside the manacles of the handle scope, we need to recheck
292 // to see if we actually found a cached script. If so, we return a 296 // to see if we actually found a cached script. If so, we return a
293 // handle created in the caller's handle scope. 297 // handle created in the caller's handle scope.
294 if (result != NULL) { 298 if (result != NULL) {
295 Handle<JSFunction> boilerplate(JSFunction::cast(result)); 299 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
296 ASSERT(HasOrigin(boilerplate, name, line_offset, column_offset)); 300 ASSERT(HasOrigin(shared, name, line_offset, column_offset));
297 // If the script was found in a later generation, we promote it to 301 // If the script was found in a later generation, we promote it to
298 // the first generation to let it survive longer in the cache. 302 // the first generation to let it survive longer in the cache.
299 if (generation != 0) Put(source, boilerplate); 303 if (generation != 0) Put(source, shared);
300 Counters::compilation_cache_hits.Increment(); 304 Counters::compilation_cache_hits.Increment();
301 return boilerplate; 305 return shared;
302 } else { 306 } else {
303 Counters::compilation_cache_misses.Increment(); 307 Counters::compilation_cache_misses.Increment();
304 return Handle<JSFunction>::null(); 308 return Handle<SharedFunctionInfo>::null();
305 } 309 }
306 } 310 }
307 311
308 312
309 Handle<CompilationCacheTable> CompilationCacheScript::TablePut( 313 Handle<CompilationCacheTable> CompilationCacheScript::TablePut(
310 Handle<String> source, 314 Handle<String> source,
311 Handle<JSFunction> boilerplate) { 315 Handle<SharedFunctionInfo> function_info) {
312 CALL_HEAP_FUNCTION(GetFirstTable()->Put(*source, *boilerplate), 316 CALL_HEAP_FUNCTION(GetFirstTable()->Put(*source, *function_info),
313 CompilationCacheTable); 317 CompilationCacheTable);
314 } 318 }
315 319
316 320
317 void CompilationCacheScript::Put(Handle<String> source, 321 void CompilationCacheScript::Put(Handle<String> source,
318 Handle<JSFunction> boilerplate) { 322 Handle<SharedFunctionInfo> function_info) {
319 HandleScope scope; 323 HandleScope scope;
320 ASSERT(boilerplate->IsBoilerplate()); 324 SetFirstTable(TablePut(source, function_info));
321 SetFirstTable(TablePut(source, boilerplate));
322 } 325 }
323 326
324 327
325 Handle<JSFunction> CompilationCacheEval::Lookup(Handle<String> source, 328 Handle<SharedFunctionInfo> CompilationCacheEval::Lookup(
326 Handle<Context> context) { 329 Handle<String> source, Handle<Context> context) {
327 // Make sure not to leak the table into the surrounding handle 330 // Make sure not to leak the table into the surrounding handle
328 // scope. Otherwise, we risk keeping old tables around even after 331 // scope. Otherwise, we risk keeping old tables around even after
329 // having cleared the cache. 332 // having cleared the cache.
330 Object* result = NULL; 333 Object* result = NULL;
331 int generation; 334 int generation;
332 { HandleScope scope; 335 { HandleScope scope;
333 for (generation = 0; generation < generations(); generation++) { 336 for (generation = 0; generation < generations(); generation++) {
334 Handle<CompilationCacheTable> table = GetTable(generation); 337 Handle<CompilationCacheTable> table = GetTable(generation);
335 result = table->LookupEval(*source, *context); 338 result = table->LookupEval(*source, *context);
336 if (result->IsJSFunction()) { 339 if (result->IsSharedFunctionInfo()) {
337 break; 340 break;
338 } 341 }
339 } 342 }
340 } 343 }
341 if (result->IsJSFunction()) { 344 if (result->IsSharedFunctionInfo()) {
342 Handle<JSFunction> boilerplate(JSFunction::cast(result)); 345 Handle<SharedFunctionInfo>
346 function_info(SharedFunctionInfo::cast(result));
343 if (generation != 0) { 347 if (generation != 0) {
344 Put(source, context, boilerplate); 348 Put(source, context, function_info);
345 } 349 }
346 Counters::compilation_cache_hits.Increment(); 350 Counters::compilation_cache_hits.Increment();
347 return boilerplate; 351 return function_info;
348 } else { 352 } else {
349 Counters::compilation_cache_misses.Increment(); 353 Counters::compilation_cache_misses.Increment();
350 return Handle<JSFunction>::null(); 354 return Handle<SharedFunctionInfo>::null();
351 } 355 }
352 } 356 }
353 357
354 358
355 Handle<CompilationCacheTable> CompilationCacheEval::TablePut( 359 Handle<CompilationCacheTable> CompilationCacheEval::TablePut(
356 Handle<String> source, 360 Handle<String> source,
357 Handle<Context> context, 361 Handle<Context> context,
358 Handle<JSFunction> boilerplate) { 362 Handle<SharedFunctionInfo> function_info) {
359 CALL_HEAP_FUNCTION(GetFirstTable()->PutEval(*source, *context, *boilerplate), 363 CALL_HEAP_FUNCTION(GetFirstTable()->PutEval(*source,
364 *context,
365 *function_info),
360 CompilationCacheTable); 366 CompilationCacheTable);
361 } 367 }
362 368
363 369
364 void CompilationCacheEval::Put(Handle<String> source, 370 void CompilationCacheEval::Put(Handle<String> source,
365 Handle<Context> context, 371 Handle<Context> context,
366 Handle<JSFunction> boilerplate) { 372 Handle<SharedFunctionInfo> function_info) {
367 HandleScope scope; 373 HandleScope scope;
368 ASSERT(boilerplate->IsBoilerplate()); 374 SetFirstTable(TablePut(source, context, function_info));
369 SetFirstTable(TablePut(source, context, boilerplate));
370 } 375 }
371 376
372 377
373 Handle<FixedArray> CompilationCacheRegExp::Lookup(Handle<String> source, 378 Handle<FixedArray> CompilationCacheRegExp::Lookup(Handle<String> source,
374 JSRegExp::Flags flags) { 379 JSRegExp::Flags flags) {
375 // Make sure not to leak the table into the surrounding handle 380 // Make sure not to leak the table into the surrounding handle
376 // scope. Otherwise, we risk keeping old tables around even after 381 // scope. Otherwise, we risk keeping old tables around even after
377 // having cleared the cache. 382 // having cleared the cache.
378 Object* result = NULL; 383 Object* result = NULL;
379 int generation; 384 int generation;
(...skipping 30 matching lines...) Expand all
410 415
411 416
412 void CompilationCacheRegExp::Put(Handle<String> source, 417 void CompilationCacheRegExp::Put(Handle<String> source,
413 JSRegExp::Flags flags, 418 JSRegExp::Flags flags,
414 Handle<FixedArray> data) { 419 Handle<FixedArray> data) {
415 HandleScope scope; 420 HandleScope scope;
416 SetFirstTable(TablePut(source, flags, data)); 421 SetFirstTable(TablePut(source, flags, data));
417 } 422 }
418 423
419 424
420 Handle<JSFunction> CompilationCache::LookupScript(Handle<String> source, 425 Handle<SharedFunctionInfo> CompilationCache::LookupScript(Handle<String> source,
421 Handle<Object> name, 426 Handle<Object> name,
422 int line_offset, 427 int line_offset,
423 int column_offset) { 428 int column_offset) {
424 if (!IsEnabled()) { 429 if (!IsEnabled()) {
425 return Handle<JSFunction>::null(); 430 return Handle<SharedFunctionInfo>::null();
426 } 431 }
427 432
428 return script.Lookup(source, name, line_offset, column_offset); 433 return script.Lookup(source, name, line_offset, column_offset);
429 } 434 }
430 435
431 436
432 Handle<JSFunction> CompilationCache::LookupEval(Handle<String> source, 437 Handle<SharedFunctionInfo> CompilationCache::LookupEval(Handle<String> source,
433 Handle<Context> context, 438 Handle<Context> context,
434 bool is_global) { 439 bool is_global) {
435 if (!IsEnabled()) { 440 if (!IsEnabled()) {
436 return Handle<JSFunction>::null(); 441 return Handle<SharedFunctionInfo>::null();
437 } 442 }
438 443
439 Handle<JSFunction> result; 444 Handle<SharedFunctionInfo> result;
440 if (is_global) { 445 if (is_global) {
441 result = eval_global.Lookup(source, context); 446 result = eval_global.Lookup(source, context);
442 } else { 447 } else {
443 result = eval_contextual.Lookup(source, context); 448 result = eval_contextual.Lookup(source, context);
444 } 449 }
445 return result; 450 return result;
446 } 451 }
447 452
448 453
449 Handle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source, 454 Handle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source,
450 JSRegExp::Flags flags) { 455 JSRegExp::Flags flags) {
451 if (!IsEnabled()) { 456 if (!IsEnabled()) {
452 return Handle<FixedArray>::null(); 457 return Handle<FixedArray>::null();
453 } 458 }
454 459
455 return reg_exp.Lookup(source, flags); 460 return reg_exp.Lookup(source, flags);
456 } 461 }
457 462
458 463
459 void CompilationCache::PutScript(Handle<String> source, 464 void CompilationCache::PutScript(Handle<String> source,
460 Handle<JSFunction> boilerplate) { 465 Handle<SharedFunctionInfo> function_info) {
461 if (!IsEnabled()) { 466 if (!IsEnabled()) {
462 return; 467 return;
463 } 468 }
464 469
465 ASSERT(boilerplate->IsBoilerplate()); 470 script.Put(source, function_info);
466 script.Put(source, boilerplate);
467 } 471 }
468 472
469 473
470 void CompilationCache::PutEval(Handle<String> source, 474 void CompilationCache::PutEval(Handle<String> source,
471 Handle<Context> context, 475 Handle<Context> context,
472 bool is_global, 476 bool is_global,
473 Handle<JSFunction> boilerplate) { 477 Handle<SharedFunctionInfo> function_info) {
474 if (!IsEnabled()) { 478 if (!IsEnabled()) {
475 return; 479 return;
476 } 480 }
477 481
478 HandleScope scope; 482 HandleScope scope;
479 ASSERT(boilerplate->IsBoilerplate());
480 if (is_global) { 483 if (is_global) {
481 eval_global.Put(source, context, boilerplate); 484 eval_global.Put(source, context, function_info);
482 } else { 485 } else {
483 eval_contextual.Put(source, context, boilerplate); 486 eval_contextual.Put(source, context, function_info);
484 } 487 }
485 } 488 }
486 489
487 490
488 491
489 void CompilationCache::PutRegExp(Handle<String> source, 492 void CompilationCache::PutRegExp(Handle<String> source,
490 JSRegExp::Flags flags, 493 JSRegExp::Flags flags,
491 Handle<FixedArray> data) { 494 Handle<FixedArray> data) {
492 if (!IsEnabled()) { 495 if (!IsEnabled()) {
493 return; 496 return;
(...skipping 29 matching lines...) Expand all
523 } 526 }
524 527
525 528
526 void CompilationCache::Disable() { 529 void CompilationCache::Disable() {
527 enabled = false; 530 enabled = false;
528 Clear(); 531 Clear();
529 } 532 }
530 533
531 534
532 } } // namespace v8::internal 535 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/compilation-cache.h ('k') | src/compiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698