Index script compilation cache over context, too,

in preparation for global lexical scope.

R=ulan@chromium.org
BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/10878007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12397 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
rossberg@chromium.org 2012-08-28 10:49:23 +00:00
parent 7cbca775ee
commit 1dbf670713
11 changed files with 86 additions and 32 deletions

View File

@ -1539,6 +1539,7 @@ Local<Script> Script::New(v8::Handle<String> source,
name_obj,
line_offset,
column_offset,
isolate->native_context(),
NULL,
pre_data_impl,
Utils::OpenHandle(*script_data),

View File

@ -1347,6 +1347,7 @@ bool Genesis::CompileScriptCached(Vector<const char> name,
script_name,
0,
0,
top_context,
extension,
NULL,
Handle<String>::null(),

View File

@ -165,10 +165,12 @@ bool CompilationCacheScript::HasOrigin(
// be cached in the same script generation. Currently the first use
// will be cached, but subsequent code from different source / line
// won't.
Handle<SharedFunctionInfo> CompilationCacheScript::Lookup(Handle<String> source,
Handle<Object> name,
int line_offset,
int column_offset) {
Handle<SharedFunctionInfo> CompilationCacheScript::Lookup(
Handle<String> source,
Handle<Object> name,
int line_offset,
int column_offset,
Handle<Context> context) {
Object* result = NULL;
int generation;
@ -177,7 +179,7 @@ Handle<SharedFunctionInfo> CompilationCacheScript::Lookup(Handle<String> source,
{ HandleScope scope(isolate());
for (generation = 0; generation < generations(); generation++) {
Handle<CompilationCacheTable> table = GetTable(generation);
Handle<Object> probe(table->Lookup(*source), isolate());
Handle<Object> probe(table->Lookup(*source, *context), isolate());
if (probe->IsSharedFunctionInfo()) {
Handle<SharedFunctionInfo> function_info =
Handle<SharedFunctionInfo>::cast(probe);
@ -214,7 +216,7 @@ Handle<SharedFunctionInfo> CompilationCacheScript::Lookup(Handle<String> source,
ASSERT(HasOrigin(shared, name, line_offset, column_offset));
// If the script was found in a later generation, we promote it to
// the first generation to let it survive longer in the cache.
if (generation != 0) Put(source, shared);
if (generation != 0) Put(source, context, shared);
isolate()->counters()->compilation_cache_hits()->Increment();
return shared;
} else {
@ -226,25 +228,28 @@ Handle<SharedFunctionInfo> CompilationCacheScript::Lookup(Handle<String> source,
MaybeObject* CompilationCacheScript::TryTablePut(
Handle<String> source,
Handle<Context> context,
Handle<SharedFunctionInfo> function_info) {
Handle<CompilationCacheTable> table = GetFirstTable();
return table->Put(*source, *function_info);
return table->Put(*source, *context, *function_info);
}
Handle<CompilationCacheTable> CompilationCacheScript::TablePut(
Handle<String> source,
Handle<Context> context,
Handle<SharedFunctionInfo> function_info) {
CALL_HEAP_FUNCTION(isolate(),
TryTablePut(source, function_info),
TryTablePut(source, context, function_info),
CompilationCacheTable);
}
void CompilationCacheScript::Put(Handle<String> source,
Handle<Context> context,
Handle<SharedFunctionInfo> function_info) {
HandleScope scope(isolate());
SetFirstTable(TablePut(source, function_info));
SetFirstTable(TablePut(source, context, function_info));
}
@ -380,15 +385,17 @@ void CompilationCache::Remove(Handle<SharedFunctionInfo> function_info) {
}
Handle<SharedFunctionInfo> CompilationCache::LookupScript(Handle<String> source,
Handle<Object> name,
int line_offset,
int column_offset) {
Handle<SharedFunctionInfo> CompilationCache::LookupScript(
Handle<String> source,
Handle<Object> name,
int line_offset,
int column_offset,
Handle<Context> context) {
if (!IsEnabled()) {
return Handle<SharedFunctionInfo>::null();
}
return script_.Lookup(source, name, line_offset, column_offset);
return script_.Lookup(source, name, line_offset, column_offset, context);
}
@ -426,12 +433,13 @@ Handle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source,
void CompilationCache::PutScript(Handle<String> source,
Handle<Context> context,
Handle<SharedFunctionInfo> function_info) {
if (!IsEnabled()) {
return;
}
script_.Put(source, function_info);
script_.Put(source, context, function_info);
}

View File

@ -98,16 +98,23 @@ class CompilationCacheScript : public CompilationSubCache {
Handle<SharedFunctionInfo> Lookup(Handle<String> source,
Handle<Object> name,
int line_offset,
int column_offset);
void Put(Handle<String> source, Handle<SharedFunctionInfo> function_info);
int column_offset,
Handle<Context> context);
void Put(Handle<String> source,
Handle<Context> context,
Handle<SharedFunctionInfo> function_info);
private:
MUST_USE_RESULT MaybeObject* TryTablePut(
Handle<String> source, Handle<SharedFunctionInfo> function_info);
Handle<String> source,
Handle<Context> context,
Handle<SharedFunctionInfo> function_info);
// Note: Returns a new hash table if operation results in expansion.
Handle<CompilationCacheTable> TablePut(
Handle<String> source, Handle<SharedFunctionInfo> function_info);
Handle<String> source,
Handle<Context> context,
Handle<SharedFunctionInfo> function_info);
bool HasOrigin(Handle<SharedFunctionInfo> function_info,
Handle<Object> name,
@ -204,7 +211,8 @@ class CompilationCache {
Handle<SharedFunctionInfo> LookupScript(Handle<String> source,
Handle<Object> name,
int line_offset,
int column_offset);
int column_offset,
Handle<Context> context);
// Finds the shared function info for a source string for eval in a
// given context. Returns an empty handle if the cache doesn't
@ -223,6 +231,7 @@ class CompilationCache {
// Associate the (source, kind) pair to the shared function
// info. This may overwrite an existing mapping.
void PutScript(Handle<String> source,
Handle<Context> context,
Handle<SharedFunctionInfo> function_info);
// Associate the (source, context->closure()->shared(), kind) triple

View File

@ -541,6 +541,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
Handle<Object> script_name,
int line_offset,
int column_offset,
Handle<Context> context,
v8::Extension* extension,
ScriptDataImpl* pre_data,
Handle<Object> script_data,
@ -561,7 +562,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
result = compilation_cache->LookupScript(source,
script_name,
line_offset,
column_offset);
column_offset,
context);
}
if (result.is_null()) {
@ -598,7 +600,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
}
result = MakeFunctionInfo(&info);
if (extension == NULL && !result.is_null() && !result->dont_cache()) {
compilation_cache->PutScript(source, result);
compilation_cache->PutScript(source, context, result);
}
} else {
if (result->ic_age() != HEAP->global_ic_age()) {

View File

@ -431,6 +431,7 @@ class Compiler : public AllStatic {
Handle<Object> script_name,
int line_offset,
int column_offset,
Handle<Context> context,
v8::Extension* extension,
ScriptDataImpl* pre_data,
Handle<Object> script_data,

View File

@ -745,12 +745,15 @@ bool Debug::CompileDebuggerScript(int index) {
isolate->bootstrapper()->NativesSourceLookup(index);
Vector<const char> name = Natives::GetScriptName(index);
Handle<String> script_name = factory->NewStringFromAscii(name);
Handle<Context> context = isolate->native_context();
// Compile the script.
Handle<SharedFunctionInfo> function_info;
function_info = Compiler::Compile(source_code,
script_name,
0, 0, NULL, NULL,
0, 0,
context,
NULL, NULL,
Handle<String>::null(),
NATIVES_CODE);
@ -762,7 +765,6 @@ bool Debug::CompileDebuggerScript(int index) {
}
// Execute the shared function in the debugger context.
Handle<Context> context = isolate->native_context();
bool caught_exception;
Handle<JSFunction> function =
factory->NewFunctionFromSharedFunctionInfo(function_info, context);

View File

@ -11944,8 +11944,23 @@ MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
}
Object* CompilationCacheTable::Lookup(String* src) {
StringKey key(src);
// The key for the script compilation cache is dependent on the mode flags,
// because they change the global language mode and thus binding behaviour.
// If flags change at some point, we must ensure that we do not hit the cache
// for code compiled with different settings.
static LanguageMode CurrentGlobalLanguageMode() {
return FLAG_use_strict
? (FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE)
: CLASSIC_MODE;
}
Object* CompilationCacheTable::Lookup(String* src, Context* context) {
SharedFunctionInfo* shared = context->closure()->shared();
StringSharedKey key(src,
shared,
CurrentGlobalLanguageMode(),
RelocInfo::kNoPosition);
int entry = FindEntry(&key);
if (entry == kNotFound) return GetHeap()->undefined_value();
return get(EntryToIndex(entry) + 1);
@ -11975,8 +11990,14 @@ Object* CompilationCacheTable::LookupRegExp(String* src,
}
MaybeObject* CompilationCacheTable::Put(String* src, Object* value) {
StringKey key(src);
MaybeObject* CompilationCacheTable::Put(String* src,
Context* context,
Object* value) {
SharedFunctionInfo* shared = context->closure()->shared();
StringSharedKey key(src,
shared,
CurrentGlobalLanguageMode(),
RelocInfo::kNoPosition);
Object* obj;
{ MaybeObject* maybe_obj = EnsureCapacity(1, &key);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
@ -11985,7 +12006,13 @@ MaybeObject* CompilationCacheTable::Put(String* src, Object* value) {
CompilationCacheTable* cache =
reinterpret_cast<CompilationCacheTable*>(obj);
int entry = cache->FindInsertionEntry(key.Hash());
cache->set(EntryToIndex(entry), src);
Object* k;
{ MaybeObject* maybe_k = key.AsObject();
if (!maybe_k->ToObject(&k)) return maybe_k;
}
cache->set(EntryToIndex(entry), k);
cache->set(EntryToIndex(entry) + 1, value);
cache->ElementAdded();
return cache;

View File

@ -6672,13 +6672,15 @@ class CompilationCacheTable: public HashTable<CompilationCacheShape,
HashTableKey*> {
public:
// Find cached value for a string key, otherwise return null.
Object* Lookup(String* src);
Object* Lookup(String* src, Context* context);
Object* LookupEval(String* src,
Context* context,
LanguageMode language_mode,
int scope_position);
Object* LookupRegExp(String* source, JSRegExp::Flags flags);
MUST_USE_RESULT MaybeObject* Put(String* src, Object* value);
MUST_USE_RESULT MaybeObject* Put(String* src,
Context* context,
Object* value);
MUST_USE_RESULT MaybeObject* PutEval(String* src,
Context* context,
SharedFunctionInfo* value,

View File

@ -120,6 +120,7 @@ static Handle<JSFunction> Compile(const char* source) {
Handle<String>(),
0,
0,
Handle<Context>(Isolate::Current()->native_context()),
NULL,
NULL,
Handle<String>::null(),

View File

@ -874,7 +874,7 @@ TEST(MultiScriptConflicts) {
context.Check("const x = 1; x",
EXPECT_RESULT, Number::New(1));
context.Check("var x = 2; x",
EXPECT_RESULT, Number::New(1));
EXPECT_EXCEPTION);
}
{ SimpleContext context;