Replace boolean indications of strict mode by an enum value.
authorkeuchel@chromium.org <keuchel@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 24 Oct 2011 07:47:22 +0000 (07:47 +0000)
committerkeuchel@chromium.org <keuchel@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 24 Oct 2011 07:47:22 +0000 (07:47 +0000)
Review URL: http://codereview.chromium.org/8344082

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9746 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

31 files changed:
src/arm/full-codegen-arm.cc
src/arm/lithium-arm.h
src/arm/lithium-codegen-arm.cc
src/arm/lithium-codegen-arm.h
src/ast-inl.h
src/ast.h
src/compiler.cc
src/compiler.h
src/full-codegen.cc
src/full-codegen.h
src/hydrogen-instructions.h
src/hydrogen.cc
src/hydrogen.h
src/ia32/full-codegen-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-codegen-ia32.h
src/ia32/lithium-ia32.h
src/objects-inl.h
src/objects.cc
src/objects.h
src/parser.cc
src/preparser.h
src/runtime.cc
src/runtime.h
src/scopes.cc
src/scopes.h
src/x64/full-codegen-x64.cc
src/x64/lithium-codegen-x64.cc
src/x64/lithium-codegen-x64.h
src/x64/lithium-x64.h
test/mjsunit/compiler/strict-recompile.js [new file with mode: 0644]

index 30e8ea6..7ac6ce9 100644 (file)
@@ -1097,7 +1097,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
       !pretenure &&
       scope()->is_function_scope() &&
       info->num_literals() == 0) {
-    FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode);
+    FastNewClosureStub stub(info->strict_mode_flag());
     __ mov(r0, Operand(info));
     __ push(r0);
     __ CallStub(&stub);
index 34b4adc..5733bd0 100644 (file)
@@ -1582,7 +1582,8 @@ class LStoreNamedGeneric: public LTemplateInstruction<0, 2, 0> {
   LOperand* object() { return inputs_[0]; }
   LOperand* value() { return inputs_[1]; }
   Handle<Object> name() const { return hydrogen()->name(); }
-  bool strict_mode() { return hydrogen()->strict_mode(); }
+  StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+  bool strict_mode() { return strict_mode_flag() == kStrictMode; }
 };
 
 
index 0265382..4cf7df4 100644 (file)
@@ -4416,8 +4416,7 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
   Handle<SharedFunctionInfo> shared_info = instr->shared_info();
   bool pretenure = instr->hydrogen()->pretenure();
   if (!pretenure && shared_info->num_literals() == 0) {
-    FastNewClosureStub stub(
-        shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
+    FastNewClosureStub stub(shared_info->strict_mode_flag());
     __ mov(r1, Operand(shared_info));
     __ push(r1);
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
index d13e7d4..b01e496 100644 (file)
@@ -140,8 +140,8 @@ class LCodeGen BASE_EMBEDDED {
   bool is_done() const { return status_ == DONE; }
   bool is_aborted() const { return status_ == ABORTED; }
 
-  int strict_mode_flag() const {
-    return info()->is_strict_mode() ? kStrictMode : kNonStrictMode;
+  StrictModeFlag strict_mode_flag() const {
+    return info()->strict_mode_flag();
   }
 
   LChunk* chunk() const { return chunk_; }
index a3af259..f8b460d 100644 (file)
@@ -121,8 +121,8 @@ int FunctionLiteral::end_position() const {
 }
 
 
-bool FunctionLiteral::strict_mode() const {
-  return scope()->is_strict_mode();
+StrictModeFlag FunctionLiteral::strict_mode_flag() const {
+  return scope()->strict_mode_flag();
 }
 
 
index cb7763b..e5aa57e 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -1648,7 +1648,8 @@ class FunctionLiteral: public Expression {
   int end_position() const;
   bool is_expression() const { return is_expression_; }
   bool is_anonymous() const { return is_anonymous_; }
-  bool strict_mode() const;
+  bool strict_mode() const { return strict_mode_flag() == kStrictMode; }
+  StrictModeFlag strict_mode_flag() const;
 
   int materialized_literal_count() { return materialized_literal_count_; }
   int expected_property_count() { return expected_property_count_; }
index 7f04aae..88db467 100644 (file)
@@ -558,7 +558,7 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
     CompilationInfo info(script);
     info.MarkAsEval();
     if (is_global) info.MarkAsGlobal();
-    if (strict_mode == kStrictMode) info.MarkAsStrictMode();
+    info.SetStrictModeFlag(strict_mode);
     info.SetCallingContext(context);
     result = MakeFunctionInfo(&info);
     if (!result.is_null()) {
@@ -566,6 +566,7 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
       // 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);
     }
@@ -597,10 +598,13 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
     HistogramTimerScope timer(isolate->counters()->compile_lazy());
 
     // After parsing we know function's strict mode. Remember it.
-    if (info->function()->strict_mode()) {
-      shared->set_strict_mode(true);
-      info->MarkAsStrictMode();
-    }
+    StrictModeFlag strict_mode = info->function()->strict_mode_flag();
+    ASSERT(info->strict_mode_flag() == kNonStrictMode ||
+           info->strict_mode_flag() == strict_mode);
+    ASSERT(shared->strict_mode_flag() == kNonStrictMode ||
+           shared->strict_mode_flag() == strict_mode);
+    info->SetStrictModeFlag(strict_mode);
+    shared->set_strict_mode_flag(strict_mode);
 
     // Compile the code.
     if (!MakeCode(info)) {
@@ -680,7 +684,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
   CompilationInfo info(script);
   info.SetFunction(literal);
   info.SetScope(literal->scope());
-  if (literal->scope()->is_strict_mode()) info.MarkAsStrictMode();
+  info.SetStrictModeFlag(literal->scope()->strict_mode_flag());
 
   LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal);
   // Determine if the function can be lazily compiled. This is necessary to
@@ -746,7 +750,7 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
       lit->has_only_simple_this_property_assignments(),
       *lit->this_property_assignments());
   function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
-  function_info->set_strict_mode(lit->strict_mode());
+  function_info->set_strict_mode_flag(lit->strict_mode_flag());
   function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
   function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
 }
index 6d77a98..bedf5ee 100644 (file)
@@ -52,7 +52,10 @@ class CompilationInfo BASE_EMBEDDED {
   bool is_lazy() const { return IsLazy::decode(flags_); }
   bool is_eval() const { return IsEval::decode(flags_); }
   bool is_global() const { return IsGlobal::decode(flags_); }
-  bool is_strict_mode() const { return IsStrictMode::decode(flags_); }
+  bool is_strict_mode() const { return strict_mode_flag() == kStrictMode; }
+  StrictModeFlag strict_mode_flag() const {
+    return StrictModeFlagField::decode(flags_);
+  }
   bool is_in_loop() const { return IsInLoop::decode(flags_); }
   FunctionLiteral* function() const { return function_; }
   Scope* scope() const { return scope_; }
@@ -73,11 +76,10 @@ class CompilationInfo BASE_EMBEDDED {
     ASSERT(!is_lazy());
     flags_ |= IsGlobal::encode(true);
   }
-  void MarkAsStrictMode() {
-    flags_ |= IsStrictMode::encode(true);
-  }
-  StrictModeFlag StrictMode() {
-    return is_strict_mode() ? kStrictMode : kNonStrictMode;
+  void SetStrictModeFlag(StrictModeFlag strict_mode_flag) {
+    ASSERT(StrictModeFlagField::decode(flags_) == kNonStrictMode ||
+           StrictModeFlagField::decode(flags_) == strict_mode_flag);
+    flags_ = StrictModeFlagField::update(flags_, strict_mode_flag);
   }
   void MarkAsInLoop() {
     ASSERT(is_lazy());
@@ -186,8 +188,9 @@ class CompilationInfo BASE_EMBEDDED {
     if (script_->type()->value() == Script::TYPE_NATIVE) {
       MarkAsNative();
     }
-    if (!shared_info_.is_null() && shared_info_->strict_mode()) {
-      MarkAsStrictMode();
+    if (!shared_info_.is_null()) {
+      ASSERT(strict_mode_flag() == kNonStrictMode);
+      SetStrictModeFlag(shared_info_->strict_mode_flag());
     }
   }
 
@@ -207,7 +210,7 @@ class CompilationInfo BASE_EMBEDDED {
   // Flags that can be set for lazy compilation.
   class IsInLoop: public BitField<bool, 3, 1> {};
   // Strict mode - used in eager compilation.
-  class IsStrictMode: public BitField<bool, 4, 1> {};
+  class StrictModeFlagField: public BitField<StrictModeFlag, 4, 1> {};
   // Is this a function from our natives.
   class IsNative: public BitField<bool, 6, 1> {};
   // Is this code being compiled with support for deoptimization..
index 0eb36f4..efcd346 100644 (file)
@@ -547,11 +547,10 @@ void FullCodeGenerator::VisitDeclarations(
 
 
 int FullCodeGenerator::DeclareGlobalsFlags() {
-  int flags = 0;
-  if (is_eval()) flags |= kDeclareGlobalsEvalFlag;
-  if (is_strict_mode()) flags |= kDeclareGlobalsStrictModeFlag;
-  if (is_native()) flags |= kDeclareGlobalsNativeFlag;
-  return flags;
+  ASSERT(DeclareGlobalsStrictModeFlag::is_valid(strict_mode_flag()));
+  return DeclareGlobalsEvalFlag::encode(is_eval()) |
+      DeclareGlobalsStrictModeFlag::encode(strict_mode_flag()) |
+      DeclareGlobalsNativeFlag::encode(is_native());
 }
 
 
index 081192a..9132502 100644 (file)
@@ -577,9 +577,11 @@ class FullCodeGenerator: public AstVisitor {
   Handle<Script> script() { return info_->script(); }
   bool is_eval() { return info_->is_eval(); }
   bool is_native() { return info_->is_native(); }
-  bool is_strict_mode() { return function()->strict_mode(); }
+  bool is_strict_mode() {
+    return strict_mode_flag() == kStrictMode;
+  }
   StrictModeFlag strict_mode_flag() {
-    return is_strict_mode() ? kStrictMode : kNonStrictMode;
+    return function()->strict_mode_flag();
   }
   FunctionLiteral* function() { return info_->function(); }
   Scope* scope() { return scope_; }
index d993ec2..65fc4df 100644 (file)
@@ -3720,9 +3720,9 @@ class HStoreNamedGeneric: public HTemplateInstruction<3> {
                      HValue* object,
                      Handle<String> name,
                      HValue* value,
-                     bool strict_mode)
+                     StrictModeFlag strict_mode_flag)
       : name_(name),
-        strict_mode_(strict_mode) {
+        strict_mode_flag_(strict_mode_flag) {
     SetOperandAt(0, object);
     SetOperandAt(1, value);
     SetOperandAt(2, context);
@@ -3733,7 +3733,7 @@ class HStoreNamedGeneric: public HTemplateInstruction<3> {
   HValue* value() { return OperandAt(1); }
   HValue* context() { return OperandAt(2); }
   Handle<String> name() { return name_; }
-  bool strict_mode() { return strict_mode_; }
+  StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
 
   virtual void PrintDataTo(StringStream* stream);
 
@@ -3745,7 +3745,7 @@ class HStoreNamedGeneric: public HTemplateInstruction<3> {
 
  private:
   Handle<String> name_;
-  bool strict_mode_;
+  StrictModeFlag strict_mode_flag_;
 };
 
 
index 0b843bd..500e38f 100644 (file)
@@ -3276,7 +3276,7 @@ void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
                                 literal,
                                 name,
                                 value,
-                                function_strict_mode());
+                                function_strict_mode_flag());
             AddInstruction(store);
             AddSimulate(key->id());
           } else {
@@ -3454,7 +3454,7 @@ HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
                          object,
                          name,
                          value,
-                         function_strict_mode());
+                         function_strict_mode_flag());
 }
 
 
@@ -3639,7 +3639,7 @@ void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
                                         global_object,
                                         var->name(),
                                         value,
-                                        function_strict_mode());
+                                        function_strict_mode_flag());
     instr->set_position(position);
     AddInstruction(instr);
     ASSERT(instr->HasSideEffects());
@@ -4304,7 +4304,7 @@ HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
                          object,
                          key,
                          value,
-                         function_strict_mode());
+                         function_strict_mode_flag());
 }
 
 bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
index 8ed1121..ec8afe6 100644 (file)
@@ -769,8 +769,8 @@ class HGraphBuilder: public AstVisitor {
   void ClearInlinedTestContext() {
     function_state()->ClearInlinedTestContext();
   }
-  bool function_strict_mode() {
-    return function_state()->compilation_info()->is_strict_mode();
+  StrictModeFlag function_strict_mode_flag() {
+    return function_state()->compilation_info()->strict_mode_flag();
   }
 
   // Generators for inline runtime functions.
index 985128b..8362cbf 100644 (file)
@@ -1079,7 +1079,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
       !pretenure &&
       scope()->is_function_scope() &&
       info->num_literals() == 0) {
-    FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode);
+    FastNewClosureStub stub(info->strict_mode_flag());
     __ push(Immediate(info));
     __ CallStub(&stub);
   } else {
index 5016778..d4cbbce 100644 (file)
@@ -4313,8 +4313,7 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
   Handle<SharedFunctionInfo> shared_info = instr->shared_info();
   bool pretenure = instr->hydrogen()->pretenure();
   if (!pretenure && shared_info->num_literals() == 0) {
-    FastNewClosureStub stub(
-        shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
+    FastNewClosureStub stub(shared_info->strict_mode_flag());
     __ push(Immediate(shared_info));
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   } else {
index d48359d..412e418 100644 (file)
@@ -131,8 +131,8 @@ class LCodeGen BASE_EMBEDDED {
   bool is_done() const { return status_ == DONE; }
   bool is_aborted() const { return status_ == ABORTED; }
 
-  int strict_mode_flag() const {
-    return info()->is_strict_mode() ? kStrictMode : kNonStrictMode;
+  StrictModeFlag strict_mode_flag() const {
+    return info()->strict_mode_flag();
   }
   bool dynamic_frame_alignment() const { return dynamic_frame_alignment_; }
   void set_dynamic_frame_alignment(bool value) {
index 1346f9e..5f23afa 100644 (file)
@@ -1640,7 +1640,8 @@ class LStoreNamedGeneric: public LTemplateInstruction<0, 3, 0> {
   LOperand* object() { return inputs_[1]; }
   LOperand* value() { return inputs_[2]; }
   Handle<Object> name() const { return hydrogen()->name(); }
-  bool strict_mode() { return hydrogen()->strict_mode(); }
+  StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+  bool strict_mode() { return strict_mode_flag() == kStrictMode; }
 };
 
 
index 33bbcfb..c46f026 100644 (file)
@@ -3599,8 +3599,23 @@ void SharedFunctionInfo::set_optimization_disabled(bool disable) {
 }
 
 
-BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, strict_mode,
-               kStrictModeFunction)
+StrictModeFlag SharedFunctionInfo::strict_mode_flag() {
+  return BooleanBit::get(compiler_hints(), kStrictModeFunction)
+      ? kStrictMode : kNonStrictMode;
+}
+
+
+void SharedFunctionInfo::set_strict_mode_flag(StrictModeFlag strict_mode_flag) {
+  ASSERT(strict_mode_flag == kStrictMode ||
+         strict_mode_flag == kNonStrictMode);
+  bool value = strict_mode_flag == kStrictMode;
+  set_compiler_hints(
+      BooleanBit::set(compiler_hints(), kStrictModeFunction, value));
+}
+
+
+BOOL_GETTER(SharedFunctionInfo, compiler_hints, strict_mode,
+            kStrictModeFunction)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
 BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints,
                name_should_print_as_anonymous,
index 8db40f0..8478f74 100644 (file)
@@ -11711,7 +11711,7 @@ MaybeObject* CompilationCacheTable::PutEval(String* src,
                                             SharedFunctionInfo* value) {
   StringSharedKey key(src,
                       context->closure()->shared(),
-                      value->strict_mode() ? kStrictMode : kNonStrictMode);
+                      value->strict_mode_flag());
   Object* obj;
   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
index 87613f0..09ed775 100644 (file)
@@ -4871,7 +4871,11 @@ class SharedFunctionInfo: public HeapObject {
   DECL_BOOLEAN_ACCESSORS(optimization_disabled)
 
   // Indicates whether the function is a strict mode function.
-  DECL_BOOLEAN_ACCESSORS(strict_mode)
+  inline bool strict_mode();
+
+  // Indicates the mode of the function.
+  inline StrictModeFlag strict_mode_flag();
+  inline void set_strict_mode_flag(StrictModeFlag strict_mode_flag);
 
   // False if the function definitely does not allocate an arguments object.
   DECL_BOOLEAN_ACCESSORS(uses_arguments)
index c3ce44f..d4e507e 100644 (file)
@@ -636,6 +636,7 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
                                         bool in_global_context,
                                         StrictModeFlag strict_mode,
                                         ZoneScope* zone_scope) {
+  ASSERT(top_scope_ == NULL);
   ASSERT(target_stack_ == NULL);
   if (pre_data_ != NULL) pre_data_->Initialize();
 
@@ -651,9 +652,8 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
     scope->set_start_position(0);
     scope->set_end_position(source->length());
     LexicalScope lexical_scope(this, scope, isolate());
-    if (strict_mode == kStrictMode) {
-      top_scope_->EnableStrictMode();
-    }
+    ASSERT(top_scope_->strict_mode_flag() == kNonStrictMode);
+    top_scope_->SetStrictModeFlag(strict_mode);
     ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16);
     bool ok = true;
     int beg_loc = scanner().location().beg_pos;
@@ -724,6 +724,7 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
                                    ZoneScope* zone_scope) {
   Handle<SharedFunctionInfo> shared_info = info->shared_info();
   scanner_.Initialize(source);
+  ASSERT(top_scope_ == NULL);
   ASSERT(target_stack_ == NULL);
 
   Handle<String> name(String::cast(shared_info->name()));
@@ -742,11 +743,10 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
       scope = Scope::DeserializeScopeChain(info, scope);
     }
     LexicalScope lexical_scope(this, scope, isolate());
-
-    if (shared_info->strict_mode()) {
-      top_scope_->EnableStrictMode();
-    }
-
+    ASSERT(scope->strict_mode_flag() == kNonStrictMode ||
+           scope->strict_mode_flag() == info->strict_mode_flag());
+    ASSERT(info->strict_mode_flag() == shared_info->strict_mode_flag());
+    scope->SetStrictModeFlag(shared_info->strict_mode_flag());
     FunctionLiteral::Type type = shared_info->is_expression()
         ? (shared_info->is_anonymous()
               ? FunctionLiteral::ANONYMOUS_EXPRESSION
@@ -1193,7 +1193,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
             directive->Equals(isolate()->heap()->use_strict()) &&
             token_loc.end_pos - token_loc.beg_pos ==
               isolate()->heap()->use_strict()->length() + 2) {
-          top_scope_->EnableStrictMode();
+          top_scope_->SetStrictModeFlag(kStrictMode);
           // "use strict" is the only directive for now.
           directive_prologue = false;
         }
@@ -1593,9 +1593,6 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
   // Construct block expecting 16 statements.
   Block* body = new(zone()) Block(isolate(), labels, 16, false);
   Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE);
-  if (top_scope_->is_strict_mode()) {
-    block_scope->EnableStrictMode();
-  }
 
   // Parse the statements and collect escaping labels.
   Expect(Token::LBRACE, CHECK_OK);
@@ -1842,9 +1839,7 @@ Block* Parser::ParseVariableDeclarations(
       } else {
         // Add strict mode.
         // We may want to pass singleton to avoid Literal allocations.
-        StrictModeFlag flag = initialization_scope->is_strict_mode()
-            ? kStrictMode
-            : kNonStrictMode;
+        StrictModeFlag flag = initialization_scope->strict_mode_flag();
         arguments->Add(NewNumberLiteral(flag));
 
         // Be careful not to assign a value to the global variable if
@@ -2244,9 +2239,6 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
 
     Expect(Token::LPAREN, CHECK_OK);
     catch_scope = NewScope(top_scope_, CATCH_SCOPE);
-    if (top_scope_->is_strict_mode()) {
-      catch_scope->EnableStrictMode();
-    }
     catch_scope->set_start_position(scanner().location().beg_pos);
     name = ParseIdentifier(CHECK_OK);
 
@@ -2377,9 +2369,6 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
   // Create an in-between scope for let-bound iteration variables.
   Scope* saved_scope = top_scope_;
   Scope* for_scope = NewScope(top_scope_, BLOCK_SCOPE);
-  if (top_scope_->is_strict_mode()) {
-    for_scope->EnableStrictMode();
-  }
   top_scope_ = for_scope;
 
   Expect(Token::FOR, CHECK_OK);
@@ -3978,7 +3967,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
         scanner().SeekForward(scope->end_position() - 1);
         materialized_literal_count = entry.literal_count();
         expected_property_count = entry.property_count();
-        if (entry.strict_mode()) top_scope_->EnableStrictMode();
+        if (entry.strict_mode()) top_scope_->SetStrictModeFlag(kStrictMode);
         only_simple_this_property_assignments = false;
         this_property_assignments = isolate()->factory()->empty_fixed_array();
         Expect(Token::RBRACE, CHECK_OK);
@@ -5390,7 +5379,7 @@ bool ParserApi::Parse(CompilationInfo* info) {
       Handle<String> source = Handle<String>(String::cast(script->source()));
       result = parser.ParseProgram(source,
                                    info->is_global(),
-                                   info->StrictMode());
+                                   info->strict_mode_flag());
     }
   }
   info->SetFunction(result);
index 658693f..6a0b97a 100644 (file)
@@ -408,6 +408,16 @@ class PreParser {
 
   typedef int Arguments;
 
+  // The Strict Mode (ECMA-262 5th edition, 4.2.2).
+  enum StrictModeFlag {
+    kNonStrictMode,
+    kStrictMode,
+    // This value is never used, but is needed to prevent GCC 4.5 from failing
+    // to compile when we assert that a flag is either kNonStrictMode or
+    // kStrictMode.
+    kInvalidStrictFlag
+  };
+
   class Scope {
    public:
     Scope(Scope** variable, ScopeType type)
@@ -417,7 +427,8 @@ class PreParser {
           materialized_literal_count_(0),
           expected_properties_(0),
           with_nesting_count_(0),
-          strict_((prev_ != NULL) && prev_->is_strict()) {
+          strict_mode_flag_((prev_ != NULL) ? prev_->strict_mode_flag()
+                            : kNonStrictMode) {
       *variable = this;
     }
     ~Scope() { *variable_ = prev_; }
@@ -427,8 +438,13 @@ class PreParser {
     int expected_properties() { return expected_properties_; }
     int materialized_literal_count() { return materialized_literal_count_; }
     bool IsInsideWith() { return with_nesting_count_ != 0; }
-    bool is_strict() { return strict_; }
-    void set_strict() { strict_ = true; }
+    bool is_strict_mode() { return strict_mode_flag_ == kStrictMode; }
+    StrictModeFlag strict_mode_flag() {
+      return strict_mode_flag_;
+    }
+    void set_strict_mode_flag(StrictModeFlag strict_mode_flag) {
+      strict_mode_flag_ = strict_mode_flag;
+    }
     void EnterWith() { with_nesting_count_++; }
     void LeaveWith() { with_nesting_count_--; }
 
@@ -439,7 +455,7 @@ class PreParser {
     int materialized_literal_count_;
     int expected_properties_;
     int with_nesting_count_;
-    bool strict_;
+    StrictModeFlag strict_mode_flag_;
   };
 
   // Private constructor only used in PreParseProgram.
@@ -470,7 +486,7 @@ class PreParser {
     if (stack_overflow_) return kPreParseStackOverflow;
     if (!ok) {
       ReportUnexpectedToken(scanner_->current_token());
-    } else if (scope_->is_strict()) {
+    } else if (scope_->is_strict_mode()) {
       CheckOctalLiteral(start_position, scanner_->location().end_pos, &ok);
     }
     return kPreParseSuccess;
@@ -575,10 +591,10 @@ class PreParser {
   bool peek_any_identifier();
 
   void set_strict_mode() {
-    scope_->set_strict();
+    scope_->set_strict_mode_flag(kStrictMode);
   }
 
-  bool strict_mode() { return scope_->is_strict(); }
+  bool strict_mode() { return scope_->strict_mode_flag() == kStrictMode; }
 
   void Consume(i::Token::Value token) { Next(); }
 
index 548d30f..2f8a6df 100644 (file)
@@ -1288,10 +1288,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
     // non-deletable. However, neither SpiderMonkey nor KJS creates the
     // property as read-only, so we don't either.
     int attr = NONE;
-    if ((flags & kDeclareGlobalsEvalFlag) == 0) {
+    if (!DeclareGlobalsEvalFlag::decode(flags)) {
       attr |= DONT_DELETE;
     }
-    bool is_native = (flags & kDeclareGlobalsNativeFlag) != 0;
+    bool is_native = DeclareGlobalsNativeFlag::decode(flags);
     if (is_const_property || (is_native && is_function_declaration)) {
       attr |= READ_ONLY;
     }
@@ -1316,9 +1316,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
                                                               value,
                                                               attributes));
     } else {
-      StrictModeFlag strict_mode =
-          ((flags & kDeclareGlobalsStrictModeFlag) != 0) ? kStrictMode
-                                                         : kNonStrictMode;
+      StrictModeFlag strict_mode = DeclareGlobalsStrictModeFlag::decode(flags);
       RETURN_IF_EMPTY_HANDLE(isolate,
                              SetProperty(global,
                                          name,
index 1d7c48a..83c69e5 100644 (file)
@@ -676,11 +676,9 @@ class Runtime : public AllStatic {
 //---------------------------------------------------------------------------
 // Constants used by interface to runtime functions.
 
-enum kDeclareGlobalsFlags {
-  kDeclareGlobalsEvalFlag = 1 << 0,
-  kDeclareGlobalsStrictModeFlag = 1 << 1,
-  kDeclareGlobalsNativeFlag = 1 << 2
-};
+class DeclareGlobalsEvalFlag:       public BitField<bool,           0, 1> {};
+class DeclareGlobalsStrictModeFlag: public BitField<StrictModeFlag, 1, 1> {};
+class DeclareGlobalsNativeFlag:     public BitField<bool,           2, 1> {};
 
 } }  // namespace v8::internal
 
index 9672bd6..5e49d80 100644 (file)
@@ -200,7 +200,8 @@ void Scope::SetDefaults(ScopeType type,
   scope_contains_with_ = false;
   scope_calls_eval_ = false;
   // Inherit the strict mode from the parent scope.
-  strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_;
+  strict_mode_flag_ = (outer_scope != NULL)
+      ? outer_scope->strict_mode_flag_ : kNonStrictMode;
   outer_scope_calls_non_strict_eval_ = false;
   inner_scope_calls_eval_ = false;
   force_eager_compilation_ = false;
index 58b683b..922d8d1 100644 (file)
@@ -192,9 +192,9 @@ class Scope: public ZoneObject {
   // Inform the scope that the corresponding code contains an eval call.
   void RecordEvalCall() { if (!is_global_scope()) scope_calls_eval_ = true; }
 
-  // Enable strict mode for the scope (unless disabled by a global flag).
-  void EnableStrictMode() {
-    strict_mode_ = FLAG_strict_mode;
+  // Set the strict mode flag (unless disabled by a global flag).
+  void SetStrictModeFlag(StrictModeFlag strict_mode_flag) {
+    strict_mode_flag_ = FLAG_strict_mode ? strict_mode_flag : kNonStrictMode;
   }
 
   // Position in the source where this scope begins and ends.
@@ -241,7 +241,7 @@ class Scope: public ZoneObject {
   bool is_declaration_scope() const {
     return is_eval_scope() || is_function_scope() || is_global_scope();
   }
-  bool is_strict_mode() const { return strict_mode_; }
+  bool is_strict_mode() const { return strict_mode_flag() == kStrictMode; }
   bool is_strict_mode_eval_scope() const {
     return is_eval_scope() && is_strict_mode();
   }
@@ -269,6 +269,9 @@ class Scope: public ZoneObject {
   // The type of this scope.
   ScopeType type() const { return type_; }
 
+  // The strict mode of this scope.
+  StrictModeFlag strict_mode_flag() const { return strict_mode_flag_; }
+
   // The variable corresponding the 'this' value.
   Variable* receiver() { return receiver_; }
 
@@ -420,7 +423,7 @@ class Scope: public ZoneObject {
   // the 'eval' call site this scope is the declaration scope.
   bool scope_calls_eval_;
   // This scope is a strict mode scope.
-  bool strict_mode_;
+  StrictModeFlag strict_mode_flag_;
   // Source positions.
   int start_position_;
   int end_position_;
index eda2e55..7ddb8b8 100644 (file)
@@ -1055,7 +1055,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
       !pretenure &&
       scope()->is_function_scope() &&
       info->num_literals() == 0) {
-    FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode);
+    FastNewClosureStub stub(info->strict_mode_flag());
     __ Push(info);
     __ CallStub(&stub);
   } else {
index 5379cf9..38a8c18 100644 (file)
@@ -4034,8 +4034,7 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
   Handle<SharedFunctionInfo> shared_info = instr->shared_info();
   bool pretenure = instr->hydrogen()->pretenure();
   if (!pretenure && shared_info->num_literals() == 0) {
-    FastNewClosureStub stub(
-        shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
+    FastNewClosureStub stub(shared_info->strict_mode_flag());
     __ Push(shared_info);
     CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
   } else {
index a521c14..f3cb667 100644 (file)
@@ -126,8 +126,8 @@ class LCodeGen BASE_EMBEDDED {
   bool is_done() const { return status_ == DONE; }
   bool is_aborted() const { return status_ == ABORTED; }
 
-  int strict_mode_flag() const {
-    return info()->is_strict_mode() ? kStrictMode : kNonStrictMode;
+  StrictModeFlag strict_mode_flag() const {
+    return info()->strict_mode_flag();
   }
 
   LChunk* chunk() const { return chunk_; }
index c947406..20a6937 100644 (file)
@@ -1572,7 +1572,8 @@ class LStoreNamedGeneric: public LTemplateInstruction<0, 2, 0> {
   LOperand* object() { return inputs_[0]; }
   LOperand* value() { return inputs_[1]; }
   Handle<Object> name() const { return hydrogen()->name(); }
-  bool strict_mode() { return hydrogen()->strict_mode(); }
+  StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+  bool strict_mode() { return strict_mode_flag() == kStrictMode; }
 };
 
 
diff --git a/test/mjsunit/compiler/strict-recompile.js b/test/mjsunit/compiler/strict-recompile.js
new file mode 100644 (file)
index 0000000..96e8bca
--- /dev/null
@@ -0,0 +1,51 @@
+// 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.
+
+// Flags: --allow-natives-syntax
+
+function foo() {
+  try {
+    var o = {};
+    Object.defineProperty(o, 'x', {value: 12, writable: false});
+    o.x = 13;
+  } catch(e) {
+    return true;
+  }
+  return false;
+}
+
+assertFalse(foo());
+
+function do_eval(str) {
+  "use strict";
+  return eval(str);
+}
+
+var eval_foo = do_eval('(' + foo + ')');
+for (var i = 0; i < 5; i++) assertTrue(eval_foo());
+%OptimizeFunctionOnNextCall(eval_foo);
+assertTrue(eval_foo());