compilation-cache.cc revision 1e0659c275bb392c045087af4f6b0d7565cb3d77
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2008 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "compilation-cache.h" 313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "serialize.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The number of sub caches covering the different types to cache. 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kSubCacheCount = 4; 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The number of generations for each sub cache. 403ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The number of ScriptGenerations is carefully chosen based on histograms. 413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// See issue 458: http://code.google.com/p/v8/issues/detail?id=458 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kScriptGenerations = 5; 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kEvalGlobalGenerations = 2; 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kEvalContextualGenerations = 2; 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kRegExpGenerations = 2; 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Initial size of each compilation cache table allocated. 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kInitialCacheSize = 64; 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Index for the first generation in the cache. 516ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic const int kFirstGeneration = 0; 526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The compilation cache consists of several generational sub-caches which uses 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// this class as a base class. A sub-cache contains a compilation cache tables 553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// for each generation of the sub-cache. Since the same source code string has 563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// different compiled code for scripts and evals, we use separate sub-caches 573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// for different compilation modes, to avoid retrieving the wrong result. 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CompilationSubCache { 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit CompilationSubCache(int generations): generations_(generations) { 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tables_ = NewArray<Object*>(generations); 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~CompilationSubCache() { DeleteArray(tables_); } 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the compilation cache tables for a specific generation. 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<CompilationCacheTable> GetTable(int generation); 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Accessors for first generation. 706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<CompilationCacheTable> GetFirstTable() { 716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return GetTable(kFirstGeneration); 726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void SetFirstTable(Handle<CompilationCacheTable> value) { 746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(kFirstGeneration < generations_); 756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block tables_[kFirstGeneration] = *value; 766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Age the sub-cache by evicting the oldest generation and creating a new 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // young generation. 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Age(); 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // GC support. 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Iterate(ObjectVisitor* v); 84756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick void IterateFunctions(ObjectVisitor* v); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Clear this sub-cache evicting all its content. 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Clear(); 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Remove given shared function info from sub-cache. 90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Remove(Handle<SharedFunctionInfo> function_info); 91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Number of generations in this sub-cache. 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block inline int generations() { return generations_; } 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int generations_; // Number of generations. 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object** tables_; // Compilation cache tables - one for each generation. 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationSubCache); 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Sub-cache for scripts. 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CompilationCacheScript : public CompilationSubCache { 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit CompilationCacheScript(int generations) 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : CompilationSubCache(generations) { } 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> Lookup(Handle<String> source, 1106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object> name, 1116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int line_offset, 1126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int column_offset); 1136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void Put(Handle<String> source, Handle<SharedFunctionInfo> function_info); 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MUST_USE_RESULT MaybeObject* TryTablePut( 1170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<String> source, Handle<SharedFunctionInfo> function_info); 1180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 1196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Note: Returns a new hash table if operation results in expansion. 1206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<CompilationCacheTable> TablePut( 1216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<String> source, Handle<SharedFunctionInfo> function_info); 1226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool HasOrigin(Handle<SharedFunctionInfo> function_info, 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> name, 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int line_offset, 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int column_offset); 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheScript); 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Sub-cache for eval scripts. 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CompilationCacheEval: public CompilationSubCache { 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit CompilationCacheEval(int generations) 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : CompilationSubCache(generations) { } 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> Lookup(Handle<String> source, 1391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Context> context, 1401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block StrictModeFlag strict_mode); 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Put(Handle<String> source, 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Context> context, 1446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info); 1456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 1475913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MUST_USE_RESULT MaybeObject* TryTablePut( 1480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<String> source, 1490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<Context> context, 1500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<SharedFunctionInfo> function_info); 1510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 1520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 1536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Note: Returns a new hash table if operation results in expansion. 1546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<CompilationCacheTable> TablePut( 1556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<String> source, 1566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Context> context, 1576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info); 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval); 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Sub-cache for regular expressions. 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CompilationCacheRegExp: public CompilationSubCache { 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit CompilationCacheRegExp(int generations) 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : CompilationSubCache(generations) { } 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray> Lookup(Handle<String> source, JSRegExp::Flags flags); 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Put(Handle<String> source, 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSRegExp::Flags flags, 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray> data); 1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 1755913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck MUST_USE_RESULT MaybeObject* TryTablePut(Handle<String> source, 1765913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck JSRegExp::Flags flags, 1775913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck Handle<FixedArray> data); 1780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 1796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Note: Returns a new hash table if operation results in expansion. 1806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<CompilationCacheTable> TablePut(Handle<String> source, 1816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSRegExp::Flags flags, 1826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<FixedArray> data); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheRegExp); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Statically allocate all the sub-caches. 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic CompilationCacheScript script(kScriptGenerations); 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic CompilationCacheEval eval_global(kEvalGlobalGenerations); 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic CompilationCacheEval eval_contextual(kEvalContextualGenerations); 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic CompilationCacheRegExp reg_exp(kRegExpGenerations); 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic CompilationSubCache* subcaches[kSubCacheCount] = 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block {&script, &eval_global, &eval_contextual, ®_exp}; 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Current enable state of the compilation cache. 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool enabled = true; 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline bool IsEnabled() { 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return FLAG_compilation_cache && enabled; 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic Handle<CompilationCacheTable> AllocateTable(int size) { 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CALL_HEAP_FUNCTION(CompilationCacheTable::Allocate(size), 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompilationCacheTable); 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<CompilationCacheTable> CompilationSubCache::GetTable(int generation) { 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(generation < generations_); 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<CompilationCacheTable> result; 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (tables_[generation]->IsUndefined()) { 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = AllocateTable(kInitialCacheSize); 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tables_[generation] = *result; 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompilationCacheTable* table = 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CompilationCacheTable::cast(tables_[generation]); 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = Handle<CompilationCacheTable>(table); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationSubCache::Age() { 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Age the generations implicitly killing off the oldest. 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = generations_ - 1; i > 0; i--) { 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tables_[i] = tables_[i - 1]; 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the first generation as unborn. 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tables_[0] = Heap::undefined_value(); 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 236756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid CompilationSubCache::IterateFunctions(ObjectVisitor* v) { 237756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Object* undefined = Heap::raw_unchecked_undefined_value(); 238756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < generations_; i++) { 239756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (tables_[i] != undefined) { 240756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick reinterpret_cast<CompilationCacheTable*>(tables_[i])->IterateElements(v); 241756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 242756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 243756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 244756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 245756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationSubCache::Iterate(ObjectVisitor* v) { 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block v->VisitPointers(&tables_[0], &tables_[generations_]); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationSubCache::Clear() { 2526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block MemsetPointer(tables_, Heap::undefined_value(), generations_); 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid CompilationSubCache::Remove(Handle<SharedFunctionInfo> function_info) { 257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Probe the script generation tables. Make sure not to leak handles 258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // into the caller's handle scope. 259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { HandleScope scope; 260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int generation = 0; generation < generations(); generation++) { 261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<CompilationCacheTable> table = GetTable(generation); 262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch table->Remove(*function_info); 263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We only re-use a cached function for some script source code if the 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// script originates from the same place. This is to avoid issues 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// when reporting errors, etc. 2716ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockbool CompilationCacheScript::HasOrigin( 2726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info, 2736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object> name, 2746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int line_offset, 2756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int column_offset) { 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Script> script = 2776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Script>(Script::cast(function_info->script())); 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the script name isn't set, the boilerplate script should have 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // an undefined name to have the same origin. 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (name.is_null()) { 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return script->name()->IsUndefined(); 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do the fast bailout checks first. 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (line_offset != script->line_offset()->value()) return false; 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (column_offset != script->column_offset()->value()) return false; 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that both names are strings. If not, no match. 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!name->IsString() || !script->name()->IsString()) return false; 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare the two name strings for equality. 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return String::cast(*name)->Equals(String::cast(script->name())); 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// TODO(245): Need to allow identical code from different contexts to 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// be cached in the same script generation. Currently the first use 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// will be cached, but subsequent code from different source / line 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// won't. 2976ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockHandle<SharedFunctionInfo> CompilationCacheScript::Lookup(Handle<String> source, 2986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object> name, 2996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int line_offset, 3006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int column_offset) { 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* result = NULL; 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int generation; 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the script generation tables. Make sure not to leak handles 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // into the caller's handle scope. 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { HandleScope scope; 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (generation = 0; generation < generations(); generation++) { 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<CompilationCacheTable> table = GetTable(generation); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> probe(table->Lookup(*source)); 3106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (probe->IsSharedFunctionInfo()) { 3116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info = 3126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo>::cast(probe); 3136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Break when we've found a suitable shared function info that 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // matches the origin. 3156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (HasOrigin(function_info, name, line_offset, column_offset)) { 3166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block result = *function_info; 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void* script_histogram = StatsTable::CreateHistogram( 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "V8.ScriptCache", 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 0, 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block kScriptGenerations, 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block kScriptGenerations + 1); 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (script_histogram != NULL) { 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The level NUMBER_OF_SCRIPT_GENERATIONS is equivalent to a cache miss. 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StatsTable::AddHistogramSample(script_histogram, generation); 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Once outside the manacles of the handle scope, we need to recheck 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to see if we actually found a cached script. If so, we return a 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // handle created in the caller's handle scope. 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result != NULL) { 3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result)); 3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(HasOrigin(shared, name, line_offset, column_offset)); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the script was found in a later generation, we promote it to 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the first generation to let it survive longer in the cache. 3426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (generation != 0) Put(source, shared); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Counters::compilation_cache_hits.Increment(); 3446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return shared; 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Counters::compilation_cache_misses.Increment(); 3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Handle<SharedFunctionInfo>::null(); 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3525913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CompilationCacheScript::TryTablePut( 3530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<String> source, 3540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<SharedFunctionInfo> function_info) { 3550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<CompilationCacheTable> table = GetFirstTable(); 3560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return table->Put(*source, *function_info); 3570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 3580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 3606ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockHandle<CompilationCacheTable> CompilationCacheScript::TablePut( 3616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<String> source, 3626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info) { 3630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CALL_HEAP_FUNCTION(TryTablePut(source, function_info), CompilationCacheTable); 3646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 3656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCacheScript::Put(Handle<String> source, 3686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info) { 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandleScope scope; 3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetFirstTable(TablePut(source, function_info)); 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3746ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockHandle<SharedFunctionInfo> CompilationCacheEval::Lookup( 3751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<String> source, 3761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Context> context, 3771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block StrictModeFlag strict_mode) { 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure not to leak the table into the surrounding handle 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scope. Otherwise, we risk keeping old tables around even after 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // having cleared the cache. 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* result = NULL; 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int generation; 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { HandleScope scope; 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (generation = 0; generation < generations(); generation++) { 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<CompilationCacheTable> table = GetTable(generation); 3861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block result = table->LookupEval(*source, *context, strict_mode); 3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (result->IsSharedFunctionInfo()) { 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (result->IsSharedFunctionInfo()) { 3936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> 3946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block function_info(SharedFunctionInfo::cast(result)); 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (generation != 0) { 3966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Put(source, context, function_info); 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Counters::compilation_cache_hits.Increment(); 3996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return function_info; 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Counters::compilation_cache_misses.Increment(); 4026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Handle<SharedFunctionInfo>::null(); 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4075913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CompilationCacheEval::TryTablePut( 4080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<String> source, 4090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<Context> context, 4100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<SharedFunctionInfo> function_info) { 4110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<CompilationCacheTable> table = GetFirstTable(); 4120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return table->PutEval(*source, *context, *function_info); 4130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4166ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockHandle<CompilationCacheTable> CompilationCacheEval::TablePut( 4176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<String> source, 4186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Context> context, 4196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info) { 4200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CALL_HEAP_FUNCTION(TryTablePut(source, context, function_info), 4216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CompilationCacheTable); 4226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 4236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCacheEval::Put(Handle<String> source, 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Context> context, 4276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info) { 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandleScope scope; 4296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetFirstTable(TablePut(source, context, function_info)); 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<FixedArray> CompilationCacheRegExp::Lookup(Handle<String> source, 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSRegExp::Flags flags) { 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure not to leak the table into the surrounding handle 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scope. Otherwise, we risk keeping old tables around even after 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // having cleared the cache. 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* result = NULL; 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int generation; 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { HandleScope scope; 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (generation = 0; generation < generations(); generation++) { 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<CompilationCacheTable> table = GetTable(generation); 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = table->LookupRegExp(*source, flags); 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result->IsFixedArray()) { 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result->IsFixedArray()) { 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray> data(FixedArray::cast(result)); 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (generation != 0) { 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Put(source, flags, data); 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Counters::compilation_cache_hits.Increment(); 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return data; 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Counters::compilation_cache_misses.Increment(); 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Handle<FixedArray>::null(); 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4635913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckMaybeObject* CompilationCacheRegExp::TryTablePut( 4640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<String> source, 4650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen JSRegExp::Flags flags, 4660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<FixedArray> data) { 4670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<CompilationCacheTable> table = GetFirstTable(); 4680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return table->PutRegExp(*source, flags, *data); 4690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4726ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockHandle<CompilationCacheTable> CompilationCacheRegExp::TablePut( 4736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<String> source, 4746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block JSRegExp::Flags flags, 4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<FixedArray> data) { 4760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen CALL_HEAP_FUNCTION(TryTablePut(source, flags, data), CompilationCacheTable); 4776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 4786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCacheRegExp::Put(Handle<String> source, 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSRegExp::Flags flags, 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray> data) { 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandleScope scope; 4846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block SetFirstTable(TablePut(source, flags, data)); 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid CompilationCache::Remove(Handle<SharedFunctionInfo> function_info) { 489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!IsEnabled()) return; 490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch eval_global.Remove(function_info); 492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch eval_contextual.Remove(function_info); 493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch script.Remove(function_info); 494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4976ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockHandle<SharedFunctionInfo> CompilationCache::LookupScript(Handle<String> source, 4986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<Object> name, 4996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int line_offset, 5006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int column_offset) { 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!IsEnabled()) { 5026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Handle<SharedFunctionInfo>::null(); 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return script.Lookup(source, name, line_offset, column_offset); 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5091e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockHandle<SharedFunctionInfo> CompilationCache::LookupEval( 5101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<String> source, 5111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Context> context, 5121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool is_global, 5131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block StrictModeFlag strict_mode) { 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!IsEnabled()) { 5156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return Handle<SharedFunctionInfo>::null(); 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> result; 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (is_global) { 5201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block result = eval_global.Lookup(source, context, strict_mode); 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 5221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block result = eval_contextual.Lookup(source, context, strict_mode); 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source, 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSRegExp::Flags flags) { 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!IsEnabled()) { 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Handle<FixedArray>::null(); 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return reg_exp.Lookup(source, flags); 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::PutScript(Handle<String> source, 5396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info) { 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!IsEnabled()) { 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block script.Put(source, function_info); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::PutEval(Handle<String> source, 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Context> context, 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_global, 5516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Handle<SharedFunctionInfo> function_info) { 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!IsEnabled()) { 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandleScope scope; 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (is_global) { 5586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block eval_global.Put(source, context, function_info); 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 5606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block eval_contextual.Put(source, context, function_info); 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::PutRegExp(Handle<String> source, 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block JSRegExp::Flags flags, 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<FixedArray> data) { 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!IsEnabled()) { 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reg_exp.Put(source, flags, data); 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool SourceHashCompare(void* key1, void* key2) { 578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return key1 == key2; 579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic HashMap* EagerOptimizingSet() { 583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static HashMap map(&SourceHashCompare); 584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return ↦ 585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool CompilationCache::ShouldOptimizeEagerly(Handle<JSFunction> function) { 589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_opt_eagerly) return true; 590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t hash = function->SourceHash(); 591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void* key = reinterpret_cast<void*>(hash); 592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return EagerOptimizingSet()->Lookup(key, hash, false) != NULL; 593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid CompilationCache::MarkForEagerOptimizing(Handle<JSFunction> function) { 597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t hash = function->SourceHash(); 598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void* key = reinterpret_cast<void*>(hash); 599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EagerOptimizingSet()->Lookup(key, hash, true); 600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid CompilationCache::MarkForLazyOptimizing(Handle<JSFunction> function) { 604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t hash = function->SourceHash(); 605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void* key = reinterpret_cast<void*>(hash); 606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EagerOptimizingSet()->Remove(key, hash); 607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid CompilationCache::ResetEagerOptimizingData() { 611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HashMap* set = EagerOptimizingSet(); 612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (set->occupancy() > 0) set->Clear(); 613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::Clear() { 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kSubCacheCount; i++) { 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block subcaches[i]->Clear(); 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 622756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid CompilationCache::Iterate(ObjectVisitor* v) { 623756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < kSubCacheCount; i++) { 624756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick subcaches[i]->Iterate(v); 625756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 6267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 6277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 6287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 629756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid CompilationCache::IterateFunctions(ObjectVisitor* v) { 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kSubCacheCount; i++) { 631756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick subcaches[i]->IterateFunctions(v); 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::MarkCompactPrologue() { 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kSubCacheCount; i++) { 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block subcaches[i]->Age(); 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::Enable() { 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enabled = true; 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid CompilationCache::Disable() { 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enabled = false; 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Clear(); 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 655