'all': [
'accessors.cc', 'allocation.cc', 'api.cc', 'assembler.cc', 'ast.cc',
'bootstrapper.cc', 'builtins.cc', 'checks.cc', 'code-stubs.cc',
- 'codegen.cc', 'compiler.cc', 'contexts.cc', 'conversions.cc',
- 'counters.cc', 'dateparser.cc', 'debug.cc', 'disassembler.cc',
- 'execution.cc', 'factory.cc', 'flags.cc', 'frames.cc',
+ 'codegen.cc', 'compilation-cache.cc', 'compiler.cc', 'contexts.cc',
+ 'conversions.cc', 'counters.cc', 'dateparser.cc', 'debug.cc',
+ 'disassembler.cc', 'execution.cc', 'factory.cc', 'flags.cc', 'frames.cc',
'global-handles.cc', 'handles.cc', 'hashmap.cc', 'heap.cc', 'ic.cc',
'jsregexp.cc', 'log.cc', 'mark-compact.cc', 'messages.cc', 'objects.cc',
'parser.cc', 'property.cc', 'rewriter.cc', 'runtime.cc', 'scanner.cc',
source_objs = context.ConfigureObject(env, source_files)
non_snapshot_files = [jscre_obj, dtoa_obj, source_objs]
-
+
# Create snapshot if necessary.
empty_snapshot_obj = context.ConfigureObject(env, 'snapshot-empty.cc')
if context.use_snapshot:
--- /dev/null
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "compilation-cache.h"
+
+namespace v8 { namespace internal {
+
+enum {
+ NUMBER_OF_ENTRY_KINDS = CompilationCache::EVAL_CONTEXTUAL + 1
+};
+
+
+// Keep separate tables for the different entry kinds.
+static Object* tables[NUMBER_OF_ENTRY_KINDS] = { 0, };
+
+
+static Handle<CompilationCacheTable> AllocateTable(int size) {
+ CALL_HEAP_FUNCTION(CompilationCacheTable::Allocate(size),
+ CompilationCacheTable);
+}
+
+
+static Handle<CompilationCacheTable> GetTable(CompilationCache::Entry entry) {
+ Handle<CompilationCacheTable> result;
+ if (tables[entry]->IsUndefined()) {
+ static const int kInitialCacheSize = 64;
+ result = AllocateTable(kInitialCacheSize);
+ tables[entry] = *result;
+ } else {
+ CompilationCacheTable* table = CompilationCacheTable::cast(tables[entry]);
+ result = Handle<CompilationCacheTable>(table);
+ }
+ return result;
+}
+
+
+// We only re-use a cached function for some script source code if the
+// script originates from the same places. This is to avoid issues
+// when reporting errors, etc.
+static bool HasOrigin(Handle<JSFunction> boilerplate,
+ Handle<Object> name,
+ int line_offset,
+ int column_offset) {
+ Handle<Script> script =
+ Handle<Script>(Script::cast(boilerplate->shared()->script()));
+ // If the script name isn't set, the boilerplate script should have
+ // an undefined name to have the same origin.
+ if (name.is_null()) {
+ return script->name()->IsUndefined();
+ }
+ // Do the fast bailout checks first.
+ if (line_offset != script->line_offset()->value()) return false;
+ if (column_offset != script->column_offset()->value()) return false;
+ // Check that both names are strings. If not, no match.
+ if (!name->IsString() || !script->name()->IsString()) return false;
+ // Compare the two name strings for equality.
+ return String::cast(*name)->Equals(String::cast(script->name()));
+}
+
+
+static Handle<JSFunction> Lookup(Handle<String> source,
+ CompilationCache::Entry entry) {
+ Handle<CompilationCacheTable> table = GetTable(entry);
+ Object* result = table->Lookup(*source);
+ if (result->IsJSFunction()) {
+ return Handle<JSFunction>(JSFunction::cast(result));
+ } else {
+ return Handle<JSFunction>::null();
+ }
+}
+
+
+Handle<JSFunction> CompilationCache::LookupScript(Handle<String> source,
+ Handle<Object> name,
+ int line_offset,
+ int column_offset) {
+ Handle<JSFunction> result = Lookup(source, SCRIPT);
+ if (result.is_null()) {
+ Counters::compilation_cache_misses.Increment();
+ } else if (HasOrigin(result, name, line_offset, column_offset)) {
+ Counters::compilation_cache_hits.Increment();
+ } else {
+ result = Handle<JSFunction>::null();
+ Counters::compilation_cache_misses.Increment();
+ }
+ return result;
+}
+
+
+Handle<JSFunction> CompilationCache::LookupEval(Handle<String> source,
+ Entry entry) {
+ ASSERT(entry == EVAL_GLOBAL || entry == EVAL_CONTEXTUAL);
+ Handle<JSFunction> result = Lookup(source, entry);
+ if (result.is_null()) {
+ Counters::compilation_cache_misses.Increment();
+ } else {
+ Counters::compilation_cache_hits.Increment();
+ }
+ return result;
+}
+
+
+void CompilationCache::Associate(Handle<String> source,
+ Entry entry,
+ Handle<JSFunction> boilerplate) {
+ ASSERT(boilerplate->IsBoilerplate());
+ Handle<CompilationCacheTable> table = GetTable(entry);
+ CALL_HEAP_FUNCTION_VOID(table->Put(*source, *boilerplate));
+}
+
+
+void CompilationCache::Clear() {
+ for (int i = 0; i < NUMBER_OF_ENTRY_KINDS; i++) {
+ tables[i] = Heap::undefined_value();
+ }
+}
+
+
+void CompilationCache::Iterate(ObjectVisitor* v) {
+ v->VisitPointers(&tables[0], &tables[NUMBER_OF_ENTRY_KINDS]);
+}
+
+
+} } // namespace v8::internal
--- /dev/null
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_COMPILATION_CACHE_H_
+#define V8_COMPILATION_CACHE_H_
+
+namespace v8 { namespace internal {
+
+
+// The compilation cache keeps function boilerplates for compiled
+// scripts and evals. The boilerplates are looked up using the source
+// string as the key.
+class CompilationCache {
+ public:
+ // The same source code string has different compiled code for
+ // scripts and evals. Internally, we use separate caches to avoid
+ // getting the wrong kind of entry when looking up.
+ enum Entry {
+ SCRIPT,
+ EVAL_GLOBAL,
+ EVAL_CONTEXTUAL
+ };
+
+ // Finds the script function boilerplate for a source
+ // string. Returns an empty handle if the cache doesn't contain a
+ // script for the given source string with the right origin.
+ static Handle<JSFunction> LookupScript(Handle<String> source,
+ Handle<Object> name,
+ int line_offset,
+ int column_offset);
+
+ // Finds the function boilerplate for a source string for
+ // eval. Returns an empty handle if the cache doesn't contain a
+ // script for the given source string.
+ static Handle<JSFunction> LookupEval(Handle<String> source,
+ Entry entry);
+
+ // Associate the (source, kind) pair to the boilerplate. This may
+ // overwrite an existing mapping.
+ static void Associate(Handle<String> source,
+ Entry entry,
+ Handle<JSFunction> boilerplate);
+
+ // Clear the cache - also used to initialize the cache at startup.
+ static void Clear();
+
+ // GC support.
+ static void Iterate(ObjectVisitor* v);
+
+ // Notify the cache that a mark-sweep garbage collection is about to
+ // take place. This is used to retire entries from the cache to
+ // avoid keeping them alive too long without using them. For now, we
+ // just clear the cache but we should consider are more
+ // sophisticated LRU scheme.
+ static void MarkCompactPrologue() { Clear(); }
+};
+
+
+} } // namespace v8::internal
+
+#endif // V8_COMPILATION_CACHE_H_
#include "bootstrapper.h"
#include "codegen-inl.h"
+#include "compilation-cache.h"
#include "compiler.h"
#include "debug.h"
#include "scopes.h"
// The VM is in the COMPILER state until exiting this function.
VMState state(COMPILER);
- ScriptDataImpl* pre_data = input_pre_data;
- if (pre_data == NULL && source->length() >= FLAG_min_preparse_length) {
- Access<SafeStringInputBuffer> buf(&safe_string_input_buffer);
- buf->Reset(source.location());
- pre_data = PreParse(buf.value(), extension);
+ // Do a lookup in the compilation cache but not for extensions.
+ Handle<JSFunction> result;
+ if (extension == NULL) {
+ result = CompilationCache::LookupScript(source,
+ script_name,
+ line_offset,
+ column_offset);
}
- // Create a script object describing the script to be compiled.
- Handle<Script> script = Factory::NewScript(source);
- if (!script_name.is_null()) {
- script->set_name(*script_name);
- script->set_line_offset(Smi::FromInt(line_offset));
- script->set_column_offset(Smi::FromInt(column_offset));
+ if (result.is_null()) {
+ // No cache entry found. Do pre-parsing and compile the script.
+ ScriptDataImpl* pre_data = input_pre_data;
+ if (pre_data == NULL && source->length() >= FLAG_min_preparse_length) {
+ Access<SafeStringInputBuffer> buf(&safe_string_input_buffer);
+ buf->Reset(source.location());
+ pre_data = PreParse(buf.value(), extension);
+ }
+
+ // Create a script object describing the script to be compiled.
+ Handle<Script> script = Factory::NewScript(source);
+ if (!script_name.is_null()) {
+ script->set_name(*script_name);
+ script->set_line_offset(Smi::FromInt(line_offset));
+ script->set_column_offset(Smi::FromInt(column_offset));
+ }
+
+ // Compile the function and add it to the cache.
+ result = MakeFunction(true, false, script, extension, pre_data);
+ if (extension == NULL && !result.is_null()) {
+ CompilationCache::Associate(source, CompilationCache::SCRIPT, result);
+ }
+
+ // Get rid of the pre-parsing data (if necessary).
+ if (input_pre_data == NULL && pre_data != NULL) {
+ delete pre_data;
+ }
}
- Handle<JSFunction> result =
- MakeFunction(true, false, script, extension, pre_data);
-
- if (input_pre_data == NULL && pre_data != NULL)
- delete pre_data;
-
return result;
}
// The VM is in the COMPILER state until exiting this function.
VMState state(COMPILER);
-
- // Create a script object describing the script to be compiled.
- Handle<Script> script = Factory::NewScript(source);
- return MakeFunction(is_global, true, script, NULL, NULL);
+ CompilationCache::Entry entry = is_global
+ ? CompilationCache::EVAL_GLOBAL
+ : CompilationCache::EVAL_CONTEXTUAL;
+
+ // Do a lookup in the compilation cache; if the entry is not there,
+ // invoke the compiler and add the result to the cache.
+ Handle<JSFunction> result = CompilationCache::LookupEval(source, entry);
+ if (result.is_null()) {
+ // Create a script object describing the script to be compiled.
+ Handle<Script> script = Factory::NewScript(source);
+ result = MakeFunction(is_global, true, script, NULL, NULL);
+ if (!result.is_null()) {
+ CompilationCache::Associate(source, entry, result);
+ }
+ }
+ return result;
}
}
-// Don't use the following names: __object__, __failure__.
-#define CALL_HEAP_FUNCTION_VOID(FUNCTION_CALL) \
- GC_GREEDY_CHECK(); \
- Object* __object__ = FUNCTION_CALL; \
- if (__object__->IsFailure()) { \
- if (__object__->IsRetryAfterGC()) { \
- Failure* __failure__ = Failure::cast(__object__); \
- if (!Heap::CollectGarbage(__failure__->requested(), \
- __failure__->allocation_space())) { \
- /* TODO(1181417): Fix this. */ \
- V8::FatalProcessOutOfMemory("Handles"); \
- } \
- __object__ = FUNCTION_CALL; \
- if (__object__->IsFailure()) { \
- if (__object__->IsRetryAfterGC()) { \
- /* TODO(1181417): Fix this. */ \
- V8::FatalProcessOutOfMemory("Handles"); \
- } \
- return; \
- } \
- } else { \
- return; \
- } \
- }
-
-
-
-
Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray> content,
Handle<JSArray> array) {
CALL_HEAP_FUNCTION(content->AddKeysFromJSArray(*array), FixedArray);
} while (false)
+// Don't use the following names: __object__, __failure__.
+#define CALL_HEAP_FUNCTION_VOID(FUNCTION_CALL) \
+ GC_GREEDY_CHECK(); \
+ Object* __object__ = FUNCTION_CALL; \
+ if (__object__->IsFailure()) { \
+ if (__object__->IsRetryAfterGC()) { \
+ Failure* __failure__ = Failure::cast(__object__); \
+ if (!Heap::CollectGarbage(__failure__->requested(), \
+ __failure__->allocation_space())) { \
+ /* TODO(1181417): Fix this. */ \
+ V8::FatalProcessOutOfMemory("Handles"); \
+ } \
+ __object__ = FUNCTION_CALL; \
+ if (__object__->IsFailure()) { \
+ if (__object__->IsRetryAfterGC()) { \
+ /* TODO(1181417): Fix this. */ \
+ V8::FatalProcessOutOfMemory("Handles"); \
+ } \
+ return; \
+ } \
+ } else { \
+ return; \
+ } \
+ }
+
+
#ifdef DEBUG
inline bool Heap::allow_allocation(bool new_state) {
#include "api.h"
#include "bootstrapper.h"
#include "codegen-inl.h"
+#include "compilation-cache.h"
#include "debug.h"
#include "global-handles.h"
#include "jsregexp.h"
void Heap::MarkCompactPrologue() {
- // Empty eval caches
- Heap::eval_cache_global_ = Heap::null_value();
- Heap::eval_cache_non_global_ = Heap::null_value();
-
+ CompilationCache::MarkCompactPrologue();
RegExpImpl::OldSpaceCollectionPrologue();
Top::MarkCompactPrologue();
ThreadManager::MarkCompactPrologue();
if (obj->IsFailure()) return false;
natives_source_cache_ = FixedArray::cast(obj);
- // Initialized eval cache to null value.
- eval_cache_global_ = null_value();
- eval_cache_non_global_ = null_value();
+ // Initialize compilation cache.
+ CompilationCache::Clear();
return true;
}
}
-Object* Heap::LookupEvalCache(bool is_global_context, String* src) {
- Object* cache = is_global_context ?
- eval_cache_global_ : eval_cache_non_global_;
- return cache == null_value() ?
- null_value() : EvalCache::cast(cache)->Lookup(src);
-}
-
-
-Object* Heap::PutInEvalCache(bool is_global_context, String* src,
- JSFunction* value) {
- Object** cache_ptr = is_global_context ?
- &eval_cache_global_ : &eval_cache_non_global_;
-
- if (*cache_ptr == null_value()) {
- Object* obj = EvalCache::Allocate(kInitialEvalCacheSize);
- if (obj->IsFailure()) return false;
- *cache_ptr = obj;
- }
-
- Object* new_cache =
- EvalCache::cast(*cache_ptr)->Put(src, value);
- if (new_cache->IsFailure()) return new_cache;
- *cache_ptr = new_cache;
-
- return value;
-}
-
-
#ifdef DEBUG
void Heap::ZapFromSpace() {
ASSERT(HAS_HEAP_OBJECT_TAG(kFromSpaceZapValue));
SYNCHRONIZE_TAG("top");
Debug::Iterate(v);
SYNCHRONIZE_TAG("debug");
+ CompilationCache::Iterate(v);
+ SYNCHRONIZE_TAG("compilationcache");
// Iterate over local handles in handle scopes.
HandleScopeImplementer::Iterate(v);
V(Code, c_entry_debug_break_code) \
V(FixedArray, number_string_cache) \
V(FixedArray, single_character_string_cache) \
- V(FixedArray, natives_source_cache) \
- V(Object, eval_cache_global) \
- V(Object, eval_cache_non_global)
+ V(FixedArray, natives_source_cache)
+
#define ROOT_LIST(V) \
STRONG_ROOT_LIST(V) \
}
static Object* LookupSymbol(String* str);
- // EvalCache caches function boilerplates for compiled scripts
- // from 'eval' function.
- // Source string is used as the key, and compiled function
- // boilerplate as value. Because the same source has different
- // compiled code in global or local context, we use separate
- // caches for global and local contexts.
- // Caches are cleared before mark-compact/mark-sweep GC's.
-
- // Finds the function boilerplate of a source string.
- // It returns a JSFunction object if found in the cache.
- // The first parameter specifies whether the code is
- // compiled in a global context.
- static Object* LookupEvalCache(bool is_global_context, String* src);
-
- // Put a source string and its compiled function boilerplate
- // in the eval cache. The cache may expand, and returns failure
- // if it cannot expand the cache, otherwise the value is returned.
- // The first parameter specifies whether the boilerplate is
- // compiled in a global context.
- static Object* PutInEvalCache(bool is_global_context,
- String* src, JSFunction* value);
-
// Compute the matching symbol map for a string if possible.
// NULL is returned if string is in new space or not flattened.
static Map* SymbolMapForString(String* str);
}
-bool Object::IsEvalCache() {
- return IsHashTable() &&
- (this == Heap::eval_cache_global() ||
- this == Heap::eval_cache_non_global());
+bool Object::IsCompilationCacheTable() {
+ return IsHashTable();
}
CAST_ACCESSOR(DescriptorArray)
CAST_ACCESSOR(Dictionary)
CAST_ACCESSOR(SymbolTable)
-CAST_ACCESSOR(EvalCache)
+CAST_ACCESSOR(CompilationCacheTable)
CAST_ACCESSOR(String)
CAST_ACCESSOR(SeqString)
CAST_ACCESSOR(AsciiString)
}
-Object* EvalCache::Lookup(String* src) {
+Object* CompilationCacheTable::Lookup(String* src) {
StringKey key(src);
int entry = FindEntry(&key);
if (entry != -1) {
}
-Object* EvalCache::Put(String* src, Object* value) {
+Object* CompilationCacheTable::Put(String* src, Object* value) {
StringKey key(src);
Object* obj = EnsureCapacity(1, &key);
if (obj->IsFailure()) return obj;
- EvalCache* cache = reinterpret_cast<EvalCache*>(obj);
+ CompilationCacheTable* cache =
+ reinterpret_cast<CompilationCacheTable*>(obj);
int entry = cache->FindInsertionEntry(src, key.Hash());
cache->set(EntryToIndex(entry), src);
cache->set(EntryToIndex(entry) + 1, value);
inline bool IsHashTable();
inline bool IsDictionary();
inline bool IsSymbolTable();
- inline bool IsEvalCache();
+ inline bool IsCompilationCacheTable();
inline bool IsPrimitive();
inline bool IsGlobalObject();
inline bool IsJSGlobalObject();
};
-// EvalCache for caching eval'ed string and function.
-//
-// The cache is cleaned up during a mark-compact GC.
-class EvalCache: public HashTable<0, 2> {
+class CompilationCacheTable: public HashTable<0, 2> {
public:
// Find cached value for a string key, otherwise return null.
Object* Lookup(String* src);
Object* Put(String* src, Object* value);
- static inline EvalCache* cast(Object* obj);
+ static inline CompilationCacheTable* cast(Object* obj);
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(EvalCache);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable);
};
static Object* Runtime_CompileString(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 2);
+ CONVERT_ARG_CHECKED(String, source, 0);
bool contextual = args[1]->IsTrue();
RUNTIME_ASSERT(contextual || args[1]->IsFalse());
context = Handle<Context>(Top::context()->global_context());
}
- // Compile eval() source.
- bool is_global_context = context->IsGlobalContext();
- Handle<String> source(String::cast(args[0]));
- Object* obj = Heap::LookupEvalCache(is_global_context, *source);
- if (obj->IsFailure()) return obj;
-
- Handle<JSFunction> boilerplate;
- if (!obj->IsJSFunction()) {
- Counters::eval_cache_misses.Increment();
- boilerplate = Compiler::CompileEval(is_global_context, source);
- if (boilerplate.is_null()) return Failure::Exception();
-
- Object* obj =
- Heap::PutInEvalCache(is_global_context, *source, *boilerplate);
- if (obj->IsFailure()) return obj;
-
- } else {
- Counters::eval_cache_hits.Increment();
- boilerplate = Handle<JSFunction>(JSFunction::cast(obj));
- }
+ // Compile source string.
+ bool is_global = context->IsGlobalContext();
+ Handle<JSFunction> boilerplate =
+ Compiler::CompileEval(is_global, source);
+ if (boilerplate.is_null()) return Failure::Exception();
Handle<JSFunction> fun =
Factory::NewFunctionFromBoilerplate(boilerplate, context);
return *fun;
SC(call_normal_stubs, V8.CallNormalStubs) \
SC(call_megamorphic_stubs, V8.CallMegamorphicStubs) \
SC(arguments_adaptors, V8.ArgumentsAdaptors) \
- SC(eval_cache_hits, V8.EvalCacheHits) \
- SC(eval_cache_misses, V8.EvalCacheMisses) \
+ SC(compilation_cache_hits, V8.CompilationCacheHits) \
+ SC(compilation_cache_misses, V8.CompilationCacheMisses) \
/* Amount of evaled source code. */ \
SC(total_eval_size, V8.TotalEvalSize) \
/* Amount of loaded source code. */ \
"\n"
"Foo();\n");
v8::Handle<v8::Script> script =
- v8::Script::Compile(source, v8::String::New("test.js"));
+ v8::Script::Compile(source, v8::String::New("test.js"));
v8::TryCatch try_catch;
v8::Handle<v8::Value> result = script->Run();
CHECK(result.IsEmpty());
v8::String::AsciiValue name(message->GetScriptResourceName());
CHECK_EQ("test.js", *name);
}
+
+
+THREADED_TEST(CompilationCache) {
+ v8::HandleScope scope;
+ LocalContext context;
+ v8::Handle<v8::String> source0 = v8::String::New("1234");
+ v8::Handle<v8::String> source1 = v8::String::New("1234");
+ v8::Handle<v8::Script> script0 =
+ v8::Script::Compile(source0, v8::String::New("test.js"));
+ v8::Handle<v8::Script> script1 =
+ v8::Script::Compile(source1, v8::String::New("test.js"));
+ v8::Handle<v8::Script> script2 =
+ v8::Script::Compile(source0); // different origin
+ CHECK_EQ(1234, script0->Run()->Int32Value());
+ CHECK_EQ(1234, script1->Run()->Int32Value());
+ CHECK_EQ(1234, script2->Run()->Int32Value());
+}
>
</File>
<File
+ RelativePath="..\..\src\compilation-cache.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\compilation-cache.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\compiler.cc"
>
</File>