Revision: 6652
Author: [email protected]
Date: Fri Feb  4 10:15:49 2011
Log: Pass strict mode to eval.
Code review feedback.

Code Review URL: http://codereview.chromium.org/6286043/
http://code.google.com/p/v8/source/detail?r=6652

Added:
 /branches/bleeding_edge/test/mjsunit/strict-mode-eval.js
Modified:
 /branches/bleeding_edge/src/arm/codegen-arm.cc
 /branches/bleeding_edge/src/arm/codegen-arm.h
 /branches/bleeding_edge/src/arm/full-codegen-arm.cc
 /branches/bleeding_edge/src/codegen-inl.h
 /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/full-codegen.h
 /branches/bleeding_edge/src/ia32/codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/codegen-ia32.h
 /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/parser.cc
 /branches/bleeding_edge/src/parser.h
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/runtime.h
 /branches/bleeding_edge/src/v8globals.h
 /branches/bleeding_edge/src/x64/codegen-x64.cc
 /branches/bleeding_edge/src/x64/codegen-x64.h
 /branches/bleeding_edge/src/x64/full-codegen-x64.cc

=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/strict-mode-eval.js Fri Feb 4 10:15:49 2011
@@ -0,0 +1,82 @@
+// 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:
+//
+//     * 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.
+
+"use strict";
+
+var code1 = "function f(eval) {}";
+var code2 = "function f(a, a) {}";
+var code3 = "var x = '\\020;'";
+var code4 = "function arguments() {}";
+
+// Verify the code compiles just fine in non-strict mode
+// (using aliased eval to force non-strict mode)
+var eval_alias = eval;
+
+eval_alias(code1);
+eval_alias(code2);
+eval_alias(code3);
+eval_alias(code4);
+
+function strict1() {
+  try {
+    eval(code1);
+    assertUnreachable("did not throw exception");
+  } catch (e) {
+    assertInstanceof(e, SyntaxError);
+  }
+
+  function strict2() {
+    try {
+      eval(code2);
+      assertUnreachable("did not throw exception");
+    } catch (e) {
+      assertInstanceof(e, SyntaxError);
+    }
+
+    function strict3() {
+      try {
+        eval(code3);
+        assertUnreachable("did not throw exception");
+      } catch (e) {
+        assertInstanceof(e, SyntaxError);
+      }
+
+      function strict4() {
+        try {
+          eval(code4);
+          assertUnreachable("did not throw exception");
+        } catch (e) {
+          assertInstanceof(e, SyntaxError);
+        }
+      }
+      strict4();
+    }
+    strict3();
+  }
+  strict2();
+}
+strict1();
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc      Fri Feb  4 02:52:19 2011
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc      Fri Feb  4 10:15:49 2011
@@ -4177,7 +4177,10 @@
       __ ldr(r1, frame_->Receiver());
       frame_->EmitPush(r1);

-      frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup, 3);
+      // Push the strict mode flag.
+      frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag())));
+
+      frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup, 4);

       done.Jump();
       slow.Bind();
@@ -4197,8 +4200,11 @@
     __ ldr(r1, frame_->Receiver());
     frame_->EmitPush(r1);

+    // Push the strict mode flag.
+    frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag())));
+
     // Resolve the call.
-    frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
+    frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);

     // If we generated fast-case code bind the jump-target where fast
     // and slow case merge.
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.h       Tue Dec  7 03:31:57 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.h       Fri Feb  4 10:15:49 2011
@@ -287,6 +287,7 @@
   // Accessors
   inline bool is_eval();
   inline Scope* scope();
+  inline StrictModeFlag strict_mode_flag();

   // Generating deferred code.
   void ProcessDeferred();
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Fri Feb 4 02:52:19 2011 +++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Fri Feb 4 10:15:49 2011
@@ -1926,7 +1926,10 @@
       __ ldr(r1,
MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize));
       __ push(r1);
-      __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
+      // Push the strict mode flag.
+      __ mov(r1, Operand(Smi::FromInt(strict_mode_flag())));
+      __ push(r1);
+      __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);

       // The runtime call returns a pair of values in r0 (function) and
       // r1 (receiver). Touch up the stack with the right values.
=======================================
--- /branches/bleeding_edge/src/codegen-inl.h   Tue Dec  7 03:01:02 2010
+++ /branches/bleeding_edge/src/codegen-inl.h   Fri Feb  4 10:15:49 2011
@@ -54,6 +54,10 @@
 bool CodeGenerator::is_eval() { return info_->is_eval(); }

 Scope* CodeGenerator::scope() { return info_->function()->scope(); }
+
+StrictModeFlag CodeGenerator::strict_mode_flag() {
+  return info_->function()->strict_mode() ? kStrictMode : kNonStrictMode;
+}

 } }  // namespace v8::internal

=======================================
--- /branches/bleeding_edge/src/compilation-cache.cc Tue Dec 7 03:31:57 2010 +++ /branches/bleeding_edge/src/compilation-cache.cc Fri Feb 4 10:15:49 2011
@@ -136,7 +136,8 @@
       : CompilationSubCache(generations) { }

   Handle<SharedFunctionInfo> Lookup(Handle<String> source,
-                                    Handle<Context> context);
+                                    Handle<Context> context,
+                                    StrictModeFlag strict_mode);

   void Put(Handle<String> source,
            Handle<Context> context,
@@ -371,7 +372,9 @@


 Handle<SharedFunctionInfo> CompilationCacheEval::Lookup(
-    Handle<String> source, Handle<Context> context) {
+    Handle<String> source,
+    Handle<Context> context,
+    StrictModeFlag strict_mode) {
   // 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.
@@ -380,7 +383,7 @@
   { HandleScope scope;
     for (generation = 0; generation < generations(); generation++) {
       Handle<CompilationCacheTable> table = GetTable(generation);
-      result = table->LookupEval(*source, *context);
+      result = table->LookupEval(*source, *context, strict_mode);
       if (result->IsSharedFunctionInfo()) {
         break;
       }
@@ -503,18 +506,20 @@
 }


-Handle<SharedFunctionInfo> CompilationCache::LookupEval(Handle<String> source, - Handle<Context> context,
-                                                        bool is_global) {
+Handle<SharedFunctionInfo> CompilationCache::LookupEval(
+    Handle<String> source,
+    Handle<Context> context,
+    bool is_global,
+    StrictModeFlag strict_mode) {
   if (!IsEnabled()) {
     return Handle<SharedFunctionInfo>::null();
   }

   Handle<SharedFunctionInfo> result;
   if (is_global) {
-    result = eval_global.Lookup(source, context);
+    result = eval_global.Lookup(source, context, strict_mode);
   } else {
-    result = eval_contextual.Lookup(source, context);
+    result = eval_contextual.Lookup(source, context, strict_mode);
   }
   return result;
 }
=======================================
--- /branches/bleeding_edge/src/compilation-cache.h     Tue Dec  7 03:31:57 2010
+++ /branches/bleeding_edge/src/compilation-cache.h     Fri Feb  4 10:15:49 2011
@@ -51,7 +51,8 @@
   // contain a script for the given source string.
   static Handle<SharedFunctionInfo> LookupEval(Handle<String> source,
                                                Handle<Context> context,
-                                               bool is_global);
+                                               bool is_global,
+                                               StrictModeFlag strict_mode);

   // Returns the regexp data associated with the given regexp if it
   // is in cache, otherwise an empty handle.
=======================================
--- /branches/bleeding_edge/src/compiler.cc     Wed Jan 19 05:55:56 2011
+++ /branches/bleeding_edge/src/compiler.cc     Fri Feb  4 10:15:49 2011
@@ -548,7 +548,8 @@

 Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
                                                  Handle<Context> context,
-                                                 bool is_global) {
+                                                 bool is_global,
+ StrictModeFlag strict_mode) {
   int source_length = source->length();
   Counters::total_eval_size.Increment(source_length);
   Counters::total_compile_size.Increment(source_length);
@@ -559,7 +560,10 @@
// Do a lookup in the compilation cache; if the entry is not there, invoke
   // the compiler and add the result to the cache.
   Handle<SharedFunctionInfo> result;
-  result = CompilationCache::LookupEval(source, context, is_global);
+  result = CompilationCache::LookupEval(source,
+                                        context,
+                                        is_global,
+                                        strict_mode);

   if (result.is_null()) {
     // Create a script object describing the script to be compiled.
@@ -567,9 +571,14 @@
     CompilationInfo info(script);
     info.MarkAsEval();
     if (is_global) info.MarkAsGlobal();
+    if (strict_mode == kStrictMode) info.MarkAsStrict();
     info.SetCallingContext(context);
     result = MakeFunctionInfo(&info);
     if (!result.is_null()) {
+      // If caller is strict mode, the result must be strict as well,
+      // but not the other way around. Consider:
+      // eval("'use strict'; ...");
+      ASSERT(strict_mode == kNonStrictMode || result->strict_mode());
       CompilationCache::PutEval(source, context, is_global, result);
     }
   }
@@ -762,6 +771,7 @@
       *lit->this_property_assignments());
   function_info->set_try_full_codegen(lit->try_full_codegen());
   function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
+  function_info->set_strict_mode(lit->strict_mode());
 }


=======================================
--- /branches/bleeding_edge/src/compiler.h      Tue Jan 18 05:43:48 2011
+++ /branches/bleeding_edge/src/compiler.h      Fri Feb  4 10:15:49 2011
@@ -49,6 +49,7 @@
   bool is_lazy() const { return (flags_ & IsLazy::mask()) != 0; }
   bool is_eval() const { return (flags_ & IsEval::mask()) != 0; }
   bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; }
+  bool is_strict() const { return (flags_ & IsStrict::mask()) != 0; }
   bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
   FunctionLiteral* function() const { return function_; }
   Scope* scope() const { return scope_; }
@@ -69,6 +70,13 @@
     ASSERT(!is_lazy());
     flags_ |= IsGlobal::encode(true);
   }
+  void MarkAsStrict() {
+    ASSERT(!is_lazy());
+    flags_ |= IsStrict::encode(true);
+  }
+  StrictModeFlag StrictMode() {
+    return is_strict() ? kStrictMode : kNonStrictMode;
+  }
   void MarkAsInLoop() {
     ASSERT(is_lazy());
     flags_ |= IsInLoop::encode(true);
@@ -162,6 +170,8 @@
   class IsGlobal: public BitField<bool, 2, 1> {};
   // Flags that can be set for lazy compilation.
   class IsInLoop: public BitField<bool, 3, 1> {};
+  // Strict mode - used in eager compilation.
+  class IsStrict: public BitField<bool, 4, 1> {};

   unsigned flags_;

@@ -230,7 +240,8 @@
   // Compile a String source within a context for Eval.
   static Handle<SharedFunctionInfo> CompileEval(Handle<String> source,
                                                 Handle<Context> context,
-                                                bool is_global);
+                                                bool is_global,
+ StrictModeFlag strict_mode);

// 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/full-codegen.h  Wed Dec 15 08:14:29 2010
+++ /branches/bleeding_edge/src/full-codegen.h  Fri Feb  4 10:15:49 2011
@@ -531,6 +531,9 @@

   Handle<Script> script() { return info_->script(); }
   bool is_eval() { return info_->is_eval(); }
+  StrictModeFlag strict_mode_flag() {
+    return function()->strict_mode() ? kStrictMode : kNonStrictMode;
+  }
   FunctionLiteral* function() { return info_->function(); }
   Scope* scope() { return info_->scope(); }

=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Wed Feb 2 04:54:58 2011 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Feb 4 10:15:49 2011
@@ -6102,9 +6102,12 @@
       }
       frame_->PushParameterAt(-1);

+      // Push the strict mode flag.
+      frame_->Push(Smi::FromInt(strict_mode_flag()));
+
       // Resolve the call.
       result =
- frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup, 3); + frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup, 4);

       done.Jump(&result);
       slow.Bind();
@@ -6121,8 +6124,11 @@
     }
     frame_->PushParameterAt(-1);

+    // Push the strict mode flag.
+    frame_->Push(Smi::FromInt(strict_mode_flag()));
+
     // Resolve the call.
-    result = frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
+    result = frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);

     // If we generated fast-case code bind the jump-target where fast
     // and slow case merge.
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.h     Tue Dec  7 03:31:57 2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.h     Fri Feb  4 10:15:49 2011
@@ -365,6 +365,7 @@
   // Accessors
   inline bool is_eval();
   inline Scope* scope();
+  inline StrictModeFlag strict_mode_flag();

   // Generating deferred code.
   void ProcessDeferred();
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Fri Feb 4 04:06:41 2011 +++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Fri Feb 4 10:15:49 2011
@@ -2292,7 +2292,9 @@

       // Push the receiver of the enclosing function and do runtime call.
__ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
-      __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
+      // Push the strict mode flag.
+      __ push(Immediate(Smi::FromInt(strict_mode_flag())));
+      __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);

       // The runtime call returns a pair of values in eax (function) and
       // edx (receiver). Touch up the stack with the right values.
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Thu Feb  3 02:07:22 2011
+++ /branches/bleeding_edge/src/objects-inl.h   Fri Feb  4 10:15:49 2011
@@ -2991,6 +2991,18 @@
     code()->set_optimizable(false);
   }
 }
+
+
+bool SharedFunctionInfo::strict_mode() {
+  return BooleanBit::get(compiler_hints(), kStrictModeFunction);
+}
+
+
+void SharedFunctionInfo::set_strict_mode(bool value) {
+  set_compiler_hints(BooleanBit::set(compiler_hints(),
+                                     kStrictModeFunction,
+                                     value));
+}


 ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
=======================================
--- /branches/bleeding_edge/src/objects.cc      Fri Feb  4 06:09:03 2011
+++ /branches/bleeding_edge/src/objects.cc      Fri Feb  4 10:15:49 2011
@@ -7998,20 +7998,28 @@
 // StringSharedKeys are used as keys in the eval cache.
 class StringSharedKey : public HashTableKey {
  public:
-  StringSharedKey(String* source, SharedFunctionInfo* shared)
-      : source_(source), shared_(shared) { }
+  StringSharedKey(String* source,
+                  SharedFunctionInfo* shared,
+                  StrictModeFlag strict_mode)
+      : source_(source),
+        shared_(shared),
+        strict_mode_(strict_mode) { }

   bool IsMatch(Object* other) {
     if (!other->IsFixedArray()) return false;
     FixedArray* pair = FixedArray::cast(other);
     SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
     if (shared != shared_) return false;
+    StrictModeFlag strict_mode = static_cast<StrictModeFlag>(
+        Smi::cast(pair->get(2))->value());
+    if (strict_mode != strict_mode_) return false;
     String* source = String::cast(pair->get(1));
     return source->Equals(source_);
   }

   static uint32_t StringSharedHashHelper(String* source,
-                                         SharedFunctionInfo* shared) {
+                                         SharedFunctionInfo* shared,
+                                         StrictModeFlag strict_mode) {
     uint32_t hash = source->Hash();
     if (shared->HasSourceCode()) {
       // Instead of using the SharedFunctionInfo pointer in the hash
@@ -8021,36 +8029,41 @@
       // collection.
       Script* script = Script::cast(shared->script());
       hash ^= String::cast(script->source())->Hash();
+      if (strict_mode == kStrictMode) hash ^= 0x8000;
       hash += shared->start_position();
     }
     return hash;
   }

   uint32_t Hash() {
-    return StringSharedHashHelper(source_, shared_);
+    return StringSharedHashHelper(source_, shared_, strict_mode_);
   }

   uint32_t HashForObject(Object* obj) {
     FixedArray* pair = FixedArray::cast(obj);
     SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
     String* source = String::cast(pair->get(1));
-    return StringSharedHashHelper(source, shared);
+    StrictModeFlag strict_mode = static_cast<StrictModeFlag>(
+        Smi::cast(pair->get(2))->value());
+    return StringSharedHashHelper(source, shared, strict_mode);
   }

   MUST_USE_RESULT MaybeObject* AsObject() {
     Object* obj;
-    { MaybeObject* maybe_obj = Heap::AllocateFixedArray(2);
+    { MaybeObject* maybe_obj = Heap::AllocateFixedArray(3);
       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;
   }

  private:
   String* source_;
   SharedFunctionInfo* shared_;
+  StrictModeFlag strict_mode_;
 };


@@ -9009,8 +9022,10 @@
 }


-Object* CompilationCacheTable::LookupEval(String* src, Context* context) {
-  StringSharedKey key(src, context->closure()->shared());
+Object* CompilationCacheTable::LookupEval(String* src,
+                                          Context* context,
+                                          StrictModeFlag strict_mode) {
+  StringSharedKey key(src, context->closure()->shared(), strict_mode);
   int entry = FindEntry(&key);
   if (entry == kNotFound) return Heap::undefined_value();
   return get(EntryToIndex(entry) + 1);
@@ -9045,8 +9060,10 @@

 MaybeObject* CompilationCacheTable::PutEval(String* src,
                                             Context* context,
-                                            Object* value) {
-  StringSharedKey key(src, context->closure()->shared());
+                                            SharedFunctionInfo* value) {
+  StringSharedKey key(src,
+                      context->closure()->shared(),
+                      value->strict_mode() ? kStrictMode : kNonStrictMode);
   Object* obj;
   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Feb  3 02:07:22 2011
+++ /branches/bleeding_edge/src/objects.h       Fri Feb  4 10:15:49 2011
@@ -4176,6 +4176,10 @@
   inline bool optimization_disabled();
   inline void set_optimization_disabled(bool value);

+  // Indicates whether the function is a strict mode function.
+  inline bool strict_mode();
+  inline void set_strict_mode(bool value);
+
   // Indicates whether or not the code in the shared function support
   // deoptimization.
   inline bool has_deoptimization_support();
@@ -4357,6 +4361,7 @@
   static const int kCodeAgeShift = 4;
   static const int kCodeAgeMask = 0x7;
   static const int kOptimizationDisabled = 7;
+  static const int kStrictModeFunction = 8;

   DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
 };
@@ -4902,10 +4907,12 @@
  public:
   // Find cached value for a string key, otherwise return null.
   Object* Lookup(String* src);
-  Object* LookupEval(String* src, Context* context);
+ Object* LookupEval(String* src, Context* context, StrictModeFlag strict_mode);
   Object* LookupRegExp(String* source, JSRegExp::Flags flags);
   MaybeObject* Put(String* src, Object* value);
-  MaybeObject* PutEval(String* src, Context* context, Object* value);
+  MaybeObject* PutEval(String* src,
+                       Context* context,
+                       SharedFunctionInfo* value);
MaybeObject* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value);

   // Remove given value from cache.
=======================================
--- /branches/bleeding_edge/src/parser.cc       Wed Feb  2 06:02:58 2011
+++ /branches/bleeding_edge/src/parser.cc       Fri Feb  4 10:15:49 2011
@@ -616,7 +616,8 @@


 FunctionLiteral* Parser::ParseProgram(Handle<String> source,
-                                      bool in_global_context) {
+                                      bool in_global_context,
+                                      StrictModeFlag strict_mode) {
   CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT);

   HistogramTimerScope timer(&Counters::parse);
@@ -632,17 +633,18 @@
     ExternalTwoByteStringUC16CharacterStream stream(
         Handle<ExternalTwoByteString>::cast(source), 0, source->length());
     scanner_.Initialize(&stream);
-    return DoParseProgram(source, in_global_context, &zone_scope);
+ return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
   } else {
     GenericStringUC16CharacterStream stream(source, 0, source->length());
     scanner_.Initialize(&stream);
-    return DoParseProgram(source, in_global_context, &zone_scope);
+ return DoParseProgram(source, in_global_context, strict_mode, &zone_scope);
   }
 }


 FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
                                         bool in_global_context,
+                                        StrictModeFlag strict_mode,
                                         ZoneScope* zone_scope) {
   ASSERT(target_stack_ == NULL);
   if (pre_data_ != NULL) pre_data_->Initialize();
@@ -662,6 +664,9 @@
LexicalScope lexical_scope(&this->top_scope_, &this->with_nesting_level_,
                                scope);
     TemporaryScope temp_scope(&this->temp_scope_);
+    if (strict_mode == kStrictMode) {
+      temp_scope.EnableStrictMode();
+    }
     ZoneList<Statement*>* body = new ZoneList<Statement*>(16);
     bool ok = true;
     int beg_loc = scanner().location().beg_pos;
@@ -747,6 +752,10 @@
                                scope);
     TemporaryScope temp_scope(&this->temp_scope_);

+    if (info->strict_mode()) {
+      temp_scope.EnableStrictMode();
+    }
+
     FunctionLiteralType type =
         info->is_expression() ? EXPRESSION : DECLARATION;
     bool ok = true;
@@ -5024,7 +5033,9 @@
       ASSERT(Top::has_pending_exception());
     } else {
Handle<String> source = Handle<String>(String::cast(script->source()));
-      result = parser.ParseProgram(source, info->is_global());
+      result = parser.ParseProgram(source,
+                                   info->is_global(),
+                                   info->StrictMode());
     }
   }

=======================================
--- /branches/bleeding_edge/src/parser.h        Wed Jan 26 11:21:46 2011
+++ /branches/bleeding_edge/src/parser.h        Fri Feb  4 10:15:49 2011
@@ -423,7 +423,8 @@

   // Returns NULL if parsing failed.
   FunctionLiteral* ParseProgram(Handle<String> source,
-                                bool in_global_context);
+                                bool in_global_context,
+                                StrictModeFlag strict_mode);

   FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info);

@@ -446,6 +447,7 @@
   // Called by ParseProgram after setting up the scanner.
   FunctionLiteral* DoParseProgram(Handle<String> source,
                                   bool in_global_context,
+                                  StrictModeFlag strict_mode,
                                   ZoneScope* zone_scope);

   // Report syntax error
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Fri Feb  4 04:14:56 2011
+++ /branches/bleeding_edge/src/runtime.cc      Fri Feb  4 10:15:49 2011
@@ -7674,7 +7674,8 @@
   Handle<Context> context(Top::context()->global_context());
   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source,
                                                             context,
-                                                            true);
+                                                            true,
+ kNonStrictMode);
   if (shared.is_null()) return Failure::Exception();
   Handle<JSFunction> fun =
Factory::NewFunctionFromSharedFunctionInfo(shared, context, NOT_TENURED);
@@ -7683,13 +7684,15 @@


 static ObjectPair CompileGlobalEval(Handle<String> source,
-                                    Handle<Object> receiver) {
+                                    Handle<Object> receiver,
+                                    StrictModeFlag mode) {
   // Deal with a normal eval call with a string argument. Compile it
   // and return the compiled function bound in the local context.
   Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
       source,
       Handle<Context>(Top::context()),
-      Top::context()->IsGlobalContext());
+      Top::context()->IsGlobalContext(),
+      mode);
   if (shared.is_null()) return MakePair(Failure::Exception(), NULL);
   Handle<JSFunction> compiled = Factory::NewFunctionFromSharedFunctionInfo(
       shared,
@@ -7700,7 +7703,7 @@


 static ObjectPair Runtime_ResolvePossiblyDirectEval(Arguments args) {
-  ASSERT(args.length() == 3);
+  ASSERT(args.length() == 4);
   if (!args[0]->IsJSFunction()) {
     return MakePair(Top::ThrowIllegalOperation(), NULL);
   }
@@ -7764,12 +7767,16 @@
     return MakePair(*callee, Top::context()->global()->global_receiver());
   }

-  return CompileGlobalEval(args.at<String>(1), args.at<Object>(2));
+  ASSERT(args[3]->IsSmi());
+  return CompileGlobalEval(args.at<String>(1),
+                           args.at<Object>(2),
+                           static_cast<StrictModeFlag>(
+                                Smi::cast(args[3])->value()));
 }


static ObjectPair Runtime_ResolvePossiblyDirectEvalNoLookup(Arguments args) {
-  ASSERT(args.length() == 3);
+  ASSERT(args.length() == 4);
   if (!args[0]->IsJSFunction()) {
     return MakePair(Top::ThrowIllegalOperation(), NULL);
   }
@@ -7784,7 +7791,11 @@
     return MakePair(*callee, Top::context()->global()->global_receiver());
   }

-  return CompileGlobalEval(args.at<String>(1), args.at<Object>(2));
+  ASSERT(args[3]->IsSmi());
+  return CompileGlobalEval(args.at<String>(1),
+                           args.at<Object>(2),
+                           static_cast<StrictModeFlag>(
+                                Smi::cast(args[3])->value()));
 }


@@ -9921,10 +9932,14 @@
   Handle<String> function_source =
       Factory::NewStringFromAscii(Vector<const char>(source_str,
                                                      source_str_length));
+
+  // Currently, the eval code will be executed in non-strict mode,
+  // even in the strict code context.
   Handle<SharedFunctionInfo> shared =
       Compiler::CompileEval(function_source,
                             context,
-                            context->IsGlobalContext());
+                            context->IsGlobalContext(),
+                            kNonStrictMode);
   if (shared.is_null()) return Failure::Exception();
   Handle<JSFunction> compiled_function =
       Factory::NewFunctionFromSharedFunctionInfo(shared, context);
@@ -10006,10 +10021,10 @@
   }

   // Compile the source to be evaluated.
+  // 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);
+      Compiler::CompileEval(source, context, is_global, kNonStrictMode);
   if (shared.is_null()) return Failure::Exception();
   Handle<JSFunction> compiled_function =
       Handle<JSFunction>(Factory::NewFunctionFromSharedFunctionInfo(shared,
=======================================
--- /branches/bleeding_edge/src/runtime.h       Wed Feb  2 05:31:52 2011
+++ /branches/bleeding_edge/src/runtime.h       Fri Feb  4 10:15:49 2011
@@ -237,8 +237,8 @@
   \
   /* Eval */ \
   F(GlobalReceiver, 1, 1) \
-  F(ResolvePossiblyDirectEval, 3, 2) \
-  F(ResolvePossiblyDirectEvalNoLookup, 3, 2) \
+  F(ResolvePossiblyDirectEval, 4, 2) \
+  F(ResolvePossiblyDirectEvalNoLookup, 4, 2) \
   \
   F(SetProperty, -1 /* 3 or 4 */, 1) \
   F(DefineOrRedefineDataProperty, 4, 1) \
=======================================
--- /branches/bleeding_edge/src/v8globals.h     Fri Jan 14 05:16:48 2011
+++ /branches/bleeding_edge/src/v8globals.h     Fri Feb  4 10:15:49 2011
@@ -469,6 +469,12 @@
                   ARMv7 = 2,   // ARM
                   SAHF = 0};   // x86

+// The Strict Mode (ECMA-262 5th edition, 4.2.2).
+enum StrictModeFlag {
+  kNonStrictMode,
+  kStrictMode
+};
+
 } }  // namespace v8::internal

 #endif  // V8_V8GLOBALS_H_
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Wed Feb  2 04:54:58 2011
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Fri Feb  4 10:15:49 2011
@@ -5402,9 +5402,12 @@
       }
       frame_->PushParameterAt(-1);

+      // Push the strict mode flag.
+      frame_->Push(Smi::FromInt(strict_mode_flag()));
+
       // Resolve the call.
       result =
- frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup, 3); + frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup, 4);

       done.Jump(&result);
       slow.Bind();
@@ -5421,8 +5424,11 @@
     }
     frame_->PushParameterAt(-1);

+    // Push the strict mode flag.
+    frame_->Push(Smi::FromInt(strict_mode_flag()));
+
     // Resolve the call.
-    result = frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
+    result = frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);

     // If we generated fast-case code bind the jump-target where fast
     // and slow case merge.
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.h       Tue Dec  7 03:31:57 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.h       Fri Feb  4 10:15:49 2011
@@ -357,6 +357,7 @@
   // Accessors
   inline bool is_eval();
   inline Scope* scope();
+  inline StrictModeFlag strict_mode_flag();

   // Generating deferred code.
   void ProcessDeferred();
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Thu Feb 3 07:36:44 2011 +++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Fri Feb 4 10:15:49 2011
@@ -1924,7 +1924,9 @@

       // Push the receiver of the enclosing function and do runtime call.
__ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize));
-      __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3);
+      // Push the strict mode flag.
+      __ Push(Smi::FromInt(strict_mode_flag()));
+      __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);

       // The runtime call returns a pair of values in rax (function) and
       // rdx (receiver). Touch up the stack with the right values.

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to