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

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

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