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 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/assembler.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compilation-cache.h" 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/serialize.h" 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The number of generations for each sub cache. 163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The number of ScriptGenerations is carefully chosen based on histograms. 173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// See issue 458: http://code.google.com/p/v8/issues/detail?id=458 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kScriptGenerations = 5; 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kEvalGlobalGenerations = 2; 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kEvalContextualGenerations = 2; 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kRegExpGenerations = 2; 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Initial size of each compilation cache table allocated. 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kInitialCacheSize = 64; 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2744f0eee88ff00398ff7f715fab053374d808c90dSteve BlockCompilationCache::CompilationCache(Isolate* isolate) 2844f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_(isolate), 2944f0eee88ff00398ff7f715fab053374d808c90dSteve Block script_(isolate, kScriptGenerations), 3044f0eee88ff00398ff7f715fab053374d808c90dSteve Block eval_global_(isolate, kEvalGlobalGenerations), 3144f0eee88ff00398ff7f715fab053374d808c90dSteve Block eval_contextual_(isolate, kEvalContextualGenerations), 3244f0eee88ff00398ff7f715fab053374d808c90dSteve Block reg_exp_(isolate, kRegExpGenerations), 333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch enabled_(true) { 3444f0eee88ff00398ff7f715fab053374d808c90dSteve Block CompilationSubCache* subcaches[kSubCacheCount] = 3544f0eee88ff00398ff7f715fab053374d808c90dSteve Block {&script_, &eval_global_, &eval_contextual_, ®_exp_}; 3644f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < kSubCacheCount; ++i) { 3744f0eee88ff00398ff7f715fab053374d808c90dSteve Block subcaches_[i] = subcaches[i]; 386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 423fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochCompilationCache::~CompilationCache() {} 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<CompilationCacheTable> CompilationSubCache::GetTable(int generation) { 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(generation < generations_); 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<CompilationCacheTable> result; 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (tables_[generation]->IsUndefined()) { 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result = CompilationCacheTable::New(isolate(), kInitialCacheSize); 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tables_[generation] = *result; 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompilationCacheTable* table = 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompilationCacheTable::cast(tables_[generation]); 5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block result = Handle<CompilationCacheTable>(table, isolate()); 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationSubCache::Age() { 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Age the generations implicitly killing off the oldest. 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = generations_ - 1; i > 0; i--) { 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tables_[i] = tables_[i - 1]; 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the first generation as unborn. 6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block tables_[0] = isolate()->heap()->undefined_value(); 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 71756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid CompilationSubCache::IterateFunctions(ObjectVisitor* v) { 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* undefined = isolate()->heap()->undefined_value(); 73756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < generations_; i++) { 74756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (tables_[i] != undefined) { 75756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick reinterpret_cast<CompilationCacheTable*>(tables_[i])->IterateElements(v); 76756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 77756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 78756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 79756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 80756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationSubCache::Iterate(ObjectVisitor* v) { 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v->VisitPointers(&tables_[0], &tables_[generations_]); 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationSubCache::Clear() { 8744f0eee88ff00398ff7f715fab053374d808c90dSteve Block MemsetPointer(tables_, isolate()->heap()->undefined_value(), generations_); 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid CompilationSubCache::Remove(Handle<SharedFunctionInfo> function_info) { 92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Probe the script generation tables. Make sure not to leak handles 93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // into the caller's handle scope. 9444f0eee88ff00398ff7f715fab053374d808c90dSteve Block { HandleScope scope(isolate()); 95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int generation = 0; generation < generations(); generation++) { 96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<CompilationCacheTable> table = GetTable(generation); 97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch table->Remove(*function_info); 98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 10344f0eee88ff00398ff7f715fab053374d808c90dSteve BlockCompilationCacheScript::CompilationCacheScript(Isolate* isolate, 10444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int generations) 10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block : CompilationSubCache(isolate, generations), 10644f0eee88ff00398ff7f715fab053374d808c90dSteve Block script_histogram_(NULL), 10744f0eee88ff00398ff7f715fab053374d808c90dSteve Block script_histogram_initialized_(false) { } 10844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 10944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We only re-use a cached function for some script source code if the 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// script originates from the same place. This is to avoid issues 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// when reporting errors, etc. 1136ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool CompilationCacheScript::HasOrigin( 1146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info, 1156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object> name, 1166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int line_offset, 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int column_offset, 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_shared_cross_origin) { 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. 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (line_offset != script->line_offset()->value()) return false; 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (column_offset != script->column_offset()->value()) return false; 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that both names are strings. If not, no match. 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!name->IsString() || !script->name()->IsString()) return false; 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Were both scripts tagged by the embedder as being shared cross-origin? 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_shared_cross_origin != script->is_shared_cross_origin()) return false; 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare the two name strings for equality. 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return String::Equals(Handle<String>::cast(name), 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String>(String::cast(script->name()))); 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// TODO(245): Need to allow identical code from different contexts to 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// be cached in the same script generation. Currently the first use 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// will be cached, but subsequent code from different source / line 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// won't. 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<SharedFunctionInfo> CompilationCacheScript::Lookup( 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> source, 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> name, 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int line_offset, 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int column_offset, 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_shared_cross_origin, 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Context> context) { 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* result = NULL; 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int generation; 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the script generation tables. Make sure not to leak handles 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // into the caller's handle scope. 15544f0eee88ff00398ff7f715fab053374d808c90dSteve Block { HandleScope scope(isolate()); 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (generation = 0; generation < generations(); generation++) { 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<CompilationCacheTable> table = GetTable(generation); 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> probe = table->Lookup(source, context); 1596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (probe->IsSharedFunctionInfo()) { 1606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info = 1616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo>::cast(probe); 1626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Break when we've found a suitable shared function info that 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // matches the origin. 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (HasOrigin(function_info, 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name, 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch line_offset, 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch column_offset, 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch is_shared_cross_origin)) { 1696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result = *function_info; 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!script_histogram_initialized_) { 17744f0eee88ff00398ff7f715fab053374d808c90dSteve Block script_histogram_ = isolate()->stats_table()->CreateHistogram( 17844f0eee88ff00398ff7f715fab053374d808c90dSteve Block "V8.ScriptCache", 17944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 0, 18044f0eee88ff00398ff7f715fab053374d808c90dSteve Block kScriptGenerations, 18144f0eee88ff00398ff7f715fab053374d808c90dSteve Block kScriptGenerations + 1); 18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block script_histogram_initialized_ = true; 18344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (script_histogram_ != NULL) { 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The level NUMBER_OF_SCRIPT_GENERATIONS is equivalent to a cache miss. 18744f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->stats_table()->AddHistogramSample(script_histogram_, generation); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Once outside the manacles of the handle scope, we need to recheck 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to see if we actually found a cached script. If so, we return a 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // handle created in the caller's handle scope. 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result != NULL) { 19444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result), 19544f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()); 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(HasOrigin(shared, 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name, 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch line_offset, 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch column_offset, 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch is_shared_cross_origin)); 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the script was found in a later generation, we promote it to 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the first generation to let it survive longer in the cache. 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (generation != 0) Put(source, context, shared); 20444f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->counters()->compilation_cache_hits()->Increment(); 2056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return shared; 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 20744f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->counters()->compilation_cache_misses()->Increment(); 2086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Handle<SharedFunctionInfo>::null(); 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCacheScript::Put(Handle<String> source, 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Context> context, 2156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info) { 21644f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope(isolate()); 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CompilationCacheTable> table = GetFirstTable(); 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetFirstTable( 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CompilationCacheTable::Put(table, source, context, function_info)); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMaybeHandle<SharedFunctionInfo> CompilationCacheEval::Lookup( 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> source, Handle<SharedFunctionInfo> outer_info, 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StrictMode strict_mode, int scope_position) { 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScope scope(isolate()); 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure not to leak the table into the surrounding handle 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scope. Otherwise, we risk keeping old tables around even after 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // having cleared the cache. 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> result = isolate()->factory()->undefined_value(); 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int generation; 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (generation = 0; generation < generations(); generation++) { 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CompilationCacheTable> table = GetTable(generation); 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result = table->LookupEval(source, outer_info, strict_mode, scope_position); 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result->IsSharedFunctionInfo()) break; 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (result->IsSharedFunctionInfo()) { 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<SharedFunctionInfo> function_info = 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<SharedFunctionInfo>::cast(result); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (generation != 0) { 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Put(source, outer_info, function_info, scope_position); 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 24344f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->counters()->compilation_cache_hits()->Increment(); 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return scope.CloseAndEscape(function_info); 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 24644f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->counters()->compilation_cache_misses()->Increment(); 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return MaybeHandle<SharedFunctionInfo>(); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCacheEval::Put(Handle<String> source, 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<SharedFunctionInfo> outer_info, 2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<SharedFunctionInfo> function_info, 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int scope_position) { 25644f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope(isolate()); 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CompilationCacheTable> table = GetFirstTable(); 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch table = CompilationCacheTable::PutEval(table, source, outer_info, 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function_info, scope_position); 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetFirstTable(table); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMaybeHandle<FixedArray> CompilationCacheRegExp::Lookup( 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> source, 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSRegExp::Flags flags) { 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScope scope(isolate()); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure not to leak the table into the surrounding handle 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scope. Otherwise, we risk keeping old tables around even after 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // having cleared the cache. 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> result = isolate()->factory()->undefined_value(); 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int generation; 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (generation = 0; generation < generations(); generation++) { 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CompilationCacheTable> table = GetTable(generation); 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result = table->LookupRegExp(source, flags); 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result->IsFixedArray()) break; 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result->IsFixedArray()) { 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<FixedArray> data = Handle<FixedArray>::cast(result); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (generation != 0) { 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Put(source, flags, data); 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 28344f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->counters()->compilation_cache_hits()->Increment(); 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return scope.CloseAndEscape(data); 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 28644f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->counters()->compilation_cache_misses()->Increment(); 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return MaybeHandle<FixedArray>(); 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCacheRegExp::Put(Handle<String> source, 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSRegExp::Flags flags, 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray> data) { 29544f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope(isolate()); 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<CompilationCacheTable> table = GetFirstTable(); 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetFirstTable(CompilationCacheTable::PutRegExp(table, source, flags, data)); 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid CompilationCache::Remove(Handle<SharedFunctionInfo> function_info) { 302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!IsEnabled()) return; 303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 30444f0eee88ff00398ff7f715fab053374d808c90dSteve Block eval_global_.Remove(function_info); 30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block eval_contextual_.Remove(function_info); 30644f0eee88ff00398ff7f715fab053374d808c90dSteve Block script_.Remove(function_info); 307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMaybeHandle<SharedFunctionInfo> CompilationCache::LookupScript( 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> source, 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Object> name, 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int line_offset, 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int column_offset, 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_shared_cross_origin, 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Context> context) { 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!IsEnabled()) return MaybeHandle<SharedFunctionInfo>(); 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return script_.Lookup(source, name, line_offset, column_offset, 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch is_shared_cross_origin, context); 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMaybeHandle<SharedFunctionInfo> CompilationCache::LookupEval( 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<String> source, Handle<SharedFunctionInfo> outer_info, 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Context> context, StrictMode strict_mode, int scope_position) { 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!IsEnabled()) return MaybeHandle<SharedFunctionInfo>(); 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MaybeHandle<SharedFunctionInfo> result; 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (context->IsNativeContext()) { 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result = 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch eval_global_.Lookup(source, outer_info, strict_mode, scope_position); 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(scope_position != RelocInfo::kNoPosition); 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result = eval_contextual_.Lookup(source, outer_info, strict_mode, 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch scope_position); 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMaybeHandle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source, 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSRegExp::Flags flags) { 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!IsEnabled()) return MaybeHandle<FixedArray>(); 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 34644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return reg_exp_.Lookup(source, flags); 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::PutScript(Handle<String> source, 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Context> context, 3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info) { 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!IsEnabled()) return; 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch script_.Put(source, context, function_info); 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::PutEval(Handle<String> source, 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<SharedFunctionInfo> outer_info, 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Context> context, 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<SharedFunctionInfo> function_info, 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int scope_position) { 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!IsEnabled()) return; 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36644f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope(isolate()); 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (context->IsNativeContext()) { 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch eval_global_.Put(source, outer_info, function_info, scope_position); 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(scope_position != RelocInfo::kNoPosition); 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch eval_contextual_.Put(source, outer_info, function_info, scope_position); 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::PutRegExp(Handle<String> source, 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSRegExp::Flags flags, 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray> data) { 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!IsEnabled()) { 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 38444f0eee88ff00398ff7f715fab053374d808c90dSteve Block reg_exp_.Put(source, flags, data); 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::Clear() { 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kSubCacheCount; i++) { 39044f0eee88ff00398ff7f715fab053374d808c90dSteve Block subcaches_[i]->Clear(); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 395756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid CompilationCache::Iterate(ObjectVisitor* v) { 396756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < kSubCacheCount; i++) { 39744f0eee88ff00398ff7f715fab053374d808c90dSteve Block subcaches_[i]->Iterate(v); 398756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 3997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 4007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 4017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 402756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid CompilationCache::IterateFunctions(ObjectVisitor* v) { 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kSubCacheCount; i++) { 40444f0eee88ff00398ff7f715fab053374d808c90dSteve Block subcaches_[i]->IterateFunctions(v); 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::MarkCompactPrologue() { 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kSubCacheCount; i++) { 41144f0eee88ff00398ff7f715fab053374d808c90dSteve Block subcaches_[i]->Age(); 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::Enable() { 41744f0eee88ff00398ff7f715fab053374d808c90dSteve Block enabled_ = true; 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::Disable() { 42244f0eee88ff00398ff7f715fab053374d808c90dSteve Block enabled_ = false; 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Clear(); 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 428