Revision: 9984
Author: [email protected]
Date: Mon Nov 14 00:58:47 2011
Log: Make eval compilation cache calling scope sensitive.
Review URL: http://codereview.chromium.org/8518001
http://code.google.com/p/v8/source/detail?r=9984
Modified:
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/compilation-cache.cc
/branches/bleeding_edge/src/compilation-cache.h
/branches/bleeding_edge/src/compiler.cc
/branches/bleeding_edge/src/compiler.h
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/mips/full-codegen-mips.cc
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/runtime.h
/branches/bleeding_edge/src/x64/full-codegen-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Fri Nov 11 06:49:16
2011
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Mon Nov 14 00:58:47
2011
@@ -2204,7 +2204,11 @@
__ mov(r1, Operand(Smi::FromInt(strict_mode)));
__ push(r1);
- __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
+ // Push the start position of the scope the calls resides in.
+ __ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
+ __ push(r1);
+
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
}
=======================================
--- /branches/bleeding_edge/src/compilation-cache.cc Wed Jun 29 07:56:08
2011
+++ /branches/bleeding_edge/src/compilation-cache.cc Mon Nov 14 00:58:47
2011
@@ -1,4 +1,4 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
+// Copyright 2011 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:
@@ -27,6 +27,7 @@
#include "v8.h"
+#include "assembler.h"
#include "compilation-cache.h"
#include "serialize.h"
@@ -250,7 +251,8 @@
Handle<SharedFunctionInfo> CompilationCacheEval::Lookup(
Handle<String> source,
Handle<Context> context,
- StrictModeFlag strict_mode) {
+ StrictModeFlag strict_mode,
+ int scope_position) {
// Make sure not to leak the table into the surrounding handle
// scope. Otherwise, we risk keeping old tables around even after
// having cleared the cache.
@@ -259,7 +261,8 @@
{ HandleScope scope(isolate());
for (generation = 0; generation < generations(); generation++) {
Handle<CompilationCacheTable> table = GetTable(generation);
- result = table->LookupEval(*source, *context, strict_mode);
+ result = table->LookupEval(
+ *source, *context, strict_mode, scope_position);
if (result->IsSharedFunctionInfo()) {
break;
}
@@ -269,7 +272,7 @@
Handle<SharedFunctionInfo>
function_info(SharedFunctionInfo::cast(result), isolate());
if (generation != 0) {
- Put(source, context, function_info);
+ Put(source, context, function_info, scope_position);
}
isolate()->counters()->compilation_cache_hits()->Increment();
return function_info;
@@ -283,27 +286,31 @@
MaybeObject* CompilationCacheEval::TryTablePut(
Handle<String> source,
Handle<Context> context,
- Handle<SharedFunctionInfo> function_info) {
+ Handle<SharedFunctionInfo> function_info,
+ int scope_position) {
Handle<CompilationCacheTable> table = GetFirstTable();
- return table->PutEval(*source, *context, *function_info);
+ return table->PutEval(*source, *context, *function_info, scope_position);
}
Handle<CompilationCacheTable> CompilationCacheEval::TablePut(
Handle<String> source,
Handle<Context> context,
- Handle<SharedFunctionInfo> function_info) {
+ Handle<SharedFunctionInfo> function_info,
+ int scope_position) {
CALL_HEAP_FUNCTION(isolate(),
- TryTablePut(source, context, function_info),
+ TryTablePut(
+ source, context, function_info, scope_position),
CompilationCacheTable);
}
void CompilationCacheEval::Put(Handle<String> source,
Handle<Context> context,
- Handle<SharedFunctionInfo> function_info) {
+ Handle<SharedFunctionInfo> function_info,
+ int scope_position) {
HandleScope scope(isolate());
- SetFirstTable(TablePut(source, context, function_info));
+ SetFirstTable(TablePut(source, context, function_info, scope_position));
}
@@ -389,16 +396,19 @@
Handle<String> source,
Handle<Context> context,
bool is_global,
- StrictModeFlag strict_mode) {
+ StrictModeFlag strict_mode,
+ int scope_position) {
if (!IsEnabled()) {
return Handle<SharedFunctionInfo>::null();
}
Handle<SharedFunctionInfo> result;
if (is_global) {
- result = eval_global_.Lookup(source, context, strict_mode);
+ result = eval_global_.Lookup(source, context, strict_mode,
scope_position);
} else {
- result = eval_contextual_.Lookup(source, context, strict_mode);
+ ASSERT(scope_position != RelocInfo::kNoPosition);
+ result = eval_contextual_.Lookup(
+ source, context, strict_mode, scope_position);
}
return result;
}
@@ -427,16 +437,18 @@
void CompilationCache::PutEval(Handle<String> source,
Handle<Context> context,
bool is_global,
- Handle<SharedFunctionInfo> function_info) {
+ Handle<SharedFunctionInfo> function_info,
+ int scope_position) {
if (!IsEnabled()) {
return;
}
HandleScope scope(isolate());
if (is_global) {
- eval_global_.Put(source, context, function_info);
+ eval_global_.Put(source, context, function_info, scope_position);
} else {
- eval_contextual_.Put(source, context, function_info);
+ ASSERT(scope_position != RelocInfo::kNoPosition);
+ eval_contextual_.Put(source, context, function_info, scope_position);
}
}
=======================================
--- /branches/bleeding_edge/src/compilation-cache.h Thu Sep 8 12:57:14 2011
+++ /branches/bleeding_edge/src/compilation-cache.h Mon Nov 14 00:58:47 2011
@@ -1,4 +1,4 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
+// Copyright 2011 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:
@@ -123,7 +123,19 @@
};
-// Sub-cache for eval scripts.
+// Sub-cache for eval scripts. Two caches for eval are used. One for eval
calls
+// in global contexts and one for eval calls in other contexts. The cache
+// considers the following pieces of information when checking for matching
+// entries:
+// 1. The source string.
+// 2. The shared function info of the calling function.
+// 3. Whether the source should be compiled as strict code or as non-strict
+// code.
+// Note: Currently there are clients of CompileEval that always compile
+// non-strict code even if the calling function is a strict mode
function.
+// More specifically these are the CompileString, DebugEvaluate and
+// DebugEvaluateGlobal runtime functions.
+// 4. The start position of the calling scope.
class CompilationCacheEval: public CompilationSubCache {
public:
CompilationCacheEval(Isolate* isolate, int generations)
@@ -131,23 +143,27 @@
Handle<SharedFunctionInfo> Lookup(Handle<String> source,
Handle<Context> context,
- StrictModeFlag strict_mode);
+ StrictModeFlag strict_mode,
+ int scope_position);
void Put(Handle<String> source,
Handle<Context> context,
- Handle<SharedFunctionInfo> function_info);
+ Handle<SharedFunctionInfo> function_info,
+ int scope_position);
private:
MUST_USE_RESULT MaybeObject* TryTablePut(
Handle<String> source,
Handle<Context> context,
- Handle<SharedFunctionInfo> function_info);
+ Handle<SharedFunctionInfo> function_info,
+ int scope_position);
// Note: Returns a new hash table if operation results in expansion.
Handle<CompilationCacheTable> TablePut(
Handle<String> source,
Handle<Context> context,
- Handle<SharedFunctionInfo> function_info);
+ Handle<SharedFunctionInfo> function_info,
+ int scope_position);
DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheEval);
};
@@ -198,7 +214,8 @@
Handle<SharedFunctionInfo> LookupEval(Handle<String> source,
Handle<Context> context,
bool is_global,
- StrictModeFlag strict_mode);
+ StrictModeFlag strict_mode,
+ int scope_position);
// Returns the regexp data associated with the given regexp if it
// is in cache, otherwise an empty handle.
@@ -215,7 +232,8 @@
void PutEval(Handle<String> source,
Handle<Context> context,
bool is_global,
- Handle<SharedFunctionInfo> function_info);
+ Handle<SharedFunctionInfo> function_info,
+ int scope_position);
// Associate the (source, flags) pair to the given regexp data.
// This may overwrite an existing mapping.
=======================================
--- /branches/bleeding_edge/src/compiler.cc Wed Nov 9 05:54:26 2011
+++ /branches/bleeding_edge/src/compiler.cc Mon Nov 14 00:58:47 2011
@@ -533,7 +533,8 @@
Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
Handle<Context> context,
bool is_global,
- StrictModeFlag
strict_mode) {
+ StrictModeFlag
strict_mode,
+ int scope_position) {
Isolate* isolate = source->GetIsolate();
int source_length = source->length();
isolate->counters()->total_eval_size()->Increment(source_length);
@@ -549,7 +550,8 @@
result = compilation_cache->LookupEval(source,
context,
is_global,
- strict_mode);
+ strict_mode,
+ scope_position);
if (result.is_null()) {
// Create a script object describing the script to be compiled.
@@ -561,13 +563,13 @@
info.SetCallingContext(context);
result = MakeFunctionInfo(&info);
if (!result.is_null()) {
- CompilationCache* compilation_cache = isolate->compilation_cache();
// If caller is strict mode, the result must be strict as well,
// but not the other way around. Consider:
// eval("'use strict'; ...");
// TODO(keuchel): adapt this for extended mode.
ASSERT(strict_mode == kNonStrictMode || result->strict_mode());
- compilation_cache->PutEval(source, context, is_global, result);
+ compilation_cache->PutEval(
+ source, context, is_global, result, scope_position);
}
}
=======================================
--- /branches/bleeding_edge/src/compiler.h Mon Oct 24 00:47:22 2011
+++ /branches/bleeding_edge/src/compiler.h Mon Nov 14 00:58:47 2011
@@ -289,7 +289,8 @@
static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
Handle<Context> context,
bool is_global,
- StrictModeFlag
strict_mode);
+ StrictModeFlag strict_mode,
+ int scope_position);
// Compile from function info (used for lazy compilation). Returns true
on
// success and false if the compilation resulted in a stack overflow.
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Fri Nov 11
05:48:14 2011
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Mon Nov 14
00:58:47 2011
@@ -2152,7 +2152,10 @@
FLAG_harmony_scoping ? kStrictMode : strict_mode_flag();
__ push(Immediate(Smi::FromInt(strict_mode)));
- __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
+ // Push the start position of the scope the calls resides in.
+ __ push(Immediate(Smi::FromInt(scope()->start_position())));
+
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
}
=======================================
--- /branches/bleeding_edge/src/mips/full-codegen-mips.cc Thu Nov 10
00:07:39 2011
+++ /branches/bleeding_edge/src/mips/full-codegen-mips.cc Mon Nov 14
00:58:47 2011
@@ -2271,7 +2271,11 @@
__ li(a1, Operand(Smi::FromInt(strict_mode)));
__ push(a1);
- __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
+ // Push the start position of the scope the calls resides in.
+ __ li(a1, Operand(Smi::FromInt(scope()->start_position())));
+ __ push(a1);
+
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
}
=======================================
--- /branches/bleeding_edge/src/objects.cc Fri Nov 11 06:49:16 2011
+++ /branches/bleeding_edge/src/objects.cc Mon Nov 14 00:58:47 2011
@@ -10298,74 +10298,83 @@
public:
StringSharedKey(String* source,
SharedFunctionInfo* shared,
- StrictModeFlag strict_mode)
+ StrictModeFlag strict_mode,
+ int scope_position)
: source_(source),
shared_(shared),
- strict_mode_(strict_mode) { }
+ strict_mode_(strict_mode),
+ scope_position_(scope_position) { }
bool IsMatch(Object* other) {
if (!other->IsFixedArray()) return false;
- FixedArray* pair = FixedArray::cast(other);
- SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
+ FixedArray* other_array = FixedArray::cast(other);
+ SharedFunctionInfo* shared =
SharedFunctionInfo::cast(other_array->get(0));
if (shared != shared_) return false;
- int strict_unchecked = Smi::cast(pair->get(2))->value();
+ int strict_unchecked = Smi::cast(other_array->get(2))->value();
ASSERT(strict_unchecked == kStrictMode ||
strict_unchecked == kNonStrictMode);
StrictModeFlag strict_mode =
static_cast<StrictModeFlag>(strict_unchecked);
if (strict_mode != strict_mode_) return false;
- String* source = String::cast(pair->get(1));
+ int scope_position = Smi::cast(other_array->get(3))->value();
+ if (scope_position != scope_position_) return false;
+ String* source = String::cast(other_array->get(1));
return source->Equals(source_);
}
static uint32_t StringSharedHashHelper(String* source,
SharedFunctionInfo* shared,
- StrictModeFlag strict_mode) {
+ StrictModeFlag strict_mode,
+ int scope_position) {
uint32_t hash = source->Hash();
if (shared->HasSourceCode()) {
// Instead of using the SharedFunctionInfo pointer in the hash
// code computation, we use a combination of the hash of the
- // script source code and the start and end positions. We do
- // this to ensure that the cache entries can survive garbage
+ // script source code and the start position of the calling scope.
+ // We do this to ensure that the cache entries can survive garbage
// collection.
Script* script = Script::cast(shared->script());
hash ^= String::cast(script->source())->Hash();
if (strict_mode == kStrictMode) hash ^= 0x8000;
- hash += shared->start_position();
+ hash += scope_position;
}
return hash;
}
uint32_t Hash() {
- return StringSharedHashHelper(source_, shared_, strict_mode_);
+ return StringSharedHashHelper(
+ source_, shared_, strict_mode_, scope_position_);
}
uint32_t HashForObject(Object* obj) {
- FixedArray* pair = FixedArray::cast(obj);
- SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
- String* source = String::cast(pair->get(1));
- int strict_unchecked = Smi::cast(pair->get(2))->value();
+ FixedArray* other_array = FixedArray::cast(obj);
+ SharedFunctionInfo* shared =
SharedFunctionInfo::cast(other_array->get(0));
+ String* source = String::cast(other_array->get(1));
+ int strict_unchecked = Smi::cast(other_array->get(2))->value();
ASSERT(strict_unchecked == kStrictMode ||
strict_unchecked == kNonStrictMode);
StrictModeFlag strict_mode =
static_cast<StrictModeFlag>(strict_unchecked);
- return StringSharedHashHelper(source, shared, strict_mode);
+ int scope_position = Smi::cast(other_array->get(3))->value();
+ return StringSharedHashHelper(source, shared, strict_mode,
scope_position);
}
MUST_USE_RESULT MaybeObject* AsObject() {
Object* obj;
- { MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(3);
+ { MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(4);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
- FixedArray* pair = FixedArray::cast(obj);
- pair->set(0, shared_);
- pair->set(1, source_);
- pair->set(2, Smi::FromInt(strict_mode_));
- return pair;
+ FixedArray* other_array = FixedArray::cast(obj);
+ other_array->set(0, shared_);
+ other_array->set(1, source_);
+ other_array->set(2, Smi::FromInt(strict_mode_));
+ other_array->set(3, Smi::FromInt(scope_position_));
+ return other_array;
}
private:
String* source_;
SharedFunctionInfo* shared_;
StrictModeFlag strict_mode_;
+ int scope_position_;
};
@@ -11520,8 +11529,12 @@
Object* CompilationCacheTable::LookupEval(String* src,
Context* context,
- StrictModeFlag strict_mode) {
- StringSharedKey key(src, context->closure()->shared(), strict_mode);
+ StrictModeFlag strict_mode,
+ int scope_position) {
+ StringSharedKey key(src,
+ context->closure()->shared(),
+ strict_mode,
+ scope_position);
int entry = FindEntry(&key);
if (entry == kNotFound) return GetHeap()->undefined_value();
return get(EntryToIndex(entry) + 1);
@@ -11556,10 +11569,12 @@
MaybeObject* CompilationCacheTable::PutEval(String* src,
Context* context,
- SharedFunctionInfo* value) {
+ SharedFunctionInfo* value,
+ int scope_position) {
StringSharedKey key(src,
context->closure()->shared(),
- value->strict_mode_flag());
+ value->strict_mode_flag(),
+ scope_position);
Object* obj;
{ MaybeObject* maybe_obj = EnsureCapacity(1, &key);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
=======================================
--- /branches/bleeding_edge/src/objects.h Fri Nov 11 06:49:16 2011
+++ /branches/bleeding_edge/src/objects.h Mon Nov 14 00:58:47 2011
@@ -5849,12 +5849,16 @@
public:
// Find cached value for a string key, otherwise return null.
Object* Lookup(String* src);
- Object* LookupEval(String* src, Context* context, StrictModeFlag
strict_mode);
+ Object* LookupEval(String* src,
+ Context* context,
+ StrictModeFlag strict_mode,
+ int scope_position);
Object* LookupRegExp(String* source, JSRegExp::Flags flags);
MaybeObject* Put(String* src, Object* value);
MaybeObject* PutEval(String* src,
Context* context,
- SharedFunctionInfo* value);
+ SharedFunctionInfo* value,
+ int scope_position);
MaybeObject* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray*
value);
// Remove given value from cache.
=======================================
--- /branches/bleeding_edge/src/runtime.cc Fri Nov 11 09:48:40 2011
+++ /branches/bleeding_edge/src/runtime.cc Mon Nov 14 00:58:47 2011
@@ -9477,10 +9477,8 @@
}
// Compile source string in the global context.
- Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source,
- context,
- true,
-
kNonStrictMode);
+ Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
+ source, context, true, kNonStrictMode, RelocInfo::kNoPosition);
if (shared.is_null()) return Failure::Exception();
Handle<JSFunction> fun =
isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
@@ -9493,7 +9491,8 @@
static ObjectPair CompileGlobalEval(Isolate* isolate,
Handle<String> source,
Handle<Object> receiver,
- StrictModeFlag strict_mode) {
+ StrictModeFlag strict_mode,
+ int scope_position) {
Handle<Context> context = Handle<Context>(isolate->context());
Handle<Context> global_context =
Handle<Context>(context->global_context());
@@ -9511,7 +9510,8 @@
source,
Handle<Context>(isolate->context()),
context->IsGlobalContext(),
- strict_mode);
+ strict_mode,
+ scope_position);
if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
Handle<JSFunction> compiled =
isolate->factory()->NewFunctionFromSharedFunctionInfo(
@@ -9521,7 +9521,7 @@
RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
- ASSERT(args.length() == 4);
+ ASSERT(args.length() == 5);
HandleScope scope(isolate);
Handle<Object> callee = args.at<Object>(0);
@@ -9537,10 +9537,12 @@
}
CONVERT_STRICT_MODE_ARG(strict_mode, 3);
+ ASSERT(args[4]->IsSmi());
return CompileGlobalEval(isolate,
args.at<String>(1),
args.at<Object>(2),
- strict_mode);
+ strict_mode,
+ args.smi_at(4));
}
@@ -12154,7 +12156,8 @@
Compiler::CompileEval(function_source,
context,
context->IsGlobalContext(),
- kNonStrictMode);
+ kNonStrictMode,
+ RelocInfo::kNoPosition);
if (shared.is_null()) return Failure::Exception();
Handle<JSFunction> compiled_function =
isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
context);
@@ -12247,7 +12250,11 @@
// Currently, the eval code will be executed in non-strict mode,
// even in the strict code context.
Handle<SharedFunctionInfo> shared =
- Compiler::CompileEval(source, context, is_global, kNonStrictMode);
+ Compiler::CompileEval(source,
+ context,
+ is_global,
+ kNonStrictMode,
+ RelocInfo::kNoPosition);
if (shared.is_null()) return Failure::Exception();
Handle<JSFunction> compiled_function =
Handle<JSFunction>(
=======================================
--- /branches/bleeding_edge/src/runtime.h Tue Nov 8 06:39:37 2011
+++ /branches/bleeding_edge/src/runtime.h Mon Nov 14 00:58:47 2011
@@ -259,7 +259,7 @@
\
/* Eval */ \
F(GlobalReceiver, 1, 1) \
- F(ResolvePossiblyDirectEval, 4, 2) \
+ F(ResolvePossiblyDirectEval, 5, 2) \
\
F(SetProperty, -1 /* 4 or 5 */, 1) \
F(DefineOrRedefineDataProperty, 4, 1) \
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Fri Nov 11 05:48:14
2011
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Mon Nov 14 00:58:47
2011
@@ -2096,7 +2096,10 @@
FLAG_harmony_scoping ? kStrictMode : strict_mode_flag();
__ Push(Smi::FromInt(strict_mode));
- __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
+ // Push the start position of the scope the calls resides in.
+ __ Push(Smi::FromInt(scope()->start_position()));
+
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev