blob: 5bd8bf31c84695c2d38c4a59274588af8ac5af33 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "compilation-cache.h"
Andrei Popescu31002712010-02-23 13:46:05 +000031#include "serialize.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000032
33namespace v8 {
34namespace internal {
35
Steve Blocka7e24c12009-10-30 11:49:00 +000036
37// The number of generations for each sub cache.
Steve Block3ce2e202009-11-05 08:53:23 +000038// The number of ScriptGenerations is carefully chosen based on histograms.
39// See issue 458: http://code.google.com/p/v8/issues/detail?id=458
Steve Blocka7e24c12009-10-30 11:49:00 +000040static const int kScriptGenerations = 5;
41static const int kEvalGlobalGenerations = 2;
42static const int kEvalContextualGenerations = 2;
43static const int kRegExpGenerations = 2;
Steve Blocka7e24c12009-10-30 11:49:00 +000044
Steve Block3ce2e202009-11-05 08:53:23 +000045// Initial size of each compilation cache table allocated.
Steve Blocka7e24c12009-10-30 11:49:00 +000046static const int kInitialCacheSize = 64;
47
Steve Block6ded16b2010-05-10 14:33:55 +010048
Steve Block44f0eee2011-05-26 01:26:41 +010049CompilationCache::CompilationCache(Isolate* isolate)
50 : isolate_(isolate),
51 script_(isolate, kScriptGenerations),
52 eval_global_(isolate, kEvalGlobalGenerations),
53 eval_contextual_(isolate, kEvalContextualGenerations),
54 reg_exp_(isolate, kRegExpGenerations),
55 enabled_(true),
56 eager_optimizing_set_(NULL) {
57 CompilationSubCache* subcaches[kSubCacheCount] =
58 {&script_, &eval_global_, &eval_contextual_, &reg_exp_};
59 for (int i = 0; i < kSubCacheCount; ++i) {
60 subcaches_[i] = subcaches[i];
Steve Blocka7e24c12009-10-30 11:49:00 +000061 }
Steve Blocka7e24c12009-10-30 11:49:00 +000062}
63
64
Steve Block44f0eee2011-05-26 01:26:41 +010065CompilationCache::~CompilationCache() {
66 delete eager_optimizing_set_;
67 eager_optimizing_set_ = NULL;
68}
69
70
71static Handle<CompilationCacheTable> AllocateTable(Isolate* isolate, int size) {
72 CALL_HEAP_FUNCTION(isolate,
73 CompilationCacheTable::Allocate(size),
Steve Blocka7e24c12009-10-30 11:49:00 +000074 CompilationCacheTable);
75}
76
77
78Handle<CompilationCacheTable> CompilationSubCache::GetTable(int generation) {
79 ASSERT(generation < generations_);
80 Handle<CompilationCacheTable> result;
81 if (tables_[generation]->IsUndefined()) {
Steve Block44f0eee2011-05-26 01:26:41 +010082 result = AllocateTable(isolate(), kInitialCacheSize);
Steve Blocka7e24c12009-10-30 11:49:00 +000083 tables_[generation] = *result;
84 } else {
85 CompilationCacheTable* table =
86 CompilationCacheTable::cast(tables_[generation]);
Steve Block44f0eee2011-05-26 01:26:41 +010087 result = Handle<CompilationCacheTable>(table, isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +000088 }
89 return result;
90}
91
Steve Blocka7e24c12009-10-30 11:49:00 +000092void CompilationSubCache::Age() {
93 // Age the generations implicitly killing off the oldest.
94 for (int i = generations_ - 1; i > 0; i--) {
95 tables_[i] = tables_[i - 1];
96 }
97
98 // Set the first generation as unborn.
Steve Block44f0eee2011-05-26 01:26:41 +010099 tables_[0] = isolate()->heap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000100}
101
102
Iain Merrick75681382010-08-19 15:07:18 +0100103void CompilationSubCache::IterateFunctions(ObjectVisitor* v) {
Steve Block44f0eee2011-05-26 01:26:41 +0100104 Object* undefined = isolate()->heap()->raw_unchecked_undefined_value();
Iain Merrick75681382010-08-19 15:07:18 +0100105 for (int i = 0; i < generations_; i++) {
106 if (tables_[i] != undefined) {
107 reinterpret_cast<CompilationCacheTable*>(tables_[i])->IterateElements(v);
108 }
109 }
110}
111
112
Steve Blocka7e24c12009-10-30 11:49:00 +0000113void CompilationSubCache::Iterate(ObjectVisitor* v) {
114 v->VisitPointers(&tables_[0], &tables_[generations_]);
115}
116
117
118void CompilationSubCache::Clear() {
Steve Block44f0eee2011-05-26 01:26:41 +0100119 MemsetPointer(tables_, isolate()->heap()->undefined_value(), generations_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000120}
121
122
Ben Murdochb0fe1622011-05-05 13:52:32 +0100123void CompilationSubCache::Remove(Handle<SharedFunctionInfo> function_info) {
124 // Probe the script generation tables. Make sure not to leak handles
125 // into the caller's handle scope.
Steve Block44f0eee2011-05-26 01:26:41 +0100126 { HandleScope scope(isolate());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100127 for (int generation = 0; generation < generations(); generation++) {
128 Handle<CompilationCacheTable> table = GetTable(generation);
129 table->Remove(*function_info);
130 }
131 }
132}
133
134
Steve Block44f0eee2011-05-26 01:26:41 +0100135CompilationCacheScript::CompilationCacheScript(Isolate* isolate,
136 int generations)
137 : CompilationSubCache(isolate, generations),
138 script_histogram_(NULL),
139 script_histogram_initialized_(false) { }
140
141
Steve Blocka7e24c12009-10-30 11:49:00 +0000142// We only re-use a cached function for some script source code if the
143// script originates from the same place. This is to avoid issues
144// when reporting errors, etc.
Steve Block6ded16b2010-05-10 14:33:55 +0100145bool CompilationCacheScript::HasOrigin(
146 Handle<SharedFunctionInfo> function_info,
147 Handle<Object> name,
148 int line_offset,
149 int column_offset) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000150 Handle<Script> script =
Steve Block44f0eee2011-05-26 01:26:41 +0100151 Handle<Script>(Script::cast(function_info->script()), isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000152 // If the script name isn't set, the boilerplate script should have
153 // an undefined name to have the same origin.
154 if (name.is_null()) {
155 return script->name()->IsUndefined();
156 }
157 // Do the fast bailout checks first.
158 if (line_offset != script->line_offset()->value()) return false;
159 if (column_offset != script->column_offset()->value()) return false;
160 // Check that both names are strings. If not, no match.
161 if (!name->IsString() || !script->name()->IsString()) return false;
162 // Compare the two name strings for equality.
163 return String::cast(*name)->Equals(String::cast(script->name()));
164}
165
166
167// TODO(245): Need to allow identical code from different contexts to
168// be cached in the same script generation. Currently the first use
169// will be cached, but subsequent code from different source / line
170// won't.
Steve Block6ded16b2010-05-10 14:33:55 +0100171Handle<SharedFunctionInfo> CompilationCacheScript::Lookup(Handle<String> source,
172 Handle<Object> name,
173 int line_offset,
174 int column_offset) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000175 Object* result = NULL;
176 int generation;
177
178 // Probe the script generation tables. Make sure not to leak handles
179 // into the caller's handle scope.
Steve Block44f0eee2011-05-26 01:26:41 +0100180 { HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000181 for (generation = 0; generation < generations(); generation++) {
182 Handle<CompilationCacheTable> table = GetTable(generation);
Steve Block44f0eee2011-05-26 01:26:41 +0100183 Handle<Object> probe(table->Lookup(*source), isolate());
Steve Block6ded16b2010-05-10 14:33:55 +0100184 if (probe->IsSharedFunctionInfo()) {
185 Handle<SharedFunctionInfo> function_info =
186 Handle<SharedFunctionInfo>::cast(probe);
187 // Break when we've found a suitable shared function info that
Steve Blocka7e24c12009-10-30 11:49:00 +0000188 // matches the origin.
Steve Block6ded16b2010-05-10 14:33:55 +0100189 if (HasOrigin(function_info, name, line_offset, column_offset)) {
190 result = *function_info;
Steve Blocka7e24c12009-10-30 11:49:00 +0000191 break;
192 }
193 }
194 }
195 }
196
Steve Block44f0eee2011-05-26 01:26:41 +0100197 if (!script_histogram_initialized_) {
198 script_histogram_ = isolate()->stats_table()->CreateHistogram(
199 "V8.ScriptCache",
200 0,
201 kScriptGenerations,
202 kScriptGenerations + 1);
203 script_histogram_initialized_ = true;
204 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000205
Steve Block44f0eee2011-05-26 01:26:41 +0100206 if (script_histogram_ != NULL) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000207 // The level NUMBER_OF_SCRIPT_GENERATIONS is equivalent to a cache miss.
Steve Block44f0eee2011-05-26 01:26:41 +0100208 isolate()->stats_table()->AddHistogramSample(script_histogram_, generation);
Steve Blocka7e24c12009-10-30 11:49:00 +0000209 }
210
211 // Once outside the manacles of the handle scope, we need to recheck
212 // to see if we actually found a cached script. If so, we return a
213 // handle created in the caller's handle scope.
214 if (result != NULL) {
Steve Block44f0eee2011-05-26 01:26:41 +0100215 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result),
216 isolate());
Steve Block6ded16b2010-05-10 14:33:55 +0100217 ASSERT(HasOrigin(shared, name, line_offset, column_offset));
Steve Blocka7e24c12009-10-30 11:49:00 +0000218 // If the script was found in a later generation, we promote it to
219 // the first generation to let it survive longer in the cache.
Steve Block6ded16b2010-05-10 14:33:55 +0100220 if (generation != 0) Put(source, shared);
Steve Block44f0eee2011-05-26 01:26:41 +0100221 isolate()->counters()->compilation_cache_hits()->Increment();
Steve Block6ded16b2010-05-10 14:33:55 +0100222 return shared;
Steve Blocka7e24c12009-10-30 11:49:00 +0000223 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100224 isolate()->counters()->compilation_cache_misses()->Increment();
Steve Block6ded16b2010-05-10 14:33:55 +0100225 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000226 }
227}
228
229
John Reck59135872010-11-02 12:39:01 -0700230MaybeObject* CompilationCacheScript::TryTablePut(
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100231 Handle<String> source,
232 Handle<SharedFunctionInfo> function_info) {
233 Handle<CompilationCacheTable> table = GetFirstTable();
234 return table->Put(*source, *function_info);
235}
236
237
Steve Block6ded16b2010-05-10 14:33:55 +0100238Handle<CompilationCacheTable> CompilationCacheScript::TablePut(
239 Handle<String> source,
240 Handle<SharedFunctionInfo> function_info) {
Steve Block44f0eee2011-05-26 01:26:41 +0100241 CALL_HEAP_FUNCTION(isolate(),
242 TryTablePut(source, function_info),
243 CompilationCacheTable);
Steve Blocka7e24c12009-10-30 11:49:00 +0000244}
245
246
Steve Block6ded16b2010-05-10 14:33:55 +0100247void CompilationCacheScript::Put(Handle<String> source,
248 Handle<SharedFunctionInfo> function_info) {
Steve Block44f0eee2011-05-26 01:26:41 +0100249 HandleScope scope(isolate());
Steve Block6ded16b2010-05-10 14:33:55 +0100250 SetFirstTable(TablePut(source, function_info));
251}
252
253
254Handle<SharedFunctionInfo> CompilationCacheEval::Lookup(
Steve Block1e0659c2011-05-24 12:43:12 +0100255 Handle<String> source,
256 Handle<Context> context,
257 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000258 // Make sure not to leak the table into the surrounding handle
259 // scope. Otherwise, we risk keeping old tables around even after
260 // having cleared the cache.
261 Object* result = NULL;
262 int generation;
Steve Block44f0eee2011-05-26 01:26:41 +0100263 { HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000264 for (generation = 0; generation < generations(); generation++) {
265 Handle<CompilationCacheTable> table = GetTable(generation);
Steve Block1e0659c2011-05-24 12:43:12 +0100266 result = table->LookupEval(*source, *context, strict_mode);
Steve Block6ded16b2010-05-10 14:33:55 +0100267 if (result->IsSharedFunctionInfo()) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000268 break;
269 }
270 }
271 }
Steve Block6ded16b2010-05-10 14:33:55 +0100272 if (result->IsSharedFunctionInfo()) {
273 Handle<SharedFunctionInfo>
Steve Block44f0eee2011-05-26 01:26:41 +0100274 function_info(SharedFunctionInfo::cast(result), isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000275 if (generation != 0) {
Steve Block6ded16b2010-05-10 14:33:55 +0100276 Put(source, context, function_info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000277 }
Steve Block44f0eee2011-05-26 01:26:41 +0100278 isolate()->counters()->compilation_cache_hits()->Increment();
Steve Block6ded16b2010-05-10 14:33:55 +0100279 return function_info;
Steve Blocka7e24c12009-10-30 11:49:00 +0000280 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100281 isolate()->counters()->compilation_cache_misses()->Increment();
Steve Block6ded16b2010-05-10 14:33:55 +0100282 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000283 }
284}
285
286
John Reck59135872010-11-02 12:39:01 -0700287MaybeObject* CompilationCacheEval::TryTablePut(
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100288 Handle<String> source,
289 Handle<Context> context,
290 Handle<SharedFunctionInfo> function_info) {
291 Handle<CompilationCacheTable> table = GetFirstTable();
292 return table->PutEval(*source, *context, *function_info);
293}
294
295
Steve Block6ded16b2010-05-10 14:33:55 +0100296Handle<CompilationCacheTable> CompilationCacheEval::TablePut(
297 Handle<String> source,
298 Handle<Context> context,
299 Handle<SharedFunctionInfo> function_info) {
Steve Block44f0eee2011-05-26 01:26:41 +0100300 CALL_HEAP_FUNCTION(isolate(),
301 TryTablePut(source, context, function_info),
Steve Block6ded16b2010-05-10 14:33:55 +0100302 CompilationCacheTable);
303}
304
305
Steve Blocka7e24c12009-10-30 11:49:00 +0000306void CompilationCacheEval::Put(Handle<String> source,
307 Handle<Context> context,
Steve Block6ded16b2010-05-10 14:33:55 +0100308 Handle<SharedFunctionInfo> function_info) {
Steve Block44f0eee2011-05-26 01:26:41 +0100309 HandleScope scope(isolate());
Steve Block6ded16b2010-05-10 14:33:55 +0100310 SetFirstTable(TablePut(source, context, function_info));
Steve Blocka7e24c12009-10-30 11:49:00 +0000311}
312
313
314Handle<FixedArray> CompilationCacheRegExp::Lookup(Handle<String> source,
315 JSRegExp::Flags flags) {
316 // Make sure not to leak the table into the surrounding handle
317 // scope. Otherwise, we risk keeping old tables around even after
318 // having cleared the cache.
319 Object* result = NULL;
320 int generation;
Steve Block44f0eee2011-05-26 01:26:41 +0100321 { HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000322 for (generation = 0; generation < generations(); generation++) {
323 Handle<CompilationCacheTable> table = GetTable(generation);
324 result = table->LookupRegExp(*source, flags);
325 if (result->IsFixedArray()) {
326 break;
327 }
328 }
329 }
330 if (result->IsFixedArray()) {
Steve Block44f0eee2011-05-26 01:26:41 +0100331 Handle<FixedArray> data(FixedArray::cast(result), isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000332 if (generation != 0) {
333 Put(source, flags, data);
334 }
Steve Block44f0eee2011-05-26 01:26:41 +0100335 isolate()->counters()->compilation_cache_hits()->Increment();
Steve Blocka7e24c12009-10-30 11:49:00 +0000336 return data;
337 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100338 isolate()->counters()->compilation_cache_misses()->Increment();
Steve Blocka7e24c12009-10-30 11:49:00 +0000339 return Handle<FixedArray>::null();
340 }
341}
342
343
John Reck59135872010-11-02 12:39:01 -0700344MaybeObject* CompilationCacheRegExp::TryTablePut(
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100345 Handle<String> source,
346 JSRegExp::Flags flags,
347 Handle<FixedArray> data) {
348 Handle<CompilationCacheTable> table = GetFirstTable();
349 return table->PutRegExp(*source, flags, *data);
350}
351
352
Steve Block6ded16b2010-05-10 14:33:55 +0100353Handle<CompilationCacheTable> CompilationCacheRegExp::TablePut(
354 Handle<String> source,
355 JSRegExp::Flags flags,
356 Handle<FixedArray> data) {
Steve Block44f0eee2011-05-26 01:26:41 +0100357 CALL_HEAP_FUNCTION(isolate(),
358 TryTablePut(source, flags, data),
359 CompilationCacheTable);
Steve Block6ded16b2010-05-10 14:33:55 +0100360}
361
362
Steve Blocka7e24c12009-10-30 11:49:00 +0000363void CompilationCacheRegExp::Put(Handle<String> source,
364 JSRegExp::Flags flags,
365 Handle<FixedArray> data) {
Steve Block44f0eee2011-05-26 01:26:41 +0100366 HandleScope scope(isolate());
Steve Block6ded16b2010-05-10 14:33:55 +0100367 SetFirstTable(TablePut(source, flags, data));
Steve Blocka7e24c12009-10-30 11:49:00 +0000368}
369
370
Ben Murdochb0fe1622011-05-05 13:52:32 +0100371void CompilationCache::Remove(Handle<SharedFunctionInfo> function_info) {
372 if (!IsEnabled()) return;
373
Steve Block44f0eee2011-05-26 01:26:41 +0100374 eval_global_.Remove(function_info);
375 eval_contextual_.Remove(function_info);
376 script_.Remove(function_info);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100377}
378
379
Steve Block6ded16b2010-05-10 14:33:55 +0100380Handle<SharedFunctionInfo> CompilationCache::LookupScript(Handle<String> source,
381 Handle<Object> name,
382 int line_offset,
383 int column_offset) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000384 if (!IsEnabled()) {
Steve Block6ded16b2010-05-10 14:33:55 +0100385 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000386 }
387
Steve Block44f0eee2011-05-26 01:26:41 +0100388 return script_.Lookup(source, name, line_offset, column_offset);
Steve Blocka7e24c12009-10-30 11:49:00 +0000389}
390
391
Steve Block1e0659c2011-05-24 12:43:12 +0100392Handle<SharedFunctionInfo> CompilationCache::LookupEval(
393 Handle<String> source,
394 Handle<Context> context,
395 bool is_global,
396 StrictModeFlag strict_mode) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000397 if (!IsEnabled()) {
Steve Block6ded16b2010-05-10 14:33:55 +0100398 return Handle<SharedFunctionInfo>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +0000399 }
400
Steve Block6ded16b2010-05-10 14:33:55 +0100401 Handle<SharedFunctionInfo> result;
Steve Blocka7e24c12009-10-30 11:49:00 +0000402 if (is_global) {
Steve Block44f0eee2011-05-26 01:26:41 +0100403 result = eval_global_.Lookup(source, context, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000404 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100405 result = eval_contextual_.Lookup(source, context, strict_mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000406 }
407 return result;
408}
409
410
411Handle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source,
412 JSRegExp::Flags flags) {
413 if (!IsEnabled()) {
414 return Handle<FixedArray>::null();
415 }
416
Steve Block44f0eee2011-05-26 01:26:41 +0100417 return reg_exp_.Lookup(source, flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000418}
419
420
421void CompilationCache::PutScript(Handle<String> source,
Steve Block6ded16b2010-05-10 14:33:55 +0100422 Handle<SharedFunctionInfo> function_info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000423 if (!IsEnabled()) {
424 return;
425 }
426
Steve Block44f0eee2011-05-26 01:26:41 +0100427 script_.Put(source, function_info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000428}
429
430
431void CompilationCache::PutEval(Handle<String> source,
432 Handle<Context> context,
433 bool is_global,
Steve Block6ded16b2010-05-10 14:33:55 +0100434 Handle<SharedFunctionInfo> function_info) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000435 if (!IsEnabled()) {
436 return;
437 }
438
Steve Block44f0eee2011-05-26 01:26:41 +0100439 HandleScope scope(isolate());
Steve Blocka7e24c12009-10-30 11:49:00 +0000440 if (is_global) {
Steve Block44f0eee2011-05-26 01:26:41 +0100441 eval_global_.Put(source, context, function_info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000442 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100443 eval_contextual_.Put(source, context, function_info);
Steve Blocka7e24c12009-10-30 11:49:00 +0000444 }
445}
446
447
448
449void CompilationCache::PutRegExp(Handle<String> source,
450 JSRegExp::Flags flags,
451 Handle<FixedArray> data) {
452 if (!IsEnabled()) {
453 return;
454 }
455
Steve Block44f0eee2011-05-26 01:26:41 +0100456 reg_exp_.Put(source, flags, data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000457}
458
459
Ben Murdochb0fe1622011-05-05 13:52:32 +0100460static bool SourceHashCompare(void* key1, void* key2) {
461 return key1 == key2;
462}
463
464
Steve Block44f0eee2011-05-26 01:26:41 +0100465HashMap* CompilationCache::EagerOptimizingSet() {
466 if (eager_optimizing_set_ == NULL) {
467 eager_optimizing_set_ = new HashMap(&SourceHashCompare);
468 }
469 return eager_optimizing_set_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100470}
471
472
473bool CompilationCache::ShouldOptimizeEagerly(Handle<JSFunction> function) {
474 if (FLAG_opt_eagerly) return true;
475 uint32_t hash = function->SourceHash();
476 void* key = reinterpret_cast<void*>(hash);
477 return EagerOptimizingSet()->Lookup(key, hash, false) != NULL;
478}
479
480
481void CompilationCache::MarkForEagerOptimizing(Handle<JSFunction> function) {
482 uint32_t hash = function->SourceHash();
483 void* key = reinterpret_cast<void*>(hash);
484 EagerOptimizingSet()->Lookup(key, hash, true);
485}
486
487
488void CompilationCache::MarkForLazyOptimizing(Handle<JSFunction> function) {
489 uint32_t hash = function->SourceHash();
490 void* key = reinterpret_cast<void*>(hash);
491 EagerOptimizingSet()->Remove(key, hash);
492}
493
494
495void CompilationCache::ResetEagerOptimizingData() {
496 HashMap* set = EagerOptimizingSet();
497 if (set->occupancy() > 0) set->Clear();
498}
499
500
Steve Blocka7e24c12009-10-30 11:49:00 +0000501void CompilationCache::Clear() {
502 for (int i = 0; i < kSubCacheCount; i++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100503 subcaches_[i]->Clear();
Steve Blocka7e24c12009-10-30 11:49:00 +0000504 }
505}
506
Steve Block44f0eee2011-05-26 01:26:41 +0100507
Steve Blocka7e24c12009-10-30 11:49:00 +0000508void CompilationCache::Iterate(ObjectVisitor* v) {
509 for (int i = 0; i < kSubCacheCount; i++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100510 subcaches_[i]->Iterate(v);
Steve Blocka7e24c12009-10-30 11:49:00 +0000511 }
512}
513
514
Iain Merrick75681382010-08-19 15:07:18 +0100515void CompilationCache::IterateFunctions(ObjectVisitor* v) {
516 for (int i = 0; i < kSubCacheCount; i++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100517 subcaches_[i]->IterateFunctions(v);
Iain Merrick75681382010-08-19 15:07:18 +0100518 }
519}
520
521
Steve Blocka7e24c12009-10-30 11:49:00 +0000522void CompilationCache::MarkCompactPrologue() {
523 for (int i = 0; i < kSubCacheCount; i++) {
Steve Block44f0eee2011-05-26 01:26:41 +0100524 subcaches_[i]->Age();
Steve Blocka7e24c12009-10-30 11:49:00 +0000525 }
526}
527
528
529void CompilationCache::Enable() {
Steve Block44f0eee2011-05-26 01:26:41 +0100530 enabled_ = true;
Steve Blocka7e24c12009-10-30 11:49:00 +0000531}
532
533
534void CompilationCache::Disable() {
Steve Block44f0eee2011-05-26 01:26:41 +0100535 enabled_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000536 Clear();
537}
538
539
540} } // namespace v8::internal