13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compilation-cache.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/assembler.h" 8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/counters.h" 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/factory.h" 10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/objects-inl.h" 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The number of generations for each sub cache. 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kRegExpGenerations = 2; 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Initial size of each compilation cache table allocated. 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kInitialCacheSize = 64; 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2344f0eee88ff00398ff7f715fab053374d808c90dSteve BlockCompilationCache::CompilationCache(Isolate* isolate) 2444f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_(isolate), 25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier script_(isolate, 1), 26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier eval_global_(isolate, 1), 27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier eval_contextual_(isolate, 1), 2844f0eee88ff00398ff7f715fab053374d808c90dSteve Block reg_exp_(isolate, kRegExpGenerations), 293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch enabled_(true) { 3044f0eee88ff00398ff7f715fab053374d808c90dSteve Block CompilationSubCache* subcaches[kSubCacheCount] = 3144f0eee88ff00398ff7f715fab053374d808c90dSteve Block {&script_, &eval_global_, &eval_contextual_, ®_exp_}; 3244f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < kSubCacheCount; ++i) { 3344f0eee88ff00398ff7f715fab053374d808c90dSteve Block subcaches_[i] = subcaches[i]; 346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 383fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochCompilationCache::~CompilationCache() {} 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<CompilationCacheTable> CompilationSubCache::GetTable(int generation) { 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(generation < generations_); 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<CompilationCacheTable> result; 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (tables_[generation]->IsUndefined()) { 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result = CompilationCacheTable::New(isolate(), kInitialCacheSize); 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tables_[generation] = *result; 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompilationCacheTable* table = 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompilationCacheTable::cast(tables_[generation]); 5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block result = Handle<CompilationCacheTable>(table, isolate()); 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationSubCache::Age() { 57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Don't directly age single-generation caches. 58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (generations_ == 1) { 59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (tables_[0] != isolate()->heap()->undefined_value()) { 60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier CompilationCacheTable::cast(tables_[0])->Age(); 61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return; 63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Age the generations implicitly killing off the oldest. 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = generations_ - 1; i > 0; i--) { 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tables_[i] = tables_[i - 1]; 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the first generation as unborn. 7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block tables_[0] = isolate()->heap()->undefined_value(); 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 75756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid CompilationSubCache::IterateFunctions(ObjectVisitor* v) { 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* undefined = isolate()->heap()->undefined_value(); 77756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < generations_; i++) { 78756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (tables_[i] != undefined) { 79756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick reinterpret_cast<CompilationCacheTable*>(tables_[i])->IterateElements(v); 80756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 81756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 82756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 83756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 84756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationSubCache::Iterate(ObjectVisitor* v) { 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v->VisitPointers(&tables_[0], &tables_[generations_]); 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationSubCache::Clear() { 9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block MemsetPointer(tables_, isolate()->heap()->undefined_value(), generations_); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid CompilationSubCache::Remove(Handle<SharedFunctionInfo> function_info) { 96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Probe the script generation tables. Make sure not to leak handles 97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // into the caller's handle scope. 9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block { HandleScope scope(isolate()); 99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int generation = 0; generation < generations(); generation++) { 100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<CompilationCacheTable> table = GetTable(generation); 101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch table->Remove(*function_info); 102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 10744f0eee88ff00398ff7f715fab053374d808c90dSteve BlockCompilationCacheScript::CompilationCacheScript(Isolate* isolate, 10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int generations) 109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier : CompilationSubCache(isolate, generations) {} 11044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 11144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We only re-use a cached function for some script source code if the 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// script originates from the same place. This is to avoid issues 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// when reporting errors, etc. 115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool CompilationCacheScript::HasOrigin(Handle<SharedFunctionInfo> function_info, 116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Object> name, int line_offset, 117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int column_offset, 118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ScriptOriginOptions resource_options) { 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Script> script = 12044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Script>(Script::cast(function_info->script()), isolate()); 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the script name isn't set, the boilerplate script should have 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // an undefined name to have the same origin. 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (name.is_null()) { 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return script->name()->IsUndefined(); 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do the fast bailout checks first. 127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (line_offset != script->line_offset()) return false; 128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (column_offset != script->column_offset()) return false; 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that both names are strings. If not, no match. 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!name->IsString() || !script->name()->IsString()) return false; 131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Are the origin_options same? 132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (resource_options.Flags() != script->origin_options().Flags()) 133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return false; 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare the two name strings for equality. 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return String::Equals(Handle<String>::cast(name), 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String>(String::cast(script->name()))); 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// TODO(245): Need to allow identical code from different contexts to 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// be cached in the same script generation. Currently the first use 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// will be cached, but subsequent code from different source / line 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// won't. 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<SharedFunctionInfo> CompilationCacheScript::Lookup( 145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<String> source, Handle<Object> name, int line_offset, 146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int column_offset, ScriptOriginOptions resource_options, 147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Context> context, LanguageMode language_mode) { 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* result = NULL; 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int generation; 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the script generation tables. Make sure not to leak handles 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // into the caller's handle scope. 15344f0eee88ff00398ff7f715fab053374d808c90dSteve Block { HandleScope scope(isolate()); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (generation = 0; generation < generations(); generation++) { 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<CompilationCacheTable> table = GetTable(generation); 156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Object> probe = table->Lookup(source, context, language_mode); 1576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (probe->IsSharedFunctionInfo()) { 1586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info = 1596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo>::cast(probe); 1606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Break when we've found a suitable shared function info that 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // matches the origin. 162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (HasOrigin(function_info, name, line_offset, column_offset, 163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch resource_options)) { 1646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result = *function_info; 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Once outside the manacles of the handle scope, we need to recheck 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to see if we actually found a cached script. If so, we return a 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // handle created in the caller's handle scope. 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result != NULL) { 17544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result), 17644f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()); 177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK( 178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HasOrigin(shared, name, line_offset, column_offset, resource_options)); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the script was found in a later generation, we promote it to 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the first generation to let it survive longer in the cache. 181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (generation != 0) Put(source, context, language_mode, shared); 18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->counters()->compilation_cache_hits()->Increment(); 1836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return shared; 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 18544f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->counters()->compilation_cache_misses()->Increment(); 1866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Handle<SharedFunctionInfo>::null(); 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCacheScript::Put(Handle<String> source, 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Context> context, 193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LanguageMode language_mode, 1946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info) { 19544f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope(isolate()); 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CompilationCacheTable> table = GetFirstTable(); 197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch SetFirstTable(CompilationCacheTable::Put(table, source, context, 198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch language_mode, function_info)); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMaybeHandle<SharedFunctionInfo> CompilationCacheEval::Lookup( 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> source, Handle<SharedFunctionInfo> outer_info, 204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LanguageMode language_mode, int scope_position) { 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScope scope(isolate()); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure not to leak the table into the surrounding handle 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scope. Otherwise, we risk keeping old tables around even after 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // having cleared the cache. 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> result = isolate()->factory()->undefined_value(); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int generation; 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (generation = 0; generation < generations(); generation++) { 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CompilationCacheTable> table = GetTable(generation); 213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result = 214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch table->LookupEval(source, outer_info, language_mode, scope_position); 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result->IsSharedFunctionInfo()) break; 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (result->IsSharedFunctionInfo()) { 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<SharedFunctionInfo> function_info = 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<SharedFunctionInfo>::cast(result); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (generation != 0) { 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Put(source, outer_info, function_info, scope_position); 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 22344f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->counters()->compilation_cache_hits()->Increment(); 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return scope.CloseAndEscape(function_info); 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 22644f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->counters()->compilation_cache_misses()->Increment(); 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return MaybeHandle<SharedFunctionInfo>(); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCacheEval::Put(Handle<String> source, 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<SharedFunctionInfo> outer_info, 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<SharedFunctionInfo> function_info, 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int scope_position) { 23644f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope(isolate()); 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CompilationCacheTable> table = GetFirstTable(); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch table = CompilationCacheTable::PutEval(table, source, outer_info, 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function_info, scope_position); 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetFirstTable(table); 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMaybeHandle<FixedArray> CompilationCacheRegExp::Lookup( 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> source, 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSRegExp::Flags flags) { 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScope scope(isolate()); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure not to leak the table into the surrounding handle 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scope. Otherwise, we risk keeping old tables around even after 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // having cleared the cache. 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> result = isolate()->factory()->undefined_value(); 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int generation; 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (generation = 0; generation < generations(); generation++) { 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CompilationCacheTable> table = GetTable(generation); 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result = table->LookupRegExp(source, flags); 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result->IsFixedArray()) break; 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result->IsFixedArray()) { 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<FixedArray> data = Handle<FixedArray>::cast(result); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (generation != 0) { 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Put(source, flags, data); 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 26344f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->counters()->compilation_cache_hits()->Increment(); 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return scope.CloseAndEscape(data); 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 26644f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->counters()->compilation_cache_misses()->Increment(); 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return MaybeHandle<FixedArray>(); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCacheRegExp::Put(Handle<String> source, 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSRegExp::Flags flags, 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray> data) { 27544f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope(isolate()); 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CompilationCacheTable> table = GetFirstTable(); 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetFirstTable(CompilationCacheTable::PutRegExp(table, source, flags, data)); 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid CompilationCache::Remove(Handle<SharedFunctionInfo> function_info) { 282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!IsEnabled()) return; 283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 28444f0eee88ff00398ff7f715fab053374d808c90dSteve Block eval_global_.Remove(function_info); 28544f0eee88ff00398ff7f715fab053374d808c90dSteve Block eval_contextual_.Remove(function_info); 28644f0eee88ff00398ff7f715fab053374d808c90dSteve Block script_.Remove(function_info); 287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMaybeHandle<SharedFunctionInfo> CompilationCache::LookupScript( 291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<String> source, Handle<Object> name, int line_offset, 292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int column_offset, ScriptOriginOptions resource_options, 293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Context> context, LanguageMode language_mode) { 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!IsEnabled()) return MaybeHandle<SharedFunctionInfo>(); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return script_.Lookup(source, name, line_offset, column_offset, 297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch resource_options, context, language_mode); 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMaybeHandle<SharedFunctionInfo> CompilationCache::LookupEval( 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> source, Handle<SharedFunctionInfo> outer_info, 303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<Context> context, LanguageMode language_mode, int scope_position) { 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!IsEnabled()) return MaybeHandle<SharedFunctionInfo>(); 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MaybeHandle<SharedFunctionInfo> result; 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (context->IsNativeContext()) { 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result = 309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch eval_global_.Lookup(source, outer_info, language_mode, scope_position); 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(scope_position != RelocInfo::kNoPosition); 312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch result = eval_contextual_.Lookup(source, outer_info, language_mode, 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scope_position); 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMaybeHandle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source, 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSRegExp::Flags flags) { 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!IsEnabled()) return MaybeHandle<FixedArray>(); 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 32344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return reg_exp_.Lookup(source, flags); 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::PutScript(Handle<String> source, 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Context> context, 329014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LanguageMode language_mode, 3306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info) { 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!IsEnabled()) return; 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch script_.Put(source, context, language_mode, function_info); 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::PutEval(Handle<String> source, 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<SharedFunctionInfo> outer_info, 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Context> context, 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<SharedFunctionInfo> function_info, 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int scope_position) { 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!IsEnabled()) return; 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 34444f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope(isolate()); 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (context->IsNativeContext()) { 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch eval_global_.Put(source, outer_info, function_info, scope_position); 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(scope_position != RelocInfo::kNoPosition); 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch eval_contextual_.Put(source, outer_info, function_info, scope_position); 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::PutRegExp(Handle<String> source, 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSRegExp::Flags flags, 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray> data) { 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!IsEnabled()) { 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36244f0eee88ff00398ff7f715fab053374d808c90dSteve Block reg_exp_.Put(source, flags, data); 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::Clear() { 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kSubCacheCount; i++) { 36844f0eee88ff00398ff7f715fab053374d808c90dSteve Block subcaches_[i]->Clear(); 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 37244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 373756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid CompilationCache::Iterate(ObjectVisitor* v) { 374756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < kSubCacheCount; i++) { 37544f0eee88ff00398ff7f715fab053374d808c90dSteve Block subcaches_[i]->Iterate(v); 376756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 3777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 3787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 3797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 380756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid CompilationCache::IterateFunctions(ObjectVisitor* v) { 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kSubCacheCount; i++) { 38244f0eee88ff00398ff7f715fab053374d808c90dSteve Block subcaches_[i]->IterateFunctions(v); 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::MarkCompactPrologue() { 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kSubCacheCount; i++) { 38944f0eee88ff00398ff7f715fab053374d808c90dSteve Block subcaches_[i]->Age(); 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::Enable() { 39544f0eee88ff00398ff7f715fab053374d808c90dSteve Block enabled_ = true; 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::Disable() { 40044f0eee88ff00398ff7f715fab053374d808c90dSteve Block enabled_ = false; 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Clear(); 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 406014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 407