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

Reply via email to