Assignment to read only properties throws in strict mode.
authormmaly@chromium.org <mmaly@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 2 Mar 2011 04:53:43 +0000 (04:53 +0000)
committermmaly@chromium.org <mmaly@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 2 Mar 2011 04:53:43 +0000 (04:53 +0000)
Review URL: http://codereview.chromium.org/6594037/

Revert "Revert "Assignment to read only properties throws in strict mode.""

This reverts commit aefcd82e1d36d458dd071ebf4777340f08aa67b1.

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

46 files changed:
src/api.cc
src/arm/codegen-arm.cc
src/arm/full-codegen-arm.cc
src/arm/ic-arm.cc
src/arm/lithium-codegen-arm.cc
src/arm/stub-cache-arm.cc
src/arm/virtual-frame-arm.cc
src/arm/virtual-frame-arm.h
src/builtins.cc
src/builtins.h
src/debug.cc
src/handles.cc
src/handles.h
src/ia32/codegen-ia32.cc
src/ia32/full-codegen-ia32.cc
src/ia32/ic-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/stub-cache-ia32.cc
src/ia32/virtual-frame-ia32.cc
src/ia32/virtual-frame-ia32.h
src/ic-inl.h
src/ic.cc
src/ic.h
src/messages.js
src/objects-inl.h
src/objects.cc
src/objects.h
src/parser.cc
src/runtime.cc
src/runtime.h
src/stub-cache.cc
src/stub-cache.h
src/x64/codegen-x64.cc
src/x64/full-codegen-x64.cc
src/x64/ic-x64.cc
src/x64/lithium-codegen-x64.cc
src/x64/stub-cache-x64.cc
src/x64/virtual-frame-x64.cc
src/x64/virtual-frame-x64.h
test/cctest/test-api.cc
test/cctest/test-compiler.cc
test/cctest/test-debug.cc
test/cctest/test-heap.cc
test/cctest/test-mark-compact.cc
test/es5conform/es5conform.status
test/mjsunit/strict-mode.js

index d718c88..b77e450 100644 (file)
@@ -2286,7 +2286,8 @@ bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
       self,
       key_obj,
       value_obj,
-      static_cast<PropertyAttributes>(attribs));
+      static_cast<PropertyAttributes>(attribs),
+      i::kNonStrictMode);
   has_pending_exception = obj.is_null();
   EXCEPTION_BAILOUT_CHECK(false);
   return true;
@@ -2711,7 +2712,8 @@ bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
       hidden_props,
       key_obj,
       value_obj,
-      static_cast<PropertyAttributes>(None));
+      static_cast<PropertyAttributes>(None),
+      i::kNonStrictMode);
   has_pending_exception = obj.is_null();
   EXCEPTION_BAILOUT_CHECK(false);
   return true;
index 5be32a2..8bb576d 100644 (file)
@@ -1938,8 +1938,9 @@ void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
   frame_->EmitPush(cp);
   frame_->EmitPush(Operand(pairs));
   frame_->EmitPush(Operand(Smi::FromInt(is_eval() ? 1 : 0)));
+  frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag())));
 
-  frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
+  frame_->CallRuntime(Runtime::kDeclareGlobals, 4);
   // The result is discarded.
 }
 
@@ -3287,7 +3288,8 @@ void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
       // context slot followed by initialization.
       frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
     } else {
-      frame_->CallRuntime(Runtime::kStoreContextSlot, 3);
+      frame_->EmitPush(Operand(Smi::FromInt(strict_mode_flag())));
+      frame_->CallRuntime(Runtime::kStoreContextSlot, 4);
     }
     // Storing a variable must keep the (new) value on the expression
     // stack. This is necessary for compiling assignment expressions.
@@ -3637,7 +3639,8 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
         Load(key);
         Load(value);
         if (property->emit_store()) {
-          frame_->CallRuntime(Runtime::kSetProperty, 3);
+          frame_->EmitPush(Operand(Smi::FromInt(NONE)));  // PropertyAttributes
+          frame_->CallRuntime(Runtime::kSetProperty, 4);
         } else {
           frame_->Drop(3);
         }
@@ -6674,8 +6677,12 @@ class DeferredReferenceSetKeyedValue: public DeferredCode {
  public:
   DeferredReferenceSetKeyedValue(Register value,
                                  Register key,
-                                 Register receiver)
-      : value_(value), key_(key), receiver_(receiver) {
+                                 Register receiver,
+                                 StrictModeFlag strict_mode)
+      : value_(value),
+        key_(key),
+        receiver_(receiver),
+        strict_mode_(strict_mode) {
     set_comment("[ DeferredReferenceSetKeyedValue");
   }
 
@@ -6685,6 +6692,7 @@ class DeferredReferenceSetKeyedValue: public DeferredCode {
   Register value_;
   Register key_;
   Register receiver_;
+  StrictModeFlag strict_mode_;
 };
 
 
@@ -6706,7 +6714,9 @@ void DeferredReferenceSetKeyedValue::Generate() {
   { Assembler::BlockConstPoolScope block_const_pool(masm_);
     // Call keyed store IC. It has the arguments value, key and receiver in r0,
     // r1 and r2.
-    Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+    Handle<Code> ic(Builtins::builtin(
+        (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
+                                      : Builtins::KeyedStoreIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET);
     // The call must be followed by a nop instruction to indicate that the
     // keyed store has been inlined.
@@ -6724,8 +6734,12 @@ class DeferredReferenceSetNamedValue: public DeferredCode {
  public:
   DeferredReferenceSetNamedValue(Register value,
                                  Register receiver,
-                                 Handle<String> name)
-      : value_(value), receiver_(receiver), name_(name) {
+                                 Handle<String> name,
+                                 StrictModeFlag strict_mode)
+      : value_(value),
+        receiver_(receiver),
+        name_(name),
+        strict_mode_(strict_mode) {
     set_comment("[ DeferredReferenceSetNamedValue");
   }
 
@@ -6735,6 +6749,7 @@ class DeferredReferenceSetNamedValue: public DeferredCode {
   Register value_;
   Register receiver_;
   Handle<String> name_;
+  StrictModeFlag strict_mode_;
 };
 
 
@@ -6754,7 +6769,9 @@ void DeferredReferenceSetNamedValue::Generate() {
   { Assembler::BlockConstPoolScope block_const_pool(masm_);
     // Call keyed store IC. It has the arguments value, key and receiver in r0,
     // r1 and r2.
-    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+    Handle<Code> ic(Builtins::builtin(
+        (strict_mode_ == kStrictMode) ? Builtins::StoreIC_Initialize_Strict
+                                      : Builtins::StoreIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET);
     // The call must be followed by a nop instruction to indicate that the
     // named store has been inlined.
@@ -6943,7 +6960,8 @@ void CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
     Register receiver = r1;
 
     DeferredReferenceSetNamedValue* deferred =
-        new DeferredReferenceSetNamedValue(value, receiver, name);
+        new DeferredReferenceSetNamedValue(
+          value, receiver, name, strict_mode_flag());
 
     // Check that the receiver is a heap object.
     __ tst(receiver, Operand(kSmiTagMask));
@@ -7129,7 +7147,8 @@ void CodeGenerator::EmitKeyedStore(StaticType* key_type,
 
     // The deferred code expects value, key and receiver in registers.
     DeferredReferenceSetKeyedValue* deferred =
-        new DeferredReferenceSetKeyedValue(value, key, receiver);
+        new DeferredReferenceSetKeyedValue(
+          value, key, receiver, strict_mode_flag());
 
     // Check that the value is a smi. As this inlined code does not set the
     // write barrier it is only possible to store smi values.
@@ -7214,7 +7233,7 @@ void CodeGenerator::EmitKeyedStore(StaticType* key_type,
 
     deferred->BindExit();
   } else {
-    frame()->CallKeyedStoreIC();
+    frame()->CallKeyedStoreIC(strict_mode_flag());
   }
 }
 
index 337969b..7a47644 100644 (file)
@@ -776,7 +776,9 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
              prop->key()->AsLiteral()->handle()->IsSmi());
       __ mov(r1, Operand(prop->key()->AsLiteral()->handle()));
 
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(is_strict()
+          ? Builtins::KeyedStoreIC_Initialize_Strict
+          : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       // Value in r0 is ignored (declarations are statements).
     }
@@ -792,10 +794,11 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
   // Call the runtime to declare the globals.
   // The context is the first argument.
-  __ mov(r1, Operand(pairs));
-  __ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
-  __ Push(cp, r1, r0);
-  __ CallRuntime(Runtime::kDeclareGlobals, 3);
+  __ mov(r2, Operand(pairs));
+  __ mov(r1, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
+  __ mov(r0, Operand(Smi::FromInt(strict_mode_flag())));
+  __ Push(cp, r2, r1, r0);
+  __ CallRuntime(Runtime::kDeclareGlobals, 4);
   // Return value is ignored.
 }
 
@@ -1439,7 +1442,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
         VisitForStackValue(key);
         VisitForStackValue(value);
         if (property->emit_store()) {
-          __ CallRuntime(Runtime::kSetProperty, 3);
+          __ mov(r0, Operand(Smi::FromInt(NONE)));  // PropertyAttributes
+          __ push(r0);
+          __ CallRuntime(Runtime::kSetProperty, 4);
         } else {
           __ Drop(3);
         }
@@ -1820,7 +1825,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
       __ mov(r1, r0);
       __ pop(r0);  // Restore value.
       __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::StoreIC_Initialize_Strict
+                      : Builtins::StoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -1841,7 +1848,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
         __ pop(r2);
       }
       __ pop(r0);  // Restore value.
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                      : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -1865,9 +1874,9 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
     // r2, and the global object in r1.
     __ mov(r2, Operand(var->name()));
     __ ldr(r1, GlobalObjectOperand());
-    Handle<Code> ic(Builtins::builtin(is_strict()
-        ? Builtins::StoreIC_Initialize_Strict
-        : Builtins::StoreIC_Initialize));
+    Handle<Code> ic(Builtins::builtin(
+        is_strict() ? Builtins::StoreIC_Initialize_Strict
+                    : Builtins::StoreIC_Initialize));
     EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
 
   } else if (op == Token::INIT_CONST) {
@@ -1936,9 +1945,10 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
       case Slot::LOOKUP:
         // Call the runtime for the assignment.
         __ push(r0);  // Value.
-        __ mov(r0, Operand(slot->var()->name()));
-        __ Push(cp, r0);  // Context and name.
-        __ CallRuntime(Runtime::kStoreContextSlot, 3);
+        __ mov(r1, Operand(slot->var()->name()));
+        __ mov(r0, Operand(Smi::FromInt(strict_mode_flag())));
+        __ Push(cp, r1, r0);  // Context, name, strict mode.
+        __ CallRuntime(Runtime::kStoreContextSlot, 4);
         break;
     }
   }
@@ -1973,7 +1983,9 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
     __ pop(r1);
   }
 
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      is_strict() ? Builtins::StoreIC_Initialize_Strict
+                  : Builtins::StoreIC_Initialize));
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -2017,7 +2029,9 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
     __ pop(r2);
   }
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                  : Builtins::KeyedStoreIC_Initialize));
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -3791,7 +3805,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
     case NAMED_PROPERTY: {
       __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
       __ pop(r1);
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::StoreIC_Initialize_Strict
+                      : Builtins::StoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -3806,7 +3822,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
     case KEYED_PROPERTY: {
       __ pop(r1);  // Key.
       __ pop(r2);  // Receiver.
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                      : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
index 6c7aa06..0fc6818 100644 (file)
@@ -1400,7 +1400,8 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
 }
 
 
-void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
+                                              StrictModeFlag strict_mode) {
   // ---------- S t a t e --------------
   //  -- r0     : value
   //  -- r1     : key
@@ -1411,11 +1412,16 @@ void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
   // Push receiver, key and value for runtime call.
   __ Push(r2, r1, r0);
 
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ mov(r1, Operand(Smi::FromInt(NONE)));          // PropertyAttributes
+  __ mov(r0, Operand(Smi::FromInt(strict_mode)));   // Strict mode.
+  __ Push(r1, r0);
+
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 }
 
 
-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
+                                   StrictModeFlag strict_mode) {
   // ---------- S t a t e --------------
   //  -- r0     : value
   //  -- r1     : key
@@ -1470,7 +1476,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
   // r0: value.
   // r1: key.
   // r2: receiver.
-  GenerateRuntimeSetProperty(masm);
+  GenerateRuntimeSetProperty(masm, strict_mode);
 
   // Check whether the elements is a pixel array.
   // r4: elements map.
@@ -1540,7 +1546,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
 
 
 void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
-                                  Code::ExtraICState extra_ic_state) {
+                                  StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- r0    : value
   //  -- r1    : receiver
@@ -1552,7 +1558,7 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
   Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
                                          NOT_IN_LOOP,
                                          MONOMORPHIC,
-                                         extra_ic_state);
+                                         strict_mode);
   StubCache::GenerateProbe(masm, flags, r1, r2, r3, r4, r5);
 
   // Cache miss: Jump to runtime.
@@ -1646,7 +1652,8 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) {
 }
 
 
-void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) {
+void StoreIC::GenerateGlobalProxy(MacroAssembler* masm,
+                                  StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- r0    : value
   //  -- r1    : receiver
@@ -1656,8 +1663,12 @@ void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) {
 
   __ Push(r1, r2, r0);
 
+  __ mov(r1, Operand(Smi::FromInt(NONE)));  // PropertyAttributes
+  __ mov(r0, Operand(Smi::FromInt(strict_mode)));
+  __ Push(r1, r0);
+
   // Do tail-call to runtime routine.
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 }
 
 
index a2ee3e2..6d50a9c 100644 (file)
@@ -2860,9 +2860,9 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
 
   // Name is always in r2.
   __ mov(r2, Operand(instr->name()));
-  Handle<Code> ic(Builtins::builtin(info_->is_strict()
-      ? Builtins::StoreIC_Initialize_Strict
-      : Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      info_->is_strict() ? Builtins::StoreIC_Initialize_Strict
+                         : Builtins::StoreIC_Initialize));
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2904,7 +2904,9 @@ void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
   ASSERT(ToRegister(instr->key()).is(r1));
   ASSERT(ToRegister(instr->value()).is(r0));
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                         : Builtins::KeyedStoreIC_Initialize));
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
index e250112..60a11f3 100644 (file)
@@ -2671,10 +2671,13 @@ MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
 
   __ Push(r1, r2, r0);  // Receiver, name, value.
 
+  __ mov(r0, Operand(Smi::FromInt(strict_mode_)));
+  __ push(r0);  // strict mode
+
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
       ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
-  __ TailCallExternalReference(store_ic_property, 3, 1);
+  __ TailCallExternalReference(store_ic_property, 4, 1);
 
   // Handle store cache miss.
   __ bind(&miss);
@@ -4056,7 +4059,12 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
   // Push receiver, key and value for runtime call.
   __ Push(r2, r1, r0);
 
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ mov(r1, Operand(Smi::FromInt(NONE)));  // PropertyAttributes
+  __ mov(r0, Operand(Smi::FromInt(
+      Code::ExtractExtraICStateFromFlags(flags) & kStrictMode)));
+  __ Push(r1, r0);
+
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 
   return GetCode(flags);
 }
index b4b518c..544e405 100644 (file)
@@ -332,9 +332,9 @@ void VirtualFrame::CallLoadIC(Handle<String> name, RelocInfo::Mode mode) {
 void VirtualFrame::CallStoreIC(Handle<String> name,
                                bool is_contextual,
                                StrictModeFlag strict_mode) {
-  Handle<Code> ic(Builtins::builtin(strict_mode == kStrictMode
-      ? Builtins::StoreIC_Initialize_Strict
-      : Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode == kStrictMode) ? Builtins::StoreIC_Initialize_Strict
+                                   : Builtins::StoreIC_Initialize));
   PopToR0();
   RelocInfo::Mode mode;
   if (is_contextual) {
@@ -359,8 +359,10 @@ void VirtualFrame::CallKeyedLoadIC() {
 }
 
 
-void VirtualFrame::CallKeyedStoreIC() {
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+void VirtualFrame::CallKeyedStoreIC(StrictModeFlag strict_mode) {
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
+                                   : Builtins::KeyedStoreIC_Initialize));
   PopToR1R0();
   SpillAll();
   EmitPop(r2);
index b6e794a..76470bd 100644 (file)
@@ -303,7 +303,7 @@ class VirtualFrame : public ZoneObject {
 
   // Call keyed store IC. Value, key and receiver are on the stack. All three
   // are consumed. Result is returned in r0.
-  void CallKeyedStoreIC();
+  void CallKeyedStoreIC(StrictModeFlag strict_mode);
 
   // Call into an IC stub given the number of arguments it removes
   // from the stack.  Register arguments to the IC stub are implicit,
index 8fdc1b1..01e8deb 100644 (file)
@@ -1328,12 +1328,12 @@ static void Generate_StoreIC_Normal_Strict(MacroAssembler* masm) {
 
 
 static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
-  StoreIC::GenerateMegamorphic(masm, StoreIC::kStoreICNonStrict);
+  StoreIC::GenerateMegamorphic(masm, kNonStrictMode);
 }
 
 
 static void Generate_StoreIC_Megamorphic_Strict(MacroAssembler* masm) {
-  StoreIC::GenerateMegamorphic(masm, StoreIC::kStoreICStrict);
+  StoreIC::GenerateMegamorphic(masm, kStrictMode);
 }
 
 
@@ -1348,17 +1348,22 @@ static void Generate_StoreIC_ArrayLength_Strict(MacroAssembler* masm) {
 
 
 static void Generate_StoreIC_GlobalProxy(MacroAssembler* masm) {
-  StoreIC::GenerateGlobalProxy(masm);
+  StoreIC::GenerateGlobalProxy(masm, kNonStrictMode);
 }
 
 
 static void Generate_StoreIC_GlobalProxy_Strict(MacroAssembler* masm) {
-  StoreIC::GenerateGlobalProxy(masm);
+  StoreIC::GenerateGlobalProxy(masm, kStrictMode);
 }
 
 
 static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
-  KeyedStoreIC::GenerateGeneric(masm);
+  KeyedStoreIC::GenerateGeneric(masm, kNonStrictMode);
+}
+
+
+static void Generate_KeyedStoreIC_Generic_Strict(MacroAssembler* masm) {
+  KeyedStoreIC::GenerateGeneric(masm, kStrictMode);
 }
 
 
@@ -1372,6 +1377,11 @@ static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
 }
 
 
+static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) {
+  KeyedStoreIC::GenerateInitialize(masm);
+}
+
+
 #ifdef ENABLE_DEBUGGER_SUPPORT
 static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
   Debug::GenerateLoadICDebugBreak(masm);
index 2733410..5ea4665 100644 (file)
@@ -62,111 +62,116 @@ enum BuiltinExtraArguments {
 
 
 // Define list of builtins implemented in assembly.
-#define BUILTIN_LIST_A(V)                                                 \
-  V(ArgumentsAdaptorTrampoline, BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(JSConstructCall,            BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(JSConstructStubCountdown,   BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(JSConstructStubGeneric,     BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(JSConstructStubApi,         BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(JSEntryTrampoline,          BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(JSConstructEntryTrampoline, BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(LazyCompile,                BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(LazyRecompile,              BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(NotifyDeoptimized,          BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(NotifyLazyDeoptimized,      BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(NotifyOSR,                  BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  V(LoadIC_Miss,                BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(KeyedLoadIC_Miss,           BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(StoreIC_Miss,               BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(KeyedStoreIC_Miss,          BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  V(LoadIC_Initialize,          LOAD_IC, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(LoadIC_PreMonomorphic,      LOAD_IC, PREMONOMORPHIC,                  \
-                                Code::kNoExtraICState)                    \
-  V(LoadIC_Normal,              LOAD_IC, MONOMORPHIC,                     \
-                                Code::kNoExtraICState)                    \
-  V(LoadIC_ArrayLength,         LOAD_IC, MONOMORPHIC,                     \
-                                Code::kNoExtraICState)                    \
-  V(LoadIC_StringLength,        LOAD_IC, MONOMORPHIC,                     \
-                                Code::kNoExtraICState)                    \
-  V(LoadIC_StringWrapperLength, LOAD_IC, MONOMORPHIC,                     \
-                                Code::kNoExtraICState)                    \
-  V(LoadIC_FunctionPrototype,   LOAD_IC, MONOMORPHIC,                     \
-                                Code::kNoExtraICState)                    \
-  V(LoadIC_Megamorphic,         LOAD_IC, MEGAMORPHIC,                     \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  V(KeyedLoadIC_Initialize,     KEYED_LOAD_IC, UNINITIALIZED,             \
-                                Code::kNoExtraICState)                    \
-  V(KeyedLoadIC_PreMonomorphic, KEYED_LOAD_IC, PREMONOMORPHIC,            \
-                                Code::kNoExtraICState)                    \
-  V(KeyedLoadIC_Generic,        KEYED_LOAD_IC, MEGAMORPHIC,               \
-                                Code::kNoExtraICState)                    \
-  V(KeyedLoadIC_String,         KEYED_LOAD_IC, MEGAMORPHIC,               \
-                                Code::kNoExtraICState)                    \
-  V(KeyedLoadIC_IndexedInterceptor,         KEYED_LOAD_IC, MEGAMORPHIC,   \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  V(StoreIC_Initialize,         STORE_IC, UNINITIALIZED,                  \
-                                Code::kNoExtraICState)                    \
-  V(StoreIC_ArrayLength,        STORE_IC, MONOMORPHIC,                    \
-                                Code::kNoExtraICState)                    \
-  V(StoreIC_Normal,             STORE_IC, MONOMORPHIC,                    \
-                                Code::kNoExtraICState)                    \
-  V(StoreIC_Megamorphic,        STORE_IC, MEGAMORPHIC,                    \
-                                Code::kNoExtraICState)                    \
-  V(StoreIC_GlobalProxy,        STORE_IC, MEGAMORPHIC,                    \
-                                Code::kNoExtraICState)                    \
-  V(StoreIC_Initialize_Strict,  STORE_IC, UNINITIALIZED,                  \
-                                StoreIC::kStoreICStrict)                  \
-  V(StoreIC_ArrayLength_Strict, STORE_IC, MONOMORPHIC,                    \
-                                StoreIC::kStoreICStrict)                  \
-  V(StoreIC_Normal_Strict,      STORE_IC, MONOMORPHIC,                    \
-                                StoreIC::kStoreICStrict)                  \
-  V(StoreIC_Megamorphic_Strict, STORE_IC, MEGAMORPHIC,                    \
-                                StoreIC::kStoreICStrict)                  \
-  V(StoreIC_GlobalProxy_Strict, STORE_IC, MEGAMORPHIC,                    \
-                                StoreIC::kStoreICStrict)                  \
-                                                                          \
-  V(KeyedStoreIC_Initialize,    KEYED_STORE_IC, UNINITIALIZED,            \
-                                Code::kNoExtraICState)                    \
-  V(KeyedStoreIC_Generic,       KEYED_STORE_IC, MEGAMORPHIC,              \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  /* Uses KeyedLoadIC_Initialize; must be after in list. */               \
-  V(FunctionCall,               BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(FunctionApply,              BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  V(ArrayCode,                  BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-  V(ArrayConstructCode,         BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  V(StringConstructCode,        BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)                    \
-                                                                          \
-  V(OnStackReplacement,         BUILTIN, UNINITIALIZED,                   \
-                                Code::kNoExtraICState)
+#define BUILTIN_LIST_A(V)                                           \
+  V(ArgumentsAdaptorTrampoline,     BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(JSConstructCall,                BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(JSConstructStubCountdown,       BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(JSConstructStubGeneric,         BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(JSConstructStubApi,             BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(JSEntryTrampoline,              BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(JSConstructEntryTrampoline,     BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(LazyCompile,                    BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(LazyRecompile,                  BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(NotifyDeoptimized,              BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(NotifyLazyDeoptimized,          BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(NotifyOSR,                      BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(LoadIC_Miss,                    BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(KeyedLoadIC_Miss,               BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(StoreIC_Miss,                   BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(KeyedStoreIC_Miss,              BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(LoadIC_Initialize,              LOAD_IC, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(LoadIC_PreMonomorphic,          LOAD_IC, PREMONOMORPHIC,        \
+                                    Code::kNoExtraICState)          \
+  V(LoadIC_Normal,                  LOAD_IC, MONOMORPHIC,           \
+                                    Code::kNoExtraICState)          \
+  V(LoadIC_ArrayLength,             LOAD_IC, MONOMORPHIC,           \
+                                    Code::kNoExtraICState)          \
+  V(LoadIC_StringLength,            LOAD_IC, MONOMORPHIC,           \
+                                    Code::kNoExtraICState)          \
+  V(LoadIC_StringWrapperLength,     LOAD_IC, MONOMORPHIC,           \
+                                    Code::kNoExtraICState)          \
+  V(LoadIC_FunctionPrototype,       LOAD_IC, MONOMORPHIC,           \
+                                    Code::kNoExtraICState)          \
+  V(LoadIC_Megamorphic,             LOAD_IC, MEGAMORPHIC,           \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(KeyedLoadIC_Initialize,         KEYED_LOAD_IC, UNINITIALIZED,   \
+                                    Code::kNoExtraICState)          \
+  V(KeyedLoadIC_PreMonomorphic,     KEYED_LOAD_IC, PREMONOMORPHIC,  \
+                                    Code::kNoExtraICState)          \
+  V(KeyedLoadIC_Generic,            KEYED_LOAD_IC, MEGAMORPHIC,     \
+                                    Code::kNoExtraICState)          \
+  V(KeyedLoadIC_String,             KEYED_LOAD_IC, MEGAMORPHIC,     \
+                                    Code::kNoExtraICState)          \
+  V(KeyedLoadIC_IndexedInterceptor, KEYED_LOAD_IC, MEGAMORPHIC,     \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(StoreIC_Initialize,             STORE_IC, UNINITIALIZED,        \
+                                    Code::kNoExtraICState)          \
+  V(StoreIC_ArrayLength,            STORE_IC, MONOMORPHIC,          \
+                                    Code::kNoExtraICState)          \
+  V(StoreIC_Normal,                 STORE_IC, MONOMORPHIC,          \
+                                    Code::kNoExtraICState)          \
+  V(StoreIC_Megamorphic,            STORE_IC, MEGAMORPHIC,          \
+                                    Code::kNoExtraICState)          \
+  V(StoreIC_GlobalProxy,            STORE_IC, MEGAMORPHIC,          \
+                                    Code::kNoExtraICState)          \
+  V(StoreIC_Initialize_Strict,      STORE_IC, UNINITIALIZED,        \
+                                    kStrictMode)                    \
+  V(StoreIC_ArrayLength_Strict,     STORE_IC, MONOMORPHIC,          \
+                                    kStrictMode)                    \
+  V(StoreIC_Normal_Strict,          STORE_IC, MONOMORPHIC,          \
+                                    kStrictMode)                    \
+  V(StoreIC_Megamorphic_Strict,     STORE_IC, MEGAMORPHIC,          \
+                                    kStrictMode)                    \
+  V(StoreIC_GlobalProxy_Strict,     STORE_IC, MEGAMORPHIC,          \
+                                    kStrictMode)                    \
+                                                                    \
+  V(KeyedStoreIC_Initialize,        KEYED_STORE_IC, UNINITIALIZED,  \
+                                    Code::kNoExtraICState)          \
+  V(KeyedStoreIC_Generic,           KEYED_STORE_IC, MEGAMORPHIC,    \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(KeyedStoreIC_Initialize_Strict, KEYED_STORE_IC, UNINITIALIZED,  \
+                                    kStrictMode)                    \
+  V(KeyedStoreIC_Generic_Strict,    KEYED_STORE_IC, MEGAMORPHIC,    \
+                                    kStrictMode)                    \
+                                                                    \
+  /* Uses KeyedLoadIC_Initialize; must be after in list. */         \
+  V(FunctionCall,                   BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(FunctionApply,                  BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(ArrayCode,                      BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+  V(ArrayConstructCode,             BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(StringConstructCode,            BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)          \
+                                                                    \
+  V(OnStackReplacement,             BUILTIN, UNINITIALIZED,         \
+                                    Code::kNoExtraICState)
 
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
index d8201a1..c473941 100644 (file)
@@ -836,7 +836,8 @@ bool Debug::Load() {
   Handle<String> key = Factory::LookupAsciiSymbol("builtins");
   Handle<GlobalObject> global = Handle<GlobalObject>(context->global());
   RETURN_IF_EMPTY_HANDLE_VALUE(
-      SetProperty(global, key, Handle<Object>(global->builtins()), NONE),
+      SetProperty(global, key, Handle<Object>(global->builtins()),
+                  NONE, kNonStrictMode),
       false);
 
   // Compile the JavaScript for the debugger in the debugger context.
index 8b2f95b..05c81bb 100644 (file)
@@ -242,17 +242,21 @@ Handle<Object> SetPrototype(Handle<JSFunction> function,
 Handle<Object> SetProperty(Handle<JSObject> object,
                            Handle<String> key,
                            Handle<Object> value,
-                           PropertyAttributes attributes) {
-  CALL_HEAP_FUNCTION(object->SetProperty(*key, *value, attributes), Object);
+                           PropertyAttributes attributes,
+                           StrictModeFlag strict) {
+  CALL_HEAP_FUNCTION(object->SetProperty(*key, *value, attributes, strict),
+                     Object);
 }
 
 
 Handle<Object> SetProperty(Handle<Object> object,
                            Handle<Object> key,
                            Handle<Object> value,
-                           PropertyAttributes attributes) {
+                           PropertyAttributes attributes,
+                           StrictModeFlag strict) {
   CALL_HEAP_FUNCTION(
-      Runtime::SetObjectProperty(object, key, value, attributes), Object);
+      Runtime::SetObjectProperty(object, key, value, attributes, strict),
+      Object);
 }
 
 
@@ -304,10 +308,12 @@ void SetLocalPropertyNoThrow(Handle<JSObject> object,
 Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
                                           Handle<String> key,
                                           Handle<Object> value,
-                                          PropertyAttributes attributes) {
+                                          PropertyAttributes attributes,
+                                          StrictModeFlag strict) {
   CALL_HEAP_FUNCTION(object->SetPropertyWithInterceptor(*key,
                                                         *value,
-                                                        attributes),
+                                                        attributes,
+                                                        strict),
                      Object);
 }
 
index 50b2d3f..9d3588b 100644 (file)
@@ -223,12 +223,14 @@ Handle<String> FlattenGetString(Handle<String> str);
 Handle<Object> SetProperty(Handle<JSObject> object,
                            Handle<String> key,
                            Handle<Object> value,
-                           PropertyAttributes attributes);
+                           PropertyAttributes attributes,
+                           StrictModeFlag strict);
 
 Handle<Object> SetProperty(Handle<Object> object,
                            Handle<Object> key,
                            Handle<Object> value,
-                           PropertyAttributes attributes);
+                           PropertyAttributes attributes,
+                           StrictModeFlag strict);
 
 Handle<Object> ForceSetProperty(Handle<JSObject> object,
                                 Handle<Object> key,
@@ -259,7 +261,8 @@ void SetLocalPropertyNoThrow(Handle<JSObject> object,
 Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
                                           Handle<String> key,
                                           Handle<Object> value,
-                                          PropertyAttributes attributes);
+                                          PropertyAttributes attributes,
+                                          StrictModeFlag strict);
 
 Handle<Object> SetElement(Handle<JSObject> object,
                           uint32_t index,
index 8f15860..3a2753d 100644 (file)
@@ -3526,7 +3526,8 @@ void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
   frame_->EmitPush(esi);  // The context is the first argument.
   frame_->EmitPush(Immediate(pairs));
   frame_->EmitPush(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
-  Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
+  frame_->EmitPush(Immediate(Smi::FromInt(strict_mode_flag())));
+  Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 4);
   // Return value is ignored.
 }
 
@@ -5259,7 +5260,8 @@ void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
       // by initialization.
       value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
     } else {
-      value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3);
+      frame_->Push(Smi::FromInt(strict_mode_flag()));
+      value = frame_->CallRuntime(Runtime::kStoreContextSlot, 4);
     }
     // Storing a variable must keep the (new) value on the expression
     // stack. This is necessary for compiling chained assignment
@@ -5618,8 +5620,9 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
           Load(property->key());
           Load(property->value());
           if (property->emit_store()) {
+            frame_->Push(Smi::FromInt(NONE));   // PropertyAttributes
             // Ignore the result.
-            Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3);
+            Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 4);
           } else {
             frame_->Drop(3);
           }
@@ -9470,11 +9473,13 @@ class DeferredReferenceSetKeyedValue: public DeferredCode {
   DeferredReferenceSetKeyedValue(Register value,
                                  Register key,
                                  Register receiver,
-                                 Register scratch)
+                                 Register scratch,
+                                 StrictModeFlag strict_mode)
       : value_(value),
         key_(key),
         receiver_(receiver),
-        scratch_(scratch) {
+        scratch_(scratch),
+        strict_mode_(strict_mode) {
     set_comment("[ DeferredReferenceSetKeyedValue");
   }
 
@@ -9488,6 +9493,7 @@ class DeferredReferenceSetKeyedValue: public DeferredCode {
   Register receiver_;
   Register scratch_;
   Label patch_site_;
+  StrictModeFlag strict_mode_;
 };
 
 
@@ -9546,7 +9552,9 @@ void DeferredReferenceSetKeyedValue::Generate() {
   }
 
   // Call the IC stub.
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
+                                    : Builtins::KeyedStoreIC_Initialize));
   __ call(ic, RelocInfo::CODE_TARGET);
   // The delta from the start of the map-compare instruction to the
   // test instruction.  We use masm_-> directly here instead of the
@@ -9908,7 +9916,8 @@ Result CodeGenerator::EmitKeyedStore(StaticType* key_type) {
         new DeferredReferenceSetKeyedValue(result.reg(),
                                            key.reg(),
                                            receiver.reg(),
-                                           tmp.reg());
+                                           tmp.reg(),
+                                           strict_mode_flag());
 
     // Check that the receiver is not a smi.
     __ test(receiver.reg(), Immediate(kSmiTagMask));
@@ -9963,7 +9972,7 @@ Result CodeGenerator::EmitKeyedStore(StaticType* key_type) {
 
     deferred->BindExit();
   } else {
-    result = frame()->CallKeyedStoreIC();
+    result = frame()->CallKeyedStoreIC(strict_mode_flag());
     // Make sure that we do not have a test instruction after the
     // call.  A test instruction after the call is used to
     // indicate that we have generated an inline version of the
index f4a92f6..67e0e8f 100644 (file)
@@ -724,7 +724,9 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
              prop->key()->AsLiteral()->handle()->IsSmi());
       __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
 
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(is_strict()
+          ? Builtins::KeyedStoreIC_Initialize_Strict
+          : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
     }
   }
@@ -741,7 +743,8 @@ void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
   __ push(esi);  // The context is the first argument.
   __ push(Immediate(pairs));
   __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
-  __ CallRuntime(Runtime::kDeclareGlobals, 3);
+  __ push(Immediate(Smi::FromInt(strict_mode_flag())));
+  __ CallRuntime(Runtime::kDeclareGlobals, 4);
   // Return value is ignored.
 }
 
@@ -1363,7 +1366,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
             VisitForAccumulatorValue(value);
             __ mov(ecx, Immediate(key->handle()));
             __ mov(edx, Operand(esp, 0));
-            Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+            Handle<Code> ic(Builtins::builtin(
+                is_strict() ? Builtins::StoreIC_Initialize_Strict
+                            : Builtins::StoreIC_Initialize));
             EmitCallIC(ic, RelocInfo::CODE_TARGET);
             PrepareForBailoutForId(key->id(), NO_REGISTERS);
           } else {
@@ -1377,7 +1382,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
         VisitForStackValue(key);
         VisitForStackValue(value);
         if (property->emit_store()) {
-          __ CallRuntime(Runtime::kSetProperty, 3);
+          __ push(Immediate(Smi::FromInt(NONE)));  // PropertyAttributes
+          __ CallRuntime(Runtime::kSetProperty, 4);
         } else {
           __ Drop(3);
         }
@@ -1752,7 +1758,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
       __ mov(edx, eax);
       __ pop(eax);  // Restore value.
       __ mov(ecx, prop->key()->AsLiteral()->handle());
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::StoreIC_Initialize_Strict
+                      : Builtins::StoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -1773,7 +1781,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
         __ pop(edx);
       }
       __ pop(eax);  // Restore value.
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                      : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -1868,7 +1878,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
         __ push(eax);  // Value.
         __ push(esi);  // Context.
         __ push(Immediate(var->name()));
-        __ CallRuntime(Runtime::kStoreContextSlot, 3);
+        __ push(Immediate(Smi::FromInt(strict_mode_flag())));
+        __ CallRuntime(Runtime::kStoreContextSlot, 4);
         break;
     }
   }
@@ -1899,7 +1910,9 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
   } else {
     __ pop(edx);
   }
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      is_strict() ? Builtins::StoreIC_Initialize_Strict
+                  : Builtins::StoreIC_Initialize));
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -1937,7 +1950,9 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
   }
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                  : Builtins::KeyedStoreIC_Initialize));
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -3822,7 +3837,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
     case NAMED_PROPERTY: {
       __ mov(ecx, prop->key()->AsLiteral()->handle());
       __ pop(edx);
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::StoreIC_Initialize_Strict
+                      : Builtins::StoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -3837,7 +3854,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
     case KEYED_PROPERTY: {
       __ pop(ecx);
       __ pop(edx);
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                      : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
index 73cd60d..6b9e749 100644 (file)
@@ -761,7 +761,8 @@ void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
 }
 
 
-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
+                                   StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : key
@@ -801,7 +802,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
 
   // Slow case: call runtime.
   __ bind(&slow);
-  GenerateRuntimeSetProperty(masm);
+  GenerateRuntimeSetProperty(masm, strict_mode);
 
   // Check whether the elements is a pixel array.
   __ bind(&check_pixel_array);
@@ -1488,7 +1489,7 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
 
 
 void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
-                                  Code::ExtraICState extra_ic_state) {
+                                  StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : name
@@ -1499,7 +1500,7 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
   Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
                                          NOT_IN_LOOP,
                                          MONOMORPHIC,
-                                         extra_ic_state);
+                                         strict_mode);
   StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, no_reg);
 
   // Cache miss: Jump to runtime.
@@ -1617,7 +1618,8 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) {
 }
 
 
-void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) {
+void StoreIC::GenerateGlobalProxy(MacroAssembler* masm,
+                                  StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : name
@@ -1628,14 +1630,17 @@ void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) {
   __ push(edx);
   __ push(ecx);
   __ push(eax);
-  __ push(ebx);
+  __ push(Immediate(Smi::FromInt(NONE)));  // PropertyAttributes
+  __ push(Immediate(Smi::FromInt(strict_mode)));
+  __ push(ebx);  // return address
 
   // Do tail-call to runtime routine.
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 }
 
 
-void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
+                                              StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- eax    : value
   //  -- ecx    : key
@@ -1647,10 +1652,12 @@ void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
   __ push(edx);
   __ push(ecx);
   __ push(eax);
-  __ push(ebx);
+  __ push(Immediate(Smi::FromInt(NONE)));         // PropertyAttributes
+  __ push(Immediate(Smi::FromInt(strict_mode)));  // Strict mode.
+  __ push(ebx);   // return address
 
   // Do tail-call to runtime routine.
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 }
 
 
index 8f3ed06..0b345d3 100644 (file)
@@ -2782,7 +2782,9 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
   ASSERT(ToRegister(instr->value()).is(eax));
 
   __ mov(ecx, instr->name());
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      info_->is_strict() ? Builtins::StoreIC_Initialize_Strict
+                         : Builtins::StoreIC_Initialize));
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2850,7 +2852,9 @@ void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
   ASSERT(ToRegister(instr->key()).is(ecx));
   ASSERT(ToRegister(instr->value()).is(eax));
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                         : Builtins::KeyedStoreIC_Initialize));
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
index 51cc46a..633097a 100644 (file)
@@ -2552,12 +2552,13 @@ MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
   __ push(edx);  // receiver
   __ push(ecx);  // name
   __ push(eax);  // value
+  __ push(Immediate(Smi::FromInt(strict_mode_)));
   __ push(ebx);  // restore return address
 
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
       ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
-  __ TailCallExternalReference(store_ic_property, 3, 1);
+  __ TailCallExternalReference(store_ic_property, 4, 1);
 
   // Handle store cache miss.
   __ bind(&miss);
@@ -3712,10 +3713,13 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
   __ push(edx);
   __ push(ecx);
   __ push(eax);
-  __ push(ebx);
+  __ push(Immediate(Smi::FromInt(NONE)));   // PropertyAttributes
+  __ push(Immediate(Smi::FromInt(
+      Code::ExtractExtraICStateFromFlags(flags) & kStrictMode)));
+  __ push(ebx);   // return address
 
   // Do tail-call to runtime routine.
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 
   return GetCode(flags);
 }
index 515a9fe..5e2cbee 100644 (file)
@@ -1038,9 +1038,9 @@ Result VirtualFrame::CallStoreIC(Handle<String> name,
                                  StrictModeFlag strict_mode) {
   // Value and (if not contextual) receiver are on top of the frame.
   // The IC expects name in ecx, value in eax, and receiver in edx.
-  Handle<Code> ic(Builtins::builtin(strict_mode == kStrictMode
-      ? Builtins::StoreIC_Initialize_Strict
-      : Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode == kStrictMode) ? Builtins::StoreIC_Initialize_Strict
+                                   : Builtins::StoreIC_Initialize));
 
   Result value = Pop();
   RelocInfo::Mode mode;
@@ -1061,7 +1061,7 @@ Result VirtualFrame::CallStoreIC(Handle<String> name,
 }
 
 
-Result VirtualFrame::CallKeyedStoreIC() {
+Result VirtualFrame::CallKeyedStoreIC(StrictModeFlag strict_mode) {
   // Value, key, and receiver are on the top of the frame.  The IC
   // expects value in eax, key in ecx, and receiver in edx.
   Result value = Pop();
@@ -1105,7 +1105,9 @@ Result VirtualFrame::CallKeyedStoreIC() {
     receiver.Unuse();
   }
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
+                                   : Builtins::KeyedStoreIC_Initialize));
   return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
 }
 
index 93362b4..f5d0e8d 100644 (file)
@@ -370,7 +370,7 @@ class VirtualFrame: public ZoneObject {
 
   // Call keyed store IC.  Value, key, and receiver are found on top
   // of the frame.  All three are dropped.
-  Result CallKeyedStoreIC();
+  Result CallKeyedStoreIC(StrictModeFlag strict_mode);
 
   // Call call IC.  Function name, arguments, and receiver are found on top
   // of the frame and dropped by the call.  The argument count does not
index 8fbc184..9d358ed 100644 (file)
@@ -76,6 +76,15 @@ Code* IC::GetTargetAtAddress(Address address) {
 
 void IC::SetTargetAtAddress(Address address, Code* target) {
   ASSERT(target->is_inline_cache_stub() || target->is_compare_ic_stub());
+#ifdef DEBUG
+  // STORE_IC and KEYED_STORE_IC use Code::extra_ic_state() to mark
+  // ICs as strict mode. The strict-ness of the IC must be preserved.
+  Code* old_target = GetTargetAtAddress(address);
+  if (old_target->kind() == Code::STORE_IC ||
+      old_target->kind() == Code::KEYED_STORE_IC) {
+    ASSERT(old_target->extra_ic_state() == target->extra_ic_state());
+  }
+#endif
   Assembler::set_target_address_at(address, target->instruction_start());
 }
 
index 4f75ade..2d666d6 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -343,7 +343,7 @@ void StoreIC::Clear(Address address, Code* target) {
   if (target->ic_state() == UNINITIALIZED) return;
   ClearInlinedVersion(address);
   SetTargetAtAddress(address,
-      target->extra_ic_state() == kStoreICStrict
+      (target->extra_ic_state() == kStrictMode)
         ? initialize_stub_strict()
         : initialize_stub());
 }
@@ -366,7 +366,10 @@ void KeyedStoreIC::RestoreInlinedVersion(Address address) {
 
 void KeyedStoreIC::Clear(Address address, Code* target) {
   if (target->ic_state() == UNINITIALIZED) return;
-  SetTargetAtAddress(address, initialize_stub());
+  SetTargetAtAddress(address,
+      (target->extra_ic_state() == kStrictMode)
+        ? initialize_stub_strict()
+        : initialize_stub());
 }
 
 
@@ -1227,7 +1230,8 @@ MaybeObject* KeyedLoadIC::Load(State state,
         if (receiver->HasExternalArrayElements()) {
           MaybeObject* probe =
               StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver,
-                                                              false);
+                                                              false,
+                                                              kNonStrictMode);
           stub = probe->IsFailure() ?
               NULL : Code::cast(probe->ToObjectUnchecked());
         } else if (receiver->HasIndexedInterceptor()) {
@@ -1383,7 +1387,7 @@ static bool LookupForWrite(JSObject* object,
 
 
 MaybeObject* StoreIC::Store(State state,
-                            Code::ExtraICState extra_ic_state,
+                            StrictModeFlag strict_mode,
                             Handle<Object> object,
                             Handle<String> name,
                             Handle<Object> value) {
@@ -1413,11 +1417,11 @@ MaybeObject* StoreIC::Store(State state,
 #ifdef DEBUG
     if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
 #endif
-    Builtins::Name target = (extra_ic_state == kStoreICStrict)
+    Builtins::Name target = (strict_mode == kStrictMode)
         ? Builtins::StoreIC_ArrayLength_Strict
         : Builtins::StoreIC_ArrayLength;
     set_target(Builtins::builtin(target));
-    return receiver->SetProperty(*name, *value, NONE);
+    return receiver->SetProperty(*name, *value, NONE, strict_mode);
   }
 
   // Lookup the property locally in the receiver.
@@ -1441,13 +1445,15 @@ MaybeObject* StoreIC::Store(State state,
           // Index is an offset from the end of the object.
           int offset = map->instance_size() + (index * kPointerSize);
           if (PatchInlinedStore(address(), map, offset)) {
-            set_target(megamorphic_stub());
+            set_target((strict_mode == kStrictMode)
+                         ? megamorphic_stub_strict()
+                         : megamorphic_stub());
 #ifdef DEBUG
             if (FLAG_trace_ic) {
               PrintF("[StoreIC : inline patch %s]\n", *name->ToCString());
             }
 #endif
-            return receiver->SetProperty(*name, *value, NONE);
+            return receiver->SetProperty(*name, *value, NONE, strict_mode);
 #ifdef DEBUG
 
           } else {
@@ -1474,11 +1480,16 @@ MaybeObject* StoreIC::Store(State state,
 
       // If no inlined store ic was patched, generate a stub for this
       // store.
-      UpdateCaches(&lookup, state, extra_ic_state, receiver, name, value);
+      UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
     } else {
-      // Strict mode doesn't allow setting non-existent global property.
-      if (extra_ic_state == kStoreICStrict && IsContextual(object)) {
-        return ReferenceError("not_defined", name);
+      // Strict mode doesn't allow setting non-existent global property
+      // or an assignment to a read only property.
+      if (strict_mode == kStrictMode) {
+        if (lookup.IsFound() && lookup.IsReadOnly()) {
+          return TypeError("strict_read_only_property", object, name);
+        } else if (IsContextual(object)) {
+          return ReferenceError("not_defined", name);
+        }
       }
     }
   }
@@ -1486,7 +1497,7 @@ MaybeObject* StoreIC::Store(State state,
   if (receiver->IsJSGlobalProxy()) {
     // Generate a generic stub that goes to the runtime when we see a global
     // proxy as receiver.
-    Code* stub = (extra_ic_state == kStoreICStrict)
+    Code* stub = (strict_mode == kStrictMode)
         ? global_proxy_stub_strict()
         : global_proxy_stub();
     if (target() != stub) {
@@ -1498,13 +1509,13 @@ MaybeObject* StoreIC::Store(State state,
   }
 
   // Set the property.
-  return receiver->SetProperty(*name, *value, NONE);
+  return receiver->SetProperty(*name, *value, NONE, strict_mode);
 }
 
 
 void StoreIC::UpdateCaches(LookupResult* lookup,
                            State state,
-                           Code::ExtraICState extra_ic_state,
+                           StrictModeFlag strict_mode,
                            Handle<JSObject> receiver,
                            Handle<String> name,
                            Handle<Object> value) {
@@ -1526,7 +1537,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
   switch (type) {
     case FIELD: {
       maybe_code = StubCache::ComputeStoreField(
-          *name, *receiver, lookup->GetFieldIndex(), NULL, extra_ic_state);
+          *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
       break;
     }
     case MAP_TRANSITION: {
@@ -1536,7 +1547,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
       Handle<Map> transition(lookup->GetTransitionMap());
       int index = transition->PropertyIndexFor(*name);
       maybe_code = StubCache::ComputeStoreField(
-          *name, *receiver, index, *transition, extra_ic_state);
+          *name, *receiver, index, *transition, strict_mode);
       break;
     }
     case NORMAL: {
@@ -1548,10 +1559,10 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
         JSGlobalPropertyCell* cell =
             JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
         maybe_code = StubCache::ComputeStoreGlobal(
-            *name, *global, cell, extra_ic_state);
+            *name, *global, cell, strict_mode);
       } else {
         if (lookup->holder() != *receiver) return;
-        maybe_code = StubCache::ComputeStoreNormal(extra_ic_state);
+        maybe_code = StubCache::ComputeStoreNormal(strict_mode);
       }
       break;
     }
@@ -1560,13 +1571,13 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
       AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
       if (v8::ToCData<Address>(callback->setter()) == 0) return;
       maybe_code = StubCache::ComputeStoreCallback(
-          *name, *receiver, callback, extra_ic_state);
+          *name, *receiver, callback, strict_mode);
       break;
     }
     case INTERCEPTOR: {
       ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
       maybe_code = StubCache::ComputeStoreInterceptor(
-          *name, *receiver, extra_ic_state);
+          *name, *receiver, strict_mode);
       break;
     }
     default:
@@ -1583,7 +1594,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
   } else if (state == MONOMORPHIC) {
     // Only move to megamorphic if the target changes.
     if (target() != Code::cast(code)) {
-      set_target(extra_ic_state == kStoreICStrict
+      set_target((strict_mode == kStrictMode)
                    ? megamorphic_stub_strict()
                    : megamorphic_stub());
     }
@@ -1599,6 +1610,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
 
 
 MaybeObject* KeyedStoreIC::Store(State state,
+                                 StrictModeFlag strict_mode,
                                  Handle<Object> object,
                                  Handle<Object> key,
                                  Handle<Object> value) {
@@ -1630,11 +1642,11 @@ MaybeObject* KeyedStoreIC::Store(State state,
 
     // Update inline cache and stub cache.
     if (FLAG_use_ic) {
-      UpdateCaches(&lookup, state, receiver, name, value);
+      UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
     }
 
     // Set the property.
-    return receiver->SetProperty(*name, *value, NONE);
+    return receiver->SetProperty(*name, *value, NONE, strict_mode);
   }
 
   // Do not use ICs for objects that require access checks (including
@@ -1643,23 +1655,25 @@ MaybeObject* KeyedStoreIC::Store(State state,
   ASSERT(!(use_ic && object->IsJSGlobalProxy()));
 
   if (use_ic) {
-    Code* stub = generic_stub();
+    Code* stub =
+        (strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub();
     if (state == UNINITIALIZED) {
       if (object->IsJSObject()) {
         Handle<JSObject> receiver = Handle<JSObject>::cast(object);
         if (receiver->HasExternalArrayElements()) {
           MaybeObject* probe =
-              StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver, true);
+              StubCache::ComputeKeyedLoadOrStoreExternalArray(
+                  *receiver, true, strict_mode);
           stub = probe->IsFailure() ?
               NULL : Code::cast(probe->ToObjectUnchecked());
         } else if (receiver->HasPixelElements()) {
           MaybeObject* probe =
-              StubCache::ComputeKeyedStorePixelArray(*receiver);
+              StubCache::ComputeKeyedStorePixelArray(*receiver, strict_mode);
           stub = probe->IsFailure() ?
               NULL : Code::cast(probe->ToObjectUnchecked());
         } else if (key->IsSmi() && receiver->map()->has_fast_elements()) {
           MaybeObject* probe =
-              StubCache::ComputeKeyedStoreSpecialized(*receiver);
+              StubCache::ComputeKeyedStoreSpecialized(*receiver, strict_mode);
           stub = probe->IsFailure() ?
               NULL : Code::cast(probe->ToObjectUnchecked());
         }
@@ -1669,12 +1683,13 @@ MaybeObject* KeyedStoreIC::Store(State state,
   }
 
   // Set the property.
-  return Runtime::SetObjectProperty(object, key, value, NONE);
+  return Runtime::SetObjectProperty(object, key, value, NONE, strict_mode);
 }
 
 
 void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
                                 State state,
+                                StrictModeFlag strict_mode,
                                 Handle<JSObject> receiver,
                                 Handle<String> name,
                                 Handle<Object> value) {
@@ -1701,8 +1716,8 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
 
   switch (type) {
     case FIELD: {
-      maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver,
-                                                     lookup->GetFieldIndex());
+      maybe_code = StubCache::ComputeKeyedStoreField(
+          *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
       break;
     }
     case MAP_TRANSITION: {
@@ -1711,8 +1726,8 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
         ASSERT(type == MAP_TRANSITION);
         Handle<Map> transition(lookup->GetTransitionMap());
         int index = transition->PropertyIndexFor(*name);
-        maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver,
-                                                       index, *transition);
+        maybe_code = StubCache::ComputeKeyedStoreField(
+            *name, *receiver, index, *transition, strict_mode);
         break;
       }
       // fall through.
@@ -1720,7 +1735,9 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
     default: {
       // Always rewrite to the generic case so that we do not
       // repeatedly try to rewrite.
-      maybe_code = generic_stub();
+      maybe_code = (strict_mode == kStrictMode)
+          ? generic_stub_strict()
+          : generic_stub();
       break;
     }
   }
@@ -1735,7 +1752,9 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
   if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
     set_target(Code::cast(code));
   } else if (state == MONOMORPHIC) {
-    set_target(megamorphic_stub());
+    set_target((strict_mode == kStrictMode)
+                 ? megamorphic_stub_strict()
+                 : megamorphic_stub());
   }
 
 #ifdef DEBUG
@@ -1836,8 +1855,11 @@ MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) {
   StoreIC ic;
   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
   Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
-  return ic.Store(state, extra_ic_state, args.at<Object>(0),
-                  args.at<String>(1), args.at<Object>(2));
+  return ic.Store(state,
+                  static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
+                  args.at<Object>(0),
+                  args.at<String>(1),
+                  args.at<Object>(2));
 }
 
 
@@ -1901,7 +1923,11 @@ MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(Arguments args) {
   ASSERT(args.length() == 3);
   KeyedStoreIC ic;
   IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
-  return ic.Store(state, args.at<Object>(0), args.at<Object>(1),
+  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
+  return ic.Store(state,
+                  static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
+                  args.at<Object>(0),
+                  args.at<Object>(1),
                   args.at<Object>(2));
 }
 
index 96838c7..e12cbaf 100644 (file)
--- a/src/ic.h
+++ b/src/ic.h
@@ -398,16 +398,10 @@ class KeyedLoadIC: public IC {
 
 class StoreIC: public IC {
  public:
-
-  enum StoreICStrictMode {
-    kStoreICNonStrict = kNonStrictMode,
-    kStoreICStrict = kStrictMode
-  };
-
   StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); }
 
   MUST_USE_RESULT MaybeObject* Store(State state,
-                                     Code::ExtraICState extra_ic_state,
+                                     StrictModeFlag strict_mode,
                                      Handle<Object> object,
                                      Handle<String> name,
                                      Handle<Object> value);
@@ -416,10 +410,11 @@ class StoreIC: public IC {
   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
   static void GenerateMiss(MacroAssembler* masm);
   static void GenerateMegamorphic(MacroAssembler* masm,
-                                  Code::ExtraICState extra_ic_state);
+                                  StrictModeFlag strict_mode);
   static void GenerateArrayLength(MacroAssembler* masm);
   static void GenerateNormal(MacroAssembler* masm);
-  static void GenerateGlobalProxy(MacroAssembler* masm);
+  static void GenerateGlobalProxy(MacroAssembler* masm,
+                                  StrictModeFlag strict_mode);
 
   // Clear the use of an inlined version.
   static void ClearInlinedVersion(Address address);
@@ -433,11 +428,18 @@ class StoreIC: public IC {
   // lookup result.
   void UpdateCaches(LookupResult* lookup,
                     State state,
-                    Code::ExtraICState extra_ic_state,
+                    StrictModeFlag strict_mode,
                     Handle<JSObject> receiver,
                     Handle<String> name,
                     Handle<Object> value);
 
+  void set_target(Code* code) {
+    // Strict mode must be preserved across IC patching.
+    ASSERT((code->extra_ic_state() & kStrictMode) ==
+           (target()->extra_ic_state() & kStrictMode));
+    IC::set_target(code);
+  }
+
   // Stub accessors.
   static Code* megamorphic_stub() {
     return Builtins::builtin(Builtins::StoreIC_Megamorphic);
@@ -473,6 +475,7 @@ class KeyedStoreIC: public IC {
   KeyedStoreIC() : IC(NO_EXTRA_FRAME) { }
 
   MUST_USE_RESULT MaybeObject* Store(State state,
+                                     StrictModeFlag strict_mode,
                                      Handle<Object> object,
                                      Handle<Object> name,
                                      Handle<Object> value);
@@ -480,8 +483,9 @@ class KeyedStoreIC: public IC {
   // Code generators for stub routines.  Only called once at startup.
   static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
   static void GenerateMiss(MacroAssembler* masm);
-  static void GenerateRuntimeSetProperty(MacroAssembler* masm);
-  static void GenerateGeneric(MacroAssembler* masm);
+  static void GenerateRuntimeSetProperty(MacroAssembler* masm,
+                                         StrictModeFlag strict_mode);
+  static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
 
   // Clear the inlined version so the IC is always hit.
   static void ClearInlinedVersion(Address address);
@@ -493,20 +497,37 @@ class KeyedStoreIC: public IC {
   // Update the inline cache.
   void UpdateCaches(LookupResult* lookup,
                     State state,
+                    StrictModeFlag strict_mode,
                     Handle<JSObject> receiver,
                     Handle<String> name,
                     Handle<Object> value);
 
+  void set_target(Code* code) {
+    // Strict mode must be preserved across IC patching.
+    ASSERT((code->extra_ic_state() & kStrictMode) ==
+           (target()->extra_ic_state() & kStrictMode));
+    IC::set_target(code);
+  }
+
   // Stub accessors.
   static Code* initialize_stub() {
     return Builtins::builtin(Builtins::KeyedStoreIC_Initialize);
   }
+  static Code* initialize_stub_strict() {
+    return Builtins::builtin(Builtins::KeyedStoreIC_Initialize_Strict);
+  }
   static Code* megamorphic_stub() {
     return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
   }
+  static Code* megamorphic_stub_strict() {
+    return Builtins::builtin(Builtins::KeyedStoreIC_Generic_Strict);
+  }
   static Code* generic_stub() {
     return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
   }
+  static Code* generic_stub_strict() {
+    return Builtins::builtin(Builtins::KeyedStoreIC_Generic_Strict);
+  }
 
   static void Clear(Address address, Code* target);
 
index db33753..2c94912 100644 (file)
@@ -228,6 +228,8 @@ function FormatMessage(message) {
       strict_delete_property:       ["Cannot delete property '", "%0", "' of ", "%1"],
       strict_const:                 ["Use of const in strict mode."],
       strict_function:              ["In strict mode code, functions can only be declared at top level or immediately within another function." ],
+      strict_read_only_property:    ["Cannot assign to read only property '", "%0", "' of ", "%1"],
+      strict_cannot_assign:         ["Cannot assign to read only '", "%0", "' in strict mode"],
     };
   }
   var message_type = %MessageGetType(message);
index f955d33..dedb199 100644 (file)
@@ -2619,7 +2619,8 @@ Code::Flags Code::ComputeFlags(Kind kind,
   ASSERT(extra_ic_state == kNoExtraICState ||
          (kind == CALL_IC && (ic_state == MONOMORPHIC ||
                               ic_state == MONOMORPHIC_PROTOTYPE_FAILURE)) ||
-         (kind == STORE_IC));
+         (kind == STORE_IC) ||
+         (kind == KEYED_STORE_IC));
   // Compute the bit mask.
   int bits = kind << kFlagsKindShift;
   if (in_loop) bits |= kFlagsICInLoopMask;
@@ -3741,7 +3742,8 @@ MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
   ASSERT(!IsJSGlobalProxy());
   return SetPropertyPostInterceptor(Heap::hidden_symbol(),
                                     hidden_obj,
-                                    DONT_ENUM);
+                                    DONT_ENUM,
+                                    kNonStrictMode);
 }
 
 
index 0b1d72a..0b7f60a 100644 (file)
@@ -1444,14 +1444,15 @@ MaybeObject* JSObject::AddProperty(String* name,
 MaybeObject* JSObject::SetPropertyPostInterceptor(
     String* name,
     Object* value,
-    PropertyAttributes attributes) {
+    PropertyAttributes attributes,
+    StrictModeFlag strict) {
   // Check local property, ignore interceptor.
   LookupResult result;
   LocalLookupRealNamedProperty(name, &result);
   if (result.IsFound()) {
     // An existing property, a map transition or a null descriptor was
     // found.  Use set property to handle all these cases.
-    return SetProperty(&result, name, value, attributes);
+    return SetProperty(&result, name, value, attributes, strict);
   }
   // Add a new real property.
   return AddProperty(name, value, attributes);
@@ -1576,7 +1577,8 @@ MaybeObject* JSObject::ConvertDescriptorToField(String* name,
 MaybeObject* JSObject::SetPropertyWithInterceptor(
     String* name,
     Object* value,
-    PropertyAttributes attributes) {
+    PropertyAttributes attributes,
+    StrictModeFlag strict) {
   HandleScope scope;
   Handle<JSObject> this_handle(this);
   Handle<String> name_handle(name);
@@ -1605,7 +1607,8 @@ MaybeObject* JSObject::SetPropertyWithInterceptor(
   MaybeObject* raw_result =
       this_handle->SetPropertyPostInterceptor(*name_handle,
                                               *value_handle,
-                                              attributes);
+                                              attributes,
+                                              strict);
   RETURN_IF_SCHEDULED_EXCEPTION();
   return raw_result;
 }
@@ -1613,10 +1616,11 @@ MaybeObject* JSObject::SetPropertyWithInterceptor(
 
 MaybeObject* JSObject::SetProperty(String* name,
                                    Object* value,
-                                   PropertyAttributes attributes) {
+                                   PropertyAttributes attributes,
+                                   StrictModeFlag strict) {
   LookupResult result;
   LocalLookup(name, &result);
-  return SetProperty(&result, name, value, attributes);
+  return SetProperty(&result, name, value, attributes, strict);
 }
 
 
@@ -1896,7 +1900,8 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result,
 MaybeObject* JSObject::SetProperty(LookupResult* result,
                                    String* name,
                                    Object* value,
-                                   PropertyAttributes attributes) {
+                                   PropertyAttributes attributes,
+                                   StrictModeFlag strict) {
   // Make sure that the top context does not change when doing callbacks or
   // interceptor calls.
   AssertNoContextChange ncc;
@@ -1923,7 +1928,8 @@ MaybeObject* JSObject::SetProperty(LookupResult* result,
     Object* proto = GetPrototype();
     if (proto->IsNull()) return value;
     ASSERT(proto->IsJSGlobalObject());
-    return JSObject::cast(proto)->SetProperty(result, name, value, attributes);
+    return JSObject::cast(proto)->SetProperty(
+        result, name, value, attributes, strict);
   }
 
   if (!result->IsProperty() && !IsJSContextExtensionObject()) {
@@ -1942,7 +1948,19 @@ MaybeObject* JSObject::SetProperty(LookupResult* result,
     // Neither properties nor transitions found.
     return AddProperty(name, value, attributes);
   }
-  if (result->IsReadOnly() && result->IsProperty()) return value;
+  if (result->IsReadOnly() && result->IsProperty()) {
+    if (strict == kStrictMode) {
+      HandleScope scope;
+      Handle<String> key(name);
+      Handle<Object> holder(this);
+      Handle<Object> args[2] = { key, holder };
+      return Top::Throw(*Factory::NewTypeError("strict_read_only_property",
+                                                HandleVector(args, 2)));
+
+    } else {
+      return value;
+    }
+  }
   // This is a real property that is not read-only, or it is a
   // transition or null descriptor and there are no setters in the prototypes.
   switch (result->type()) {
@@ -1970,7 +1988,7 @@ MaybeObject* JSObject::SetProperty(LookupResult* result,
                                      value,
                                      result->holder());
     case INTERCEPTOR:
-      return SetPropertyWithInterceptor(name, value, attributes);
+      return SetPropertyWithInterceptor(name, value, attributes, strict);
     case CONSTANT_TRANSITION: {
       // If the same constant function is being added we can simply
       // transition to the target map.
@@ -6287,7 +6305,8 @@ void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
       }
       break;
     case STORE_IC:
-      if (extra == StoreIC::kStoreICStrict) {
+    case KEYED_STORE_IC:
+      if (extra == kStrictMode) {
         name = "STRICT";
       }
       break;
index fbfc5fd..de15a73 100644 (file)
@@ -1361,11 +1361,13 @@ class JSObject: public HeapObject {
 
   MUST_USE_RESULT MaybeObject* SetProperty(String* key,
                                            Object* value,
-                                           PropertyAttributes attributes);
+                                           PropertyAttributes attributes,
+                                           StrictModeFlag strict);
   MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result,
                                            String* key,
                                            Object* value,
-                                           PropertyAttributes attributes);
+                                           PropertyAttributes attributes,
+                                           StrictModeFlag strict);
   MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck(
       LookupResult* result,
       String* name,
@@ -1380,11 +1382,13 @@ class JSObject: public HeapObject {
   MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor(
       String* name,
       Object* value,
-      PropertyAttributes attributes);
+      PropertyAttributes attributes,
+      StrictModeFlag strict);
   MUST_USE_RESULT MaybeObject* SetPropertyPostInterceptor(
       String* name,
       Object* value,
-      PropertyAttributes attributes);
+      PropertyAttributes attributes,
+      StrictModeFlag strict);
   MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes(
       String* key,
       Object* value,
index 9fedfc9..8560310 100644 (file)
@@ -1661,34 +1661,49 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
 
     if (top_scope_->is_global_scope()) {
       // Compute the arguments for the runtime call.
-      ZoneList<Expression*>* arguments = new ZoneList<Expression*>(2);
-      // Be careful not to assign a value to the global variable if
-      // we're in a with. The initialization value should not
-      // necessarily be stored in the global object in that case,
-      // which is why we need to generate a separate assignment node.
+      ZoneList<Expression*>* arguments = new ZoneList<Expression*>(3);
       arguments->Add(new Literal(name));  // we have at least 1 parameter
-      if (is_const || (value != NULL && !inside_with())) {
-        arguments->Add(value);
-        value = NULL;  // zap the value to avoid the unnecessary assignment
-      }
-      // Construct the call to Runtime::DeclareGlobal{Variable,Const}Locally
-      // and add it to the initialization statement block. Note that
-      // this function does different things depending on if we have
-      // 1 or 2 parameters.
       CallRuntime* initialize;
+
       if (is_const) {
+        arguments->Add(value);
+        value = NULL;  // zap the value to avoid the unnecessary assignment
+
+        // Construct the call to Runtime_InitializeConstGlobal
+        // and add it to the initialization statement block.
+        // Note that the function does different things depending on
+        // the number of arguments (1 or 2).
         initialize =
-          new CallRuntime(
-            Factory::InitializeConstGlobal_symbol(),
-            Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
-            arguments);
+            new CallRuntime(
+              Factory::InitializeConstGlobal_symbol(),
+              Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
+              arguments);
       } else {
+        // Add strict mode.
+        // We may want to pass singleton to avoid Literal allocations.
+        arguments->Add(NewNumberLiteral(
+            temp_scope_->StrictMode() ? kStrictMode : kNonStrictMode));
+
+        // Be careful not to assign a value to the global variable if
+        // we're in a with. The initialization value should not
+        // necessarily be stored in the global object in that case,
+        // which is why we need to generate a separate assignment node.
+        if (value != NULL && !inside_with()) {
+          arguments->Add(value);
+          value = NULL;  // zap the value to avoid the unnecessary assignment
+        }
+
+        // Construct the call to Runtime_InitializeVarGlobal
+        // and add it to the initialization statement block.
+        // Note that the function does different things depending on
+        // the number of arguments (2 or 3).
         initialize =
-          new CallRuntime(
-            Factory::InitializeVarGlobal_symbol(),
-            Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
-            arguments);
+            new CallRuntime(
+              Factory::InitializeVarGlobal_symbol(),
+              Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
+              arguments);
       }
+
       block->AddStatement(new ExpressionStatement(initialize));
     }
 
index c009f37..b47cc3a 100644 (file)
@@ -161,7 +161,8 @@ MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(JSObject* boilerplate) {
           if (!maybe_result->ToObject(&result)) return maybe_result;
         }
         { MaybeObject* maybe_result =
-              copy->SetProperty(key_string, result, NONE);
+              // Creating object copy for literals. No strict mode needed.
+              copy->SetProperty(key_string, result, NONE, kNonStrictMode);
           if (!maybe_result->ToObject(&result)) return maybe_result;
         }
       }
@@ -547,7 +548,9 @@ static MaybeObject* Runtime_CreateCatchExtensionObject(Arguments args) {
   // Assign the exception value to the catch variable and make sure
   // that the catch variable is DontDelete.
   { MaybeObject* maybe_value =
-        JSObject::cast(object)->SetProperty(key, value, DONT_DELETE);
+        // Passing non-strict per ECMA-262 5th Ed. 12.14. Catch, bullet #4.
+        JSObject::cast(object)->SetProperty(
+            key, value, DONT_DELETE, kNonStrictMode);
     if (!maybe_value->ToObject(&value)) return maybe_value;
   }
   return object;
@@ -998,12 +1001,16 @@ static Failure* ThrowRedeclarationError(const char* type, Handle<String> name) {
 
 
 static MaybeObject* Runtime_DeclareGlobals(Arguments args) {
+  ASSERT(args.length() == 4);
   HandleScope scope;
   Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global());
 
   Handle<Context> context = args.at<Context>(0);
   CONVERT_ARG_CHECKED(FixedArray, pairs, 1);
   bool is_eval = Smi::cast(args[2])->value() == 1;
+  StrictModeFlag strict_mode =
+      static_cast<StrictModeFlag>(Smi::cast(args[3])->value());
+  ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
 
   // Compute the property attributes. According to ECMA-262, section
   // 13, page 71, the property must be read-only and
@@ -1118,7 +1125,11 @@ static MaybeObject* Runtime_DeclareGlobals(Arguments args) {
                                                               value,
                                                               attributes));
     } else {
-      RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, attributes));
+      RETURN_IF_EMPTY_HANDLE(SetProperty(global,
+                                         name,
+                                         value,
+                                         attributes,
+                                         strict_mode));
     }
   }
 
@@ -1179,7 +1190,8 @@ static MaybeObject* Runtime_DeclareContextSlot(Arguments args) {
         // Slow case: The property is not in the FixedArray part of the context.
         Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
         RETURN_IF_EMPTY_HANDLE(
-            SetProperty(context_ext, name, initial_value, mode));
+            SetProperty(context_ext, name, initial_value,
+                        mode, kNonStrictMode));
       }
     }
 
@@ -1220,7 +1232,8 @@ static MaybeObject* Runtime_DeclareContextSlot(Arguments args) {
         return ThrowRedeclarationError("const", name);
       }
     }
-    RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, mode));
+    RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, mode,
+                                       kNonStrictMode));
   }
 
   return Heap::undefined_value();
@@ -1229,14 +1242,21 @@ static MaybeObject* Runtime_DeclareContextSlot(Arguments args) {
 
 static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) {
   NoHandleAllocation nha;
+  // args[0] == name
+  // args[1] == strict_mode
+  // args[2] == value (optional)
 
   // Determine if we need to assign to the variable if it already
   // exists (based on the number of arguments).
-  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
-  bool assign = args.length() == 2;
+  RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
+  bool assign = args.length() == 3;
 
   CONVERT_ARG_CHECKED(String, name, 0);
   GlobalObject* global = Top::context()->global();
+  RUNTIME_ASSERT(args[1]->IsSmi());
+  StrictModeFlag strict_mode =
+      static_cast<StrictModeFlag>(Smi::cast(args[1])->value());
+  ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
 
   // According to ECMA-262, section 12.2, page 62, the property must
   // not be deletable.
@@ -1292,8 +1312,9 @@ static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) {
       }
 
       // Assign the value (or undefined) to the property.
-      Object* value = (assign) ? args[1] : Heap::undefined_value();
-      return real_holder->SetProperty(&lookup, *name, value, attributes);
+      Object* value = (assign) ? args[2] : Heap::undefined_value();
+      return real_holder->SetProperty(
+          &lookup, *name, value, attributes, strict_mode);
     }
 
     Object* proto = real_holder->GetPrototype();
@@ -1307,7 +1328,9 @@ static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) {
   }
 
   global = Top::context()->global();
-  if (assign) return global->SetProperty(*name, args[1], attributes);
+  if (assign) {
+    return global->SetProperty(*name, args[2], attributes, strict_mode);
+  }
   return Heap::undefined_value();
 }
 
@@ -1366,13 +1389,19 @@ static MaybeObject* Runtime_InitializeConstGlobal(Arguments args) {
     // BUG 1213575: Handle the case where we have to set a read-only
     // property through an interceptor and only do it if it's
     // uninitialized, e.g. the hole. Nirk...
-    RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, attributes));
+    // Passing non-strict mode because the property is writable.
+    RETURN_IF_EMPTY_HANDLE(SetProperty(global,
+                                       name,
+                                       value,
+                                       attributes,
+                                       kNonStrictMode));
     return *value;
   }
 
   // Set the value, but only we're assigning the initial value to a
   // constant. For now, we determine this by checking if the
   // current value is the hole.
+  // Strict mode handling not needed (const disallowed in strict mode).
   PropertyType type = lookup.type();
   if (type == FIELD) {
     FixedArray* properties = global->properties();
@@ -1448,7 +1477,9 @@ static MaybeObject* Runtime_InitializeConstContextSlot(Arguments args) {
   // context.
   if (attributes == ABSENT) {
     Handle<JSObject> global = Handle<JSObject>(Top::context()->global());
-    RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, NONE));
+    // Strict mode not needed (const disallowed in strict mode).
+    RETURN_IF_EMPTY_HANDLE(
+        SetProperty(global, name, value, NONE, kNonStrictMode));
     return *value;
   }
 
@@ -1485,8 +1516,9 @@ static MaybeObject* Runtime_InitializeConstContextSlot(Arguments args) {
     // The property was found in a different context extension object.
     // Set it if it is not a read-only property.
     if ((attributes & READ_ONLY) == 0) {
+      // Strict mode not needed (const disallowed in strict mode).
       RETURN_IF_EMPTY_HANDLE(
-          SetProperty(context_ext, name, value, attributes));
+          SetProperty(context_ext, name, value, attributes, kNonStrictMode));
     }
   }
 
@@ -1652,7 +1684,7 @@ static Handle<JSFunction> InstallBuiltin(Handle<JSObject> holder,
                                                       code,
                                                       false);
   optimized->shared()->DontAdaptArguments();
-  SetProperty(holder, key, optimized, NONE);
+  SetProperty(holder, key, optimized, NONE, kStrictMode);
   return optimized;
 }
 
@@ -3748,7 +3780,8 @@ static MaybeObject* Runtime_DefineOrRedefineDataProperty(Arguments args) {
 MaybeObject* Runtime::SetObjectProperty(Handle<Object> object,
                                         Handle<Object> key,
                                         Handle<Object> value,
-                                        PropertyAttributes attr) {
+                                        PropertyAttributes attr,
+                                        StrictModeFlag strict) {
   HandleScope scope;
 
   if (object->IsUndefined() || object->IsNull()) {
@@ -3778,6 +3811,7 @@ MaybeObject* Runtime::SetObjectProperty(Handle<Object> object,
       return *value;
     }
 
+    // TODO(1220): Implement SetElement strict mode.
     Handle<Object> result = SetElement(js_object, index, value);
     if (result.is_null()) return Failure::Exception();
     return *value;
@@ -3790,7 +3824,7 @@ MaybeObject* Runtime::SetObjectProperty(Handle<Object> object,
     } else {
       Handle<String> key_string = Handle<String>::cast(key);
       key_string->TryFlatten();
-      result = SetProperty(js_object, key_string, value, attr);
+      result = SetProperty(js_object, key_string, value, attr, strict);
     }
     if (result.is_null()) return Failure::Exception();
     return *value;
@@ -3803,9 +3837,10 @@ MaybeObject* Runtime::SetObjectProperty(Handle<Object> object,
   Handle<String> name = Handle<String>::cast(converted);
 
   if (name->AsArrayIndex(&index)) {
+    // TODO(1220): Implement SetElement strict mode.
     return js_object->SetElement(index, *value);
   } else {
-    return js_object->SetProperty(*name, *value, attr);
+    return js_object->SetProperty(*name, *value, attr, strict);
   }
 }
 
@@ -3897,23 +3932,27 @@ MaybeObject* Runtime::ForceDeleteObjectProperty(Handle<JSObject> js_object,
 
 static MaybeObject* Runtime_SetProperty(Arguments args) {
   NoHandleAllocation ha;
-  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
+  RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
 
   Handle<Object> object = args.at<Object>(0);
   Handle<Object> key = args.at<Object>(1);
   Handle<Object> value = args.at<Object>(2);
-
+  CONVERT_SMI_CHECKED(unchecked_attributes, args[3]);
+  RUNTIME_ASSERT(
+      (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
   // Compute attributes.
-  PropertyAttributes attributes = NONE;
-  if (args.length() == 4) {
-    CONVERT_CHECKED(Smi, value_obj, args[3]);
-    int unchecked_value = value_obj->value();
-    // Only attribute bits should be set.
-    RUNTIME_ASSERT(
-        (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
-    attributes = static_cast<PropertyAttributes>(unchecked_value);
+  PropertyAttributes attributes =
+      static_cast<PropertyAttributes>(unchecked_attributes);
+
+  StrictModeFlag strict = kNonStrictMode;
+  if (args.length() == 5) {
+    CONVERT_SMI_CHECKED(strict_unchecked, args[4]);
+    RUNTIME_ASSERT(strict_unchecked == kStrictMode ||
+                   strict_unchecked == kNonStrictMode);
+    strict = static_cast<StrictModeFlag>(strict_unchecked);
   }
-  return Runtime::SetObjectProperty(object, key, value, attributes);
+
+  return Runtime::SetObjectProperty(object, key, value, attributes, strict);
 }
 
 
@@ -3947,7 +3986,7 @@ static MaybeObject* Runtime_DeleteProperty(Arguments args) {
   CONVERT_CHECKED(JSObject, object, args[0]);
   CONVERT_CHECKED(String, key, args[1]);
   CONVERT_SMI_CHECKED(strict, args[2]);
-  return object->DeleteProperty(key, strict == kStrictMode
+  return object->DeleteProperty(key, (strict == kStrictMode)
                                       ? JSObject::STRICT_DELETION
                                       : JSObject::NORMAL_DELETION);
 }
@@ -7495,11 +7534,16 @@ static ObjectPair Runtime_LoadContextSlotNoReferenceError(Arguments args) {
 
 static MaybeObject* Runtime_StoreContextSlot(Arguments args) {
   HandleScope scope;
-  ASSERT(args.length() == 3);
+  ASSERT(args.length() == 4);
 
   Handle<Object> value(args[0]);
   CONVERT_ARG_CHECKED(Context, context, 1);
   CONVERT_ARG_CHECKED(String, name, 2);
+  CONVERT_SMI_CHECKED(strict_unchecked, args[3]);
+  RUNTIME_ASSERT(strict_unchecked == kStrictMode ||
+                 strict_unchecked == kNonStrictMode);
+  StrictModeFlag strict = static_cast<StrictModeFlag>(strict_unchecked);
+
 
   int index;
   PropertyAttributes attributes;
@@ -7543,7 +7587,12 @@ static MaybeObject* Runtime_StoreContextSlot(Arguments args) {
   // extension object itself.
   if ((attributes & READ_ONLY) == 0 ||
       (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
-    RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, NONE));
+    RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, NONE, strict));
+  } else if (strict == kStrictMode && (attributes & READ_ONLY) != 0) {
+    // Setting read only property in strict mode.
+    Handle<Object> error =
+      Factory::NewTypeError("strict_cannot_assign", HandleVector(&name, 1));
+    return Top::Throw(*error);
   }
   return *value;
 }
@@ -9288,7 +9337,9 @@ static bool CopyContextLocalsToScopeObject(
       RETURN_IF_EMPTY_HANDLE_VALUE(
           SetProperty(scope_object,
                       scope_info.context_slot_name(i),
-                      Handle<Object>(context->get(context_index)), NONE),
+                      Handle<Object>(context->get(context_index)),
+                      NONE,
+                      kNonStrictMode),
           false);
     }
   }
@@ -9314,7 +9365,9 @@ static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) {
     RETURN_IF_EMPTY_HANDLE_VALUE(
         SetProperty(local_scope,
                     scope_info.parameter_name(i),
-                    Handle<Object>(frame->GetParameter(i)), NONE),
+                    Handle<Object>(frame->GetParameter(i)),
+                    NONE,
+                    kNonStrictMode),
         Handle<JSObject>());
   }
 
@@ -9323,7 +9376,9 @@ static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) {
     RETURN_IF_EMPTY_HANDLE_VALUE(
         SetProperty(local_scope,
                     scope_info.stack_slot_name(i),
-                    Handle<Object>(frame->GetExpression(i)), NONE),
+                    Handle<Object>(frame->GetExpression(i)),
+                    NONE,
+                    kNonStrictMode),
         Handle<JSObject>());
   }
 
@@ -9347,7 +9402,11 @@ static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) {
         ASSERT(keys->get(i)->IsString());
         Handle<String> key(String::cast(keys->get(i)));
         RETURN_IF_EMPTY_HANDLE_VALUE(
-            SetProperty(local_scope, key, GetProperty(ext, key), NONE),
+            SetProperty(local_scope,
+                        key,
+                        GetProperty(ext, key),
+                        NONE,
+                        kNonStrictMode),
             Handle<JSObject>());
       }
     }
@@ -9385,7 +9444,8 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
           SetProperty(closure_scope,
                       scope_info.parameter_name(i),
                       Handle<Object>(element),
-                      NONE),
+                      NONE,
+                      kNonStrictMode),
           Handle<JSObject>());
     }
   }
@@ -9406,7 +9466,11 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
       ASSERT(keys->get(i)->IsString());
       Handle<String> key(String::cast(keys->get(i)));
       RETURN_IF_EMPTY_HANDLE_VALUE(
-          SetProperty(closure_scope, key, GetProperty(ext, key), NONE),
+          SetProperty(closure_scope,
+                      key,
+                      GetProperty(ext, key),
+                      NONE,
+                      kNonStrictMode),
           Handle<JSObject>());
     }
   }
index 06437ef..52a6e1f 100644 (file)
@@ -241,7 +241,7 @@ namespace internal {
   F(ResolvePossiblyDirectEval, 4, 2) \
   F(ResolvePossiblyDirectEvalNoLookup, 4, 2) \
   \
-  F(SetProperty, -1 /* 3 or 4 */, 1) \
+  F(SetProperty, -1 /* 4 or 5 */, 1) \
   F(DefineOrRedefineDataProperty, 4, 1) \
   F(DefineOrRedefineAccessorProperty, 5, 1) \
   F(IgnoreAttributesAndSetProperty, -1 /* 3 or 4 */, 1) \
@@ -288,12 +288,12 @@ namespace internal {
   F(DeleteContextSlot, 2, 1) \
   F(LoadContextSlot, 2, 2) \
   F(LoadContextSlotNoReferenceError, 2, 2) \
-  F(StoreContextSlot, 3, 1) \
+  F(StoreContextSlot, 4, 1) \
   \
   /* Declarations and initialization */ \
-  F(DeclareGlobals, 3, 1) \
+  F(DeclareGlobals, 4, 1) \
   F(DeclareContextSlot, 4, 1) \
-  F(InitializeVarGlobal, -1 /* 1 or 2 */, 1) \
+  F(InitializeVarGlobal, -1 /* 2 or 3 */, 1) \
   F(InitializeConstGlobal, 2, 1) \
   F(InitializeConstContextSlot, 3, 1) \
   F(OptimizeObjectForAddingMultipleProperties, 2, 1) \
@@ -538,7 +538,8 @@ class Runtime : public AllStatic {
       Handle<Object> object,
       Handle<Object> key,
       Handle<Object> value,
-      PropertyAttributes attr);
+      PropertyAttributes attr,
+      StrictModeFlag strict);
 
   MUST_USE_RESULT static MaybeObject* ForceSetObjectProperty(
       Handle<JSObject> object,
index abb26d6..360f0b7 100644 (file)
@@ -498,13 +498,13 @@ MaybeObject* StubCache::ComputeStoreField(String* name,
                                           JSObject* receiver,
                                           int field_index,
                                           Map* transition,
-                                          Code::ExtraICState extra_ic_state) {
+                                          StrictModeFlag strict_mode) {
   PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
   Code::Flags flags = Code::ComputeMonomorphicFlags(
-      Code::STORE_IC, type, extra_ic_state);
+      Code::STORE_IC, type, strict_mode);
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
-    StoreStubCompiler compiler(extra_ic_state);
+    StoreStubCompiler compiler(strict_mode);
     { MaybeObject* maybe_code =
           compiler.CompileStoreField(receiver, field_index, transition, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
@@ -521,13 +521,15 @@ MaybeObject* StubCache::ComputeStoreField(String* name,
 }
 
 
-MaybeObject* StubCache::ComputeKeyedStoreSpecialized(JSObject* receiver) {
+MaybeObject* StubCache::ComputeKeyedStoreSpecialized(
+    JSObject* receiver,
+    StrictModeFlag strict_mode) {
   Code::Flags flags =
-      Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, NORMAL);
+      Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, NORMAL, strict_mode);
   String* name = Heap::KeyedStoreSpecialized_symbol();
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
-    KeyedStoreStubCompiler compiler;
+    KeyedStoreStubCompiler compiler(strict_mode);
     { MaybeObject* maybe_code = compiler.CompileStoreSpecialized(receiver);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
@@ -542,7 +544,9 @@ MaybeObject* StubCache::ComputeKeyedStoreSpecialized(JSObject* receiver) {
 }
 
 
-MaybeObject* StubCache::ComputeKeyedStorePixelArray(JSObject* receiver) {
+MaybeObject* StubCache::ComputeKeyedStorePixelArray(
+    JSObject* receiver,
+    StrictModeFlag strict_mode) {
   // Using NORMAL as the PropertyType for array element stores is a misuse. The
   // generated stub always accesses fast elements, not slow-mode fields, but
   // some property type is required for the stub lookup. Note that overloading
@@ -550,11 +554,11 @@ MaybeObject* StubCache::ComputeKeyedStorePixelArray(JSObject* receiver) {
   // other keyed field stores. This is guaranteed to be the case since all field
   // keyed stores that are not array elements go through a generic builtin stub.
   Code::Flags flags =
-      Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, NORMAL);
+      Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, NORMAL, strict_mode);
   String* name = Heap::KeyedStorePixelArray_symbol();
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
-    KeyedStoreStubCompiler compiler;
+    KeyedStoreStubCompiler compiler(strict_mode);
     { MaybeObject* maybe_code = compiler.CompileStorePixelArray(receiver);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
@@ -598,11 +602,13 @@ ExternalArrayType ElementsKindToExternalArrayType(JSObject::ElementsKind kind) {
 
 MaybeObject* StubCache::ComputeKeyedLoadOrStoreExternalArray(
     JSObject* receiver,
-    bool is_store) {
+    bool is_store,
+    StrictModeFlag strict_mode) {
   Code::Flags flags =
       Code::ComputeMonomorphicFlags(
           is_store ? Code::KEYED_STORE_IC : Code::KEYED_LOAD_IC,
-          NORMAL);
+          NORMAL,
+          strict_mode);
   ExternalArrayType array_type =
       ElementsKindToExternalArrayType(receiver->GetElementsKind());
   String* name =
@@ -615,9 +621,9 @@ MaybeObject* StubCache::ComputeKeyedLoadOrStoreExternalArray(
   Object* code = map->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
     ExternalArrayStubCompiler compiler;
-    { MaybeObject* maybe_code =
-          is_store ? compiler.CompileKeyedStoreStub(array_type, flags) :
-          compiler.CompileKeyedLoadStub(array_type, flags);
+    { MaybeObject* maybe_code = is_store
+          ? compiler.CompileKeyedStoreStub(array_type, flags)
+          compiler.CompileKeyedLoadStub(array_type, flags);
       if (!maybe_code->ToObject(&code)) return maybe_code;
     }
     if (is_store) {
@@ -637,8 +643,8 @@ MaybeObject* StubCache::ComputeKeyedLoadOrStoreExternalArray(
 }
 
 
-MaybeObject* StubCache::ComputeStoreNormal(Code::ExtraICState extra_ic_state) {
-  return Builtins::builtin(extra_ic_state == StoreIC::kStoreICStrict
+MaybeObject* StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
+  return Builtins::builtin((strict_mode == kStrictMode)
                             ? Builtins::StoreIC_Normal_Strict
                             : Builtins::StoreIC_Normal);
 }
@@ -647,12 +653,12 @@ MaybeObject* StubCache::ComputeStoreNormal(Code::ExtraICState extra_ic_state) {
 MaybeObject* StubCache::ComputeStoreGlobal(String* name,
                                            GlobalObject* receiver,
                                            JSGlobalPropertyCell* cell,
-                                           Code::ExtraICState extra_ic_state) {
+                                           StrictModeFlag strict_mode) {
   Code::Flags flags = Code::ComputeMonomorphicFlags(
-      Code::STORE_IC, NORMAL, extra_ic_state);
+      Code::STORE_IC, NORMAL, strict_mode);
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
-    StoreStubCompiler compiler(extra_ic_state);
+    StoreStubCompiler compiler(strict_mode);
     { MaybeObject* maybe_code =
           compiler.CompileStoreGlobal(receiver, cell, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
@@ -673,13 +679,13 @@ MaybeObject* StubCache::ComputeStoreCallback(
     String* name,
     JSObject* receiver,
     AccessorInfo* callback,
-    Code::ExtraICState extra_ic_state) {
+    StrictModeFlag strict_mode) {
   ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
   Code::Flags flags = Code::ComputeMonomorphicFlags(
-      Code::STORE_IC, CALLBACKS, extra_ic_state);
+      Code::STORE_IC, CALLBACKS, strict_mode);
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
-    StoreStubCompiler compiler(extra_ic_state);
+    StoreStubCompiler compiler(strict_mode);
     { MaybeObject* maybe_code =
           compiler.CompileStoreCallback(receiver, callback, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
@@ -699,12 +705,12 @@ MaybeObject* StubCache::ComputeStoreCallback(
 MaybeObject* StubCache::ComputeStoreInterceptor(
     String* name,
     JSObject* receiver,
-    Code::ExtraICState extra_ic_state) {
+    StrictModeFlag strict_mode) {
   Code::Flags flags = Code::ComputeMonomorphicFlags(
-      Code::STORE_IC, INTERCEPTOR, extra_ic_state);
+      Code::STORE_IC, INTERCEPTOR, strict_mode);
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
-    StoreStubCompiler compiler(extra_ic_state);
+    StoreStubCompiler compiler(strict_mode);
     { MaybeObject* maybe_code =
           compiler.CompileStoreInterceptor(receiver, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
@@ -724,12 +730,14 @@ MaybeObject* StubCache::ComputeStoreInterceptor(
 MaybeObject* StubCache::ComputeKeyedStoreField(String* name,
                                                JSObject* receiver,
                                                int field_index,
-                                               Map* transition) {
+                                               Map* transition,
+                                               StrictModeFlag strict_mode) {
   PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION;
-  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type);
+  Code::Flags flags = Code::ComputeMonomorphicFlags(
+      Code::KEYED_STORE_IC, type, strict_mode);
   Object* code = receiver->map()->FindInCodeCache(name, flags);
   if (code->IsUndefined()) {
-    KeyedStoreStubCompiler compiler;
+    KeyedStoreStubCompiler compiler(strict_mode);
     { MaybeObject* maybe_code =
           compiler.CompileStoreField(receiver, field_index, transition, name);
       if (!maybe_code->ToObject(&code)) return maybe_code;
@@ -1417,12 +1425,17 @@ MaybeObject* LoadPropertyWithInterceptorForCall(Arguments args) {
 
 
 MaybeObject* StoreInterceptorProperty(Arguments args) {
+  ASSERT(args.length() == 4);
   JSObject* recv = JSObject::cast(args[0]);
   String* name = String::cast(args[1]);
   Object* value = args[2];
+  StrictModeFlag strict =
+      static_cast<StrictModeFlag>(Smi::cast(args[3])->value());
+  ASSERT(strict == kStrictMode || strict == kNonStrictMode);
   ASSERT(recv->HasNamedInterceptor());
   PropertyAttributes attr = NONE;
-  MaybeObject* result = recv->SetPropertyWithInterceptor(name, value, attr);
+  MaybeObject* result = recv->SetPropertyWithInterceptor(
+      name, value, attr, strict);
   return result;
 }
 
@@ -1675,8 +1688,8 @@ MaybeObject* KeyedLoadStubCompiler::GetCode(PropertyType type, String* name) {
 
 
 MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) {
-  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, type,
-                                                    extra_ic_state_);
+  Code::Flags flags = Code::ComputeMonomorphicFlags(
+      Code::STORE_IC, type, strict_mode_);
   MaybeObject* result = GetCodeWithFlags(flags, name);
   if (!result->IsFailure()) {
     PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG,
@@ -1691,7 +1704,8 @@ MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) {
 
 
 MaybeObject* KeyedStoreStubCompiler::GetCode(PropertyType type, String* name) {
-  Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type);
+  Code::Flags flags = Code::ComputeMonomorphicFlags(
+      Code::KEYED_STORE_IC, type, strict_mode_);
   MaybeObject* result = GetCodeWithFlags(flags, name);
   if (!result->IsFailure()) {
     PROFILE(CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
index 4638da2..6927076 100644 (file)
@@ -143,27 +143,27 @@ class StubCache : public AllStatic {
       JSObject* receiver,
       int field_index,
       Map* transition,
-      Code::ExtraICState extra_ic_state);
+      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ComputeStoreNormal(
-      Code::ExtraICState extra_ic_state);
+      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ComputeStoreGlobal(
       String* name,
       GlobalObject* receiver,
       JSGlobalPropertyCell* cell,
-      Code::ExtraICState extra_ic_state);
+      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ComputeStoreCallback(
       String* name,
       JSObject* receiver,
       AccessorInfo* callback,
-      Code::ExtraICState extra_ic_state);
+      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ComputeStoreInterceptor(
       String* name,
       JSObject* receiver,
-      Code::ExtraICState extra_ic_state);
+      StrictModeFlag strict_mode);
 
   // ---
 
@@ -171,17 +171,21 @@ class StubCache : public AllStatic {
       String* name,
       JSObject* receiver,
       int field_index,
-      Map* transition = NULL);
+      Map* transition,
+      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ComputeKeyedStoreSpecialized(
-      JSObject* receiver);
+      JSObject* receiver,
+      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ComputeKeyedStorePixelArray(
-      JSObject* receiver);
+      JSObject* receiver,
+      StrictModeFlag strict_mode);
 
   MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadOrStoreExternalArray(
       JSObject* receiver,
-      bool is_store);
+      bool is_store,
+      StrictModeFlag strict_mode);
 
   // ---
 
@@ -628,8 +632,8 @@ class KeyedLoadStubCompiler: public StubCompiler {
 
 class StoreStubCompiler: public StubCompiler {
  public:
-  explicit StoreStubCompiler(Code::ExtraICState extra_ic_state)
-    : extra_ic_state_(extra_ic_state) { }
+  explicit StoreStubCompiler(StrictModeFlag strict_mode)
+    : strict_mode_(strict_mode) { }
 
   MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
                                                  int index,
@@ -649,12 +653,15 @@ class StoreStubCompiler: public StubCompiler {
  private:
   MaybeObject* GetCode(PropertyType type, String* name);
 
-  Code::ExtraICState extra_ic_state_;
+  StrictModeFlag strict_mode_;
 };
 
 
 class KeyedStoreStubCompiler: public StubCompiler {
  public:
+  explicit KeyedStoreStubCompiler(StrictModeFlag strict_mode)
+    : strict_mode_(strict_mode) { }
+
   MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
                                                  int index,
                                                  Map* transition,
@@ -666,6 +673,8 @@ class KeyedStoreStubCompiler: public StubCompiler {
 
  private:
   MaybeObject* GetCode(PropertyType type, String* name);
+
+  StrictModeFlag strict_mode_;
 };
 
 
index dfee36e..6a71e6f 100644 (file)
@@ -2747,7 +2747,8 @@ void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
   frame_->EmitPush(rsi);  // The context is the first argument.
   frame_->EmitPush(kScratchRegister);
   frame_->EmitPush(Smi::FromInt(is_eval() ? 1 : 0));
-  Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 3);
+  frame_->EmitPush(Smi::FromInt(strict_mode_flag()));
+  Result ignored = frame_->CallRuntime(Runtime::kDeclareGlobals, 4);
   // Return value is ignored.
 }
 
@@ -4605,7 +4606,8 @@ void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) {
       // by initialization.
       value = frame_->CallRuntime(Runtime::kInitializeConstContextSlot, 3);
     } else {
-      value = frame_->CallRuntime(Runtime::kStoreContextSlot, 3);
+      frame_->Push(Smi::FromInt(strict_mode_flag()));
+      value = frame_->CallRuntime(Runtime::kStoreContextSlot, 4);
     }
     // Storing a variable must keep the (new) value on the expression
     // stack. This is necessary for compiling chained assignment
@@ -4925,8 +4927,9 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
         Load(property->key());
         Load(property->value());
         if (property->emit_store()) {
+          frame_->Push(Smi::FromInt(NONE));   // PropertyAttributes
           // Ignore the result.
-          Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3);
+          Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 4);
         } else {
           frame_->Drop(3);
         }
@@ -8086,8 +8089,12 @@ class DeferredReferenceSetKeyedValue: public DeferredCode {
  public:
   DeferredReferenceSetKeyedValue(Register value,
                                  Register key,
-                                 Register receiver)
-      : value_(value), key_(key), receiver_(receiver) {
+                                 Register receiver,
+                                 StrictModeFlag strict_mode)
+      : value_(value),
+        key_(key),
+        receiver_(receiver),
+        strict_mode_(strict_mode) {
     set_comment("[ DeferredReferenceSetKeyedValue");
   }
 
@@ -8100,6 +8107,7 @@ class DeferredReferenceSetKeyedValue: public DeferredCode {
   Register key_;
   Register receiver_;
   Label patch_site_;
+  StrictModeFlag strict_mode_;
 };
 
 
@@ -8151,7 +8159,9 @@ void DeferredReferenceSetKeyedValue::Generate() {
   }
 
   // Call the IC stub.
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
+                                    : Builtins::KeyedStoreIC_Initialize));
   __ Call(ic, RelocInfo::CODE_TARGET);
   // The delta from the start of the map-compare instructions (initial movq)
   // to the test instruction.  We use masm_-> directly here instead of the
@@ -8492,7 +8502,8 @@ Result CodeGenerator::EmitKeyedStore(StaticType* key_type) {
     DeferredReferenceSetKeyedValue* deferred =
         new DeferredReferenceSetKeyedValue(result.reg(),
                                            key.reg(),
-                                           receiver.reg());
+                                           receiver.reg(),
+                                           strict_mode_flag());
 
     // Check that the receiver is not a smi.
     __ JumpIfSmi(receiver.reg(), deferred->entry_label());
@@ -8554,7 +8565,7 @@ Result CodeGenerator::EmitKeyedStore(StaticType* key_type) {
 
     deferred->BindExit();
   } else {
-    result = frame()->CallKeyedStoreIC();
+    result = frame()->CallKeyedStoreIC(strict_mode_flag());
     // Make sure that we do not have a test instruction after the
     // call.  A test instruction after the call is used to
     // indicate that we have generated an inline version of the
index 25c01ad..0ad6ec2 100644 (file)
@@ -735,7 +735,9 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
              prop->key()->AsLiteral()->handle()->IsSmi());
       __ Move(rcx, prop->key()->AsLiteral()->handle());
 
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(is_strict()
+          ? Builtins::KeyedStoreIC_Initialize_Strict
+          : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
     }
   }
@@ -752,7 +754,8 @@ void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
   __ push(rsi);  // The context is the first argument.
   __ Push(pairs);
   __ Push(Smi::FromInt(is_eval() ? 1 : 0));
-  __ CallRuntime(Runtime::kDeclareGlobals, 3);
+  __ Push(Smi::FromInt(strict_mode_flag()));
+  __ CallRuntime(Runtime::kDeclareGlobals, 4);
   // Return value is ignored.
 }
 
@@ -1396,7 +1399,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
         VisitForStackValue(key);
         VisitForStackValue(value);
         if (property->emit_store()) {
-          __ CallRuntime(Runtime::kSetProperty, 3);
+          __ Push(Smi::FromInt(NONE));    // PropertyAttributes
+          __ CallRuntime(Runtime::kSetProperty, 4);
         } else {
           __ Drop(3);
         }
@@ -1733,7 +1737,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
       __ movq(rdx, rax);
       __ pop(rax);  // Restore value.
       __ Move(rcx, prop->key()->AsLiteral()->handle());
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::StoreIC_Initialize_Strict
+                      : Builtins::StoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -1754,7 +1760,9 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
         __ pop(rdx);
       }
       __ pop(rax);  // Restore value.
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                      : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       break;
     }
@@ -1849,7 +1857,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
         __ push(rax);  // Value.
         __ push(rsi);  // Context.
         __ Push(var->name());
-        __ CallRuntime(Runtime::kStoreContextSlot, 3);
+        __ Push(Smi::FromInt(strict_mode_flag()));
+        __ CallRuntime(Runtime::kStoreContextSlot, 4);
         break;
     }
   }
@@ -1880,7 +1889,9 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
   } else {
     __ pop(rdx);
   }
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      is_strict() ? Builtins::StoreIC_Initialize_Strict
+                  : Builtins::StoreIC_Initialize));
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -1918,7 +1929,9 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
   }
   // Record source code position before IC call.
   SetSourcePosition(expr->position());
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                  : Builtins::KeyedStoreIC_Initialize));
   EmitCallIC(ic, RelocInfo::CODE_TARGET);
 
   // If the assignment ends an initialization block, revert to fast case.
@@ -3529,7 +3542,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
     case NAMED_PROPERTY: {
       __ Move(rcx, prop->key()->AsLiteral()->handle());
       __ pop(rdx);
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::StoreIC_Initialize_Strict
+                      : Builtins::StoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
@@ -3544,7 +3559,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
     case KEYED_PROPERTY: {
       __ pop(rcx);
       __ pop(rdx);
-      Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      Handle<Code> ic(Builtins::builtin(
+          is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                      : Builtins::KeyedStoreIC_Initialize));
       EmitCallIC(ic, RelocInfo::CODE_TARGET);
       PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
       if (expr->is_postfix()) {
index 55d837c..b3243cf 100644 (file)
@@ -766,7 +766,8 @@ void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
 }
 
 
-void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
+                                   StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- rax     : value
   //  -- rcx     : key
@@ -813,7 +814,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
   __ bind(&slow);
   __ Integer32ToSmi(rcx, rcx);
   __ bind(&slow_with_tagged_index);
-  GenerateRuntimeSetProperty(masm);
+  GenerateRuntimeSetProperty(masm, strict_mode);
   // Never returns to here.
 
   // Check whether the elements is a pixel array.
@@ -1474,7 +1475,7 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
 
 
 void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
-                                  Code::ExtraICState extra_ic_state) {
+                                  StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : name
@@ -1486,7 +1487,7 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm,
   Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
                                          NOT_IN_LOOP,
                                          MONOMORPHIC,
-                                         extra_ic_state);
+                                         strict_mode);
   StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg);
 
   // Cache miss: Jump to runtime.
@@ -1593,7 +1594,8 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) {
 }
 
 
-void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) {
+void StoreIC::GenerateGlobalProxy(MacroAssembler* masm,
+                                  StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- rax    : value
   //  -- rcx    : name
@@ -1604,14 +1606,17 @@ void StoreIC::GenerateGlobalProxy(MacroAssembler* masm) {
   __ push(rdx);
   __ push(rcx);
   __ push(rax);
-  __ push(rbx);
+  __ Push(Smi::FromInt(NONE));  // PropertyAttributes
+  __ Push(Smi::FromInt(strict_mode));
+  __ push(rbx);  // return address
 
   // Do tail-call to runtime routine.
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 }
 
 
-void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
+                                              StrictModeFlag strict_mode) {
   // ----------- S t a t e -------------
   //  -- rax     : value
   //  -- rcx     : key
@@ -1623,10 +1628,12 @@ void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
   __ push(rdx);  // receiver
   __ push(rcx);  // key
   __ push(rax);  // value
+  __ Push(Smi::FromInt(NONE));          // PropertyAttributes
+  __ Push(Smi::FromInt(strict_mode));   // Strict mode.
   __ push(rbx);  // return address
 
   // Do tail-call to runtime routine.
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 }
 
 
index 7e371fd..e23fb89 100644 (file)
@@ -2687,7 +2687,9 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
   ASSERT(ToRegister(instr->value()).is(rax));
 
   __ Move(rcx, instr->hydrogen()->name());
-  Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      info_->is_strict() ? Builtins::StoreIC_Initialize_Strict
+                         : Builtins::StoreIC_Initialize));
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2756,7 +2758,9 @@ void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
   ASSERT(ToRegister(instr->key()).is(rcx));
   ASSERT(ToRegister(instr->value()).is(rax));
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
+                         : Builtins::KeyedStoreIC_Initialize));
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
 }
 
index 774de71..109985c 100644 (file)
@@ -2408,12 +2408,13 @@ MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
   __ push(rdx);  // receiver
   __ push(rcx);  // name
   __ push(rax);  // value
+  __ Push(Smi::FromInt(strict_mode_));
   __ push(rbx);  // restore return address
 
   // Do tail-call to the runtime system.
   ExternalReference store_ic_property =
       ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
-  __ TailCallExternalReference(store_ic_property, 3, 1);
+  __ TailCallExternalReference(store_ic_property, 4, 1);
 
   // Handle store cache miss.
   __ bind(&miss);
@@ -3490,10 +3491,13 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
   __ push(rdx);  // receiver
   __ push(rcx);  // key
   __ push(rax);  // value
+  __ Push(Smi::FromInt(NONE));   // PropertyAttributes
+  __ Push(Smi::FromInt(
+      Code::ExtractExtraICStateFromFlags(flags) & kStrictMode));
   __ push(rbx);  // return address
 
   // Do tail-call to runtime routine.
-  __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
+  __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
 
   return GetCode(flags);
 }
index ea115f2..1787044 100644 (file)
@@ -1124,9 +1124,9 @@ Result VirtualFrame::CallStoreIC(Handle<String> name,
                                  StrictModeFlag strict_mode) {
   // Value and (if not contextual) receiver are on top of the frame.
   // The IC expects name in rcx, value in rax, and receiver in rdx.
-  Handle<Code> ic(Builtins::builtin(strict_mode == kStrictMode
-      ? Builtins::StoreIC_Initialize_Strict
-      : Builtins::StoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode == kStrictMode) ? Builtins::StoreIC_Initialize_Strict
+                                   : Builtins::StoreIC_Initialize));
   Result value = Pop();
   RelocInfo::Mode mode;
   if (is_contextual) {
@@ -1146,7 +1146,7 @@ Result VirtualFrame::CallStoreIC(Handle<String> name,
 }
 
 
-Result VirtualFrame::CallKeyedStoreIC() {
+Result VirtualFrame::CallKeyedStoreIC(StrictModeFlag strict_mode) {
   // Value, key, and receiver are on the top of the frame.  The IC
   // expects value in rax, key in rcx, and receiver in rdx.
   Result value = Pop();
@@ -1190,7 +1190,9 @@ Result VirtualFrame::CallKeyedStoreIC() {
     receiver.Unuse();
   }
 
-  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+  Handle<Code> ic(Builtins::builtin(
+      (strict_mode == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
+                                   : Builtins::KeyedStoreIC_Initialize));
   return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
 }
 
index 824743d..b568a78 100644 (file)
@@ -343,7 +343,7 @@ class VirtualFrame : public ZoneObject {
 
   // Call keyed store IC.  Value, key, and receiver are found on top
   // of the frame.  All three are dropped.
-  Result CallKeyedStoreIC();
+  Result CallKeyedStoreIC(StrictModeFlag strict_mode);
 
   // Call call IC.  Function name, arguments, and receiver are found on top
   // of the frame and dropped by the call.
index b3c52f1..f450a34 100644 (file)
@@ -10091,10 +10091,11 @@ class RegExpStringModificationTest {
     // Inject the input as a global variable.
     i::Handle<i::String> input_name =
         i::Factory::NewStringFromAscii(i::Vector<const char>("input", 5));
-    i::Top::global_context()->global()->SetProperty(*input_name,
-                                                    *input_,
-                                                    NONE)->ToObjectChecked();
-
+    i::Top::global_context()->global()->SetProperty(
+        *input_name,
+        *input_,
+        NONE,
+        i::kNonStrictMode)->ToObjectChecked();
 
     MorphThread morph_thread(this);
     morph_thread.Start();
index b424b7f..9f21b78 100644 (file)
@@ -108,7 +108,7 @@ static void SetGlobalProperty(const char* name, Object* value) {
   Handle<Object> object(value);
   Handle<String> symbol = Factory::LookupAsciiSymbol(name);
   Handle<JSObject> global(Top::context()->global());
-  SetProperty(global, symbol, object, NONE);
+  SetProperty(global, symbol, object, NONE, kNonStrictMode);
 }
 
 
index 441aae6..7245e54 100644 (file)
@@ -153,7 +153,8 @@ class DebugLocalContext {
     Handle<v8::internal::String> debug_string =
         v8::internal::Factory::LookupAsciiSymbol("debug");
     SetProperty(global, debug_string,
-        Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM);
+        Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM,
+        ::v8::internal::kNonStrictMode);
   }
  private:
   v8::Persistent<v8::Context> context_;
index a23ee17..9cce01e 100644 (file)
@@ -212,13 +212,14 @@ TEST(GarbageCollection) {
     Handle<Map> initial_map =
         Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
     function->set_initial_map(*initial_map);
-    Top::context()->global()->SetProperty(*name,
-                                          *function,
-                                          NONE)->ToObjectChecked();
+    Top::context()->global()->SetProperty(
+        *name, *function, NONE, kNonStrictMode)->ToObjectChecked();
     // Allocate an object.  Unrooted after leaving the scope.
     Handle<JSObject> obj = Factory::NewJSObject(function);
-    obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
-    obj->SetProperty(*prop_namex, Smi::FromInt(24), NONE)->ToObjectChecked();
+    obj->SetProperty(
+        *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
+    obj->SetProperty(
+        *prop_namex, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked();
 
     CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
     CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex));
@@ -238,10 +239,10 @@ TEST(GarbageCollection) {
     HandleScope inner_scope;
     // Allocate another object, make it reachable from global.
     Handle<JSObject> obj = Factory::NewJSObject(function);
-    Top::context()->global()->SetProperty(*obj_name,
-                                          *obj,
-                                          NONE)->ToObjectChecked();
-    obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
+    Top::context()->global()->SetProperty(
+        *obj_name, *obj, NONE, kNonStrictMode)->ToObjectChecked();
+    obj->SetProperty(
+        *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
   }
 
   // After gc, it should survive.
@@ -540,12 +541,12 @@ TEST(FunctionAllocation) {
 
   Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot");
   Handle<JSObject> obj = Factory::NewJSObject(function);
-  obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
   CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
   // Check that we can add properties to function objects.
-  function->SetProperty(*prop_name,
-                        Smi::FromInt(24),
-                        NONE)->ToObjectChecked();
+  function->SetProperty(
+      *prop_name, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked();
   CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name));
 }
 
@@ -567,7 +568,8 @@ TEST(ObjectProperties) {
   CHECK(!obj->HasLocalProperty(*first));
 
   // add first
-  obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
   CHECK(obj->HasLocalProperty(*first));
 
   // delete first
@@ -575,8 +577,10 @@ TEST(ObjectProperties) {
   CHECK(!obj->HasLocalProperty(*first));
 
   // add first and then second
-  obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked();
-  obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
+  obj->SetProperty(
+      *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
   CHECK(obj->HasLocalProperty(*first));
   CHECK(obj->HasLocalProperty(*second));
 
@@ -588,8 +592,10 @@ TEST(ObjectProperties) {
   CHECK(!obj->HasLocalProperty(*second));
 
   // add first and then second
-  obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked();
-  obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
+  obj->SetProperty(
+      *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
   CHECK(obj->HasLocalProperty(*first));
   CHECK(obj->HasLocalProperty(*second));
 
@@ -603,14 +609,16 @@ TEST(ObjectProperties) {
   // check string and symbol match
   static const char* string1 = "fisk";
   Handle<String> s1 = Factory::NewStringFromAscii(CStrVector(string1));
-  obj->SetProperty(*s1, Smi::FromInt(1), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *s1, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
   Handle<String> s1_symbol = Factory::LookupAsciiSymbol(string1);
   CHECK(obj->HasLocalProperty(*s1_symbol));
 
   // check symbol and string match
   static const char* string2 = "fugl";
   Handle<String> s2_symbol = Factory::LookupAsciiSymbol(string2);
-  obj->SetProperty(*s2_symbol, Smi::FromInt(1), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *s2_symbol, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
   Handle<String> s2 = Factory::NewStringFromAscii(CStrVector(string2));
   CHECK(obj->HasLocalProperty(*s2));
 }
@@ -631,7 +639,8 @@ TEST(JSObjectMaps) {
   Handle<JSObject> obj = Factory::NewJSObject(function);
 
   // Set a propery
-  obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked();
   CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
 
   // Check the map has changed
@@ -698,8 +707,10 @@ TEST(JSObjectCopy) {
   Handle<String> first = Factory::LookupAsciiSymbol("first");
   Handle<String> second = Factory::LookupAsciiSymbol("second");
 
-  obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked();
-  obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked();
+  obj->SetProperty(
+      *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
+  obj->SetProperty(
+      *second, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
 
   Object* ok = obj->SetElement(0, *first)->ToObjectChecked();
 
@@ -716,8 +727,10 @@ TEST(JSObjectCopy) {
   CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second));
 
   // Flip the values.
-  clone->SetProperty(*first, Smi::FromInt(2), NONE)->ToObjectChecked();
-  clone->SetProperty(*second, Smi::FromInt(1), NONE)->ToObjectChecked();
+  clone->SetProperty(
+      *first, Smi::FromInt(2), NONE, kNonStrictMode)->ToObjectChecked();
+  clone->SetProperty(
+      *second, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked();
 
   ok = clone->SetElement(0, *second)->ToObjectChecked();
   ok = clone->SetElement(1, *first)->ToObjectChecked();
index 86f105f..3e3175e 100644 (file)
@@ -189,7 +189,8 @@ TEST(MarkCompactCollector) {
   function->set_initial_map(initial_map);
   Top::context()->global()->SetProperty(func_name,
                                         function,
-                                        NONE)->ToObjectChecked();
+                                        NONE,
+                                        kNonStrictMode)->ToObjectChecked();
 
   JSObject* obj =
       JSObject::cast(Heap::AllocateJSObject(function)->ToObjectChecked());
@@ -208,10 +209,14 @@ TEST(MarkCompactCollector) {
       String::cast(Heap::LookupAsciiSymbol("theObject")->ToObjectChecked());
   Top::context()->global()->SetProperty(obj_name,
                                         obj,
-                                        NONE)->ToObjectChecked();
+                                        NONE,
+                                        kNonStrictMode)->ToObjectChecked();
   String* prop_name =
       String::cast(Heap::LookupAsciiSymbol("theSlot")->ToObjectChecked());
-  obj->SetProperty(prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
+  obj->SetProperty(prop_name,
+                   Smi::FromInt(23),
+                   NONE,
+                   kNonStrictMode)->ToObjectChecked();
 
   Heap::CollectGarbage(OLD_POINTER_SPACE);
 
index e021fc5..d6f7caf 100644 (file)
@@ -269,72 +269,6 @@ chapter11/11.13/11.13.1/11.13.1-4-3-s: FAIL
 # in strict mode (Global.length)
 chapter11/11.13/11.13.1/11.13.1-4-4-s: FAIL
 # simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Object.length)
-chapter11/11.13/11.13.1/11.13.1-4-5-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Function.length)
-chapter11/11.13/11.13.1/11.13.1-4-6-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Array.length)
-chapter11/11.13/11.13.1/11.13.1-4-7-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (String.length)
-chapter11/11.13/11.13.1/11.13.1-4-8-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Boolean.length)
-chapter11/11.13/11.13.1/11.13.1-4-9-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Number.length)
-chapter11/11.13/11.13.1/11.13.1-4-10-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Date.length)
-chapter11/11.13/11.13.1/11.13.1-4-11-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (RegExp.length)
-chapter11/11.13/11.13.1/11.13.1-4-12-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Error.length)
-chapter11/11.13/11.13.1/11.13.1-4-13-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Number.MAX_VALUE)
-chapter11/11.13/11.13.1/11.13.1-4-14-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Number.MIN_VALUE)
-chapter11/11.13/11.13.1/11.13.1-4-15-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Number.NaN)
-chapter11/11.13/11.13.1/11.13.1-4-16-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Number.NEGATIVE_INFINITY)
-chapter11/11.13/11.13.1/11.13.1-4-17-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Number.POSITIVE_INFINITY)
-chapter11/11.13/11.13.1/11.13.1-4-18-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.E)
-chapter11/11.13/11.13.1/11.13.1-4-19-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.LN10)
-chapter11/11.13/11.13.1/11.13.1-4-20-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.LN2)
-chapter11/11.13/11.13.1/11.13.1-4-21-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.LOG2E)
-chapter11/11.13/11.13.1/11.13.1-4-22-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.LOG10E)
-chapter11/11.13/11.13.1/11.13.1-4-23-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.PI)
-chapter11/11.13/11.13.1/11.13.1-4-24-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.SQRT1_2)
-chapter11/11.13/11.13.1/11.13.1-4-25-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
-# in strict mode (Math.SQRT2)
-chapter11/11.13/11.13.1/11.13.1-4-26-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property
 # in strict mode (Global.undefined)
 chapter11/11.13/11.13.1/11.13.1-4-27-s: FAIL
 
index 42d8355..4071232 100644 (file)
@@ -713,3 +713,118 @@ repeat(10, function() { testAssignToUndefined(false); });
     cleanup(Boolean);
   }
 })();
+
+
+(function ObjectEnvironment() {
+  var o = {};
+  Object.defineProperty(o, "foo", { value: "FOO", writable: false });
+  assertThrows(
+    function () {
+      with (o) {
+        (function() {
+          "use strict";
+          foo = "Hello";
+        })();
+      }
+    },
+    TypeError);
+})();
+
+
+(function TestSetPropertyWithoutSetter() {
+  var o = { get foo() { return "Yey"; } };
+  assertThrows(
+    function broken() {
+      "use strict";
+      o.foo = (0xBADBAD00 >> 1);
+    },
+    TypeError);
+})();
+
+
+(function TestSetPropertyNonConfigurable() {
+  var frozen = Object.freeze({});
+  var sealed = Object.seal({});
+
+  function strict(o) {
+    "use strict";
+    o.property = "value";
+  }
+
+  assertThrows(function() { strict(frozen); }, TypeError);
+  assertThrows(function() { strict(sealed); }, TypeError);
+})();
+
+
+(function TestAssignmentToReadOnlyProperty() {
+  "use strict";
+
+  var o = {};
+  Object.defineProperty(o, "property", { value: 7 });
+
+  assertThrows(function() { o.property = "new value"; }, TypeError);
+  assertThrows(function() { o.property += 10; }, TypeError);
+  assertThrows(function() { o.property -= 10; }, TypeError);
+  assertThrows(function() { o.property *= 10; }, TypeError);
+  assertThrows(function() { o.property /= 10; }, TypeError);
+  assertThrows(function() { o.property++; }, TypeError);
+  assertThrows(function() { o.property--; }, TypeError);
+  assertThrows(function() { ++o.property; }, TypeError);
+  assertThrows(function() { --o.property; }, TypeError);
+
+  var name = "prop" + "erty"; // to avoid symbol path.
+  assertThrows(function() { o[name] = "new value"; }, TypeError);
+  assertThrows(function() { o[name] += 10; }, TypeError);
+  assertThrows(function() { o[name] -= 10; }, TypeError);
+  assertThrows(function() { o[name] *= 10; }, TypeError);
+  assertThrows(function() { o[name] /= 10; }, TypeError);
+  assertThrows(function() { o[name]++; }, TypeError);
+  assertThrows(function() { o[name]--; }, TypeError);
+  assertThrows(function() { ++o[name]; }, TypeError);
+  assertThrows(function() { --o[name]; }, TypeError);
+
+  assertEquals(o.property, 7);
+})();
+
+
+(function TestAssignmentToReadOnlyLoop() {
+  var name = "prop" + "erty"; // to avoid symbol path.
+  var o = {};
+  Object.defineProperty(o, "property", { value: 7 });
+
+  function strict(o, name) {
+    "use strict";
+    o[name] = "new value";
+  }
+
+  for (var i = 0; i < 10; i ++) {
+    try {
+      strict(o, name);
+      assertUnreachable();
+    } catch(e) {
+      assertInstanceof(e, TypeError);
+    }
+  }
+})();
+
+
+// Specialized KeyedStoreIC experiencing miss.
+(function testKeyedStoreICStrict() {
+  var o = [9,8,7,6,5,4,3,2,1];
+
+  function test(o, i, v) {
+    "use strict";
+    o[i] = v;
+  }
+
+  for (var i = 0; i < 10; i ++) {
+    test(o, 5, 17);        // start specialized for smi indices
+    assertEquals(o[5], 17);
+    test(o, "a", 19);
+    assertEquals(o["a"], 19);
+    test(o, "5", 29);
+    assertEquals(o[5], 29);
+    test(o, 100000, 31);
+    assertEquals(o[100000], 31);
+  }
+})();