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