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, &reg_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 &map;
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