Assignment to read only properties throws in strict mode.

Review URL: http://codereview.chromium.org/6594037/

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6976 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mmaly@chromium.org 2011-03-01 01:42:37 +00:00
parent bb0c22f11c
commit 98aea3c353
46 changed files with 955 additions and 523 deletions

View 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;

View 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());
}
}

View File

@ -793,7 +793,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).
}
@ -809,10 +811,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.
}
@ -1456,7 +1459,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);
}
@ -2050,7 +2055,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;
}
@ -2071,7 +2078,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;
}
@ -2095,9 +2104,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) {
@ -2166,9 +2175,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;
}
}
@ -2203,7 +2213,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.
@ -2247,7 +2259,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.
@ -3767,7 +3781,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()) {
@ -3782,7 +3798,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()) {

View 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);
}

View File

@ -2863,9 +2863,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);
}
@ -2907,7 +2907,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);
}

View 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);
}

View 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);

View 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,

View 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);

View 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

View 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.

View 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);
}

View File

@ -246,12 +246,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,
@ -282,7 +284,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,

View 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);
}
@ -9468,11 +9471,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");
}
@ -9486,6 +9491,7 @@ class DeferredReferenceSetKeyedValue: public DeferredCode {
Register receiver_;
Register scratch_;
Label patch_site_;
StrictModeFlag strict_mode_;
};
@ -9544,7 +9550,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
@ -9906,7 +9914,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));
@ -9961,7 +9970,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

View File

@ -741,7 +741,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);
}
}
@ -758,7 +760,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.
}
@ -1380,7 +1383,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 {
@ -1394,7 +1399,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);
}
@ -1985,7 +1991,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;
}
@ -2006,7 +2014,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;
}
@ -2101,7 +2111,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;
}
}
@ -2132,7 +2143,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.
@ -2170,7 +2183,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.
@ -4025,7 +4040,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()) {
@ -4040,7 +4057,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()) {

View 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);
}

View File

@ -2786,7 +2786,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);
}
@ -2854,7 +2856,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);
}

View 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);
}

View 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);
}

View 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

View 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());
}

102
src/ic.cc
View File

@ -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));
}

View File

@ -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);

View 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);

View 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);
}

View 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;

View 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,

View 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())) {
CallRuntime* initialize;
if (is_const) {
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) {
// 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));
}

View File

@ -160,7 +160,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;
}
}
@ -546,7 +547,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;
@ -994,12 +997,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
@ -1109,7 +1116,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));
}
}
@ -1170,7 +1181,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));
}
}
@ -1211,7 +1223,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();
@ -1220,14 +1233,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.
@ -1283,8 +1303,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();
@ -1298,7 +1319,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();
}
@ -1357,13 +1380,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();
@ -1439,7 +1468,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;
}
@ -1476,8 +1507,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));
}
}
@ -1643,7 +1675,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;
}
@ -3739,7 +3771,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()) {
@ -3769,6 +3802,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;
@ -3781,7 +3815,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;
@ -3794,9 +3828,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);
}
}
@ -3888,23 +3923,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);
}
@ -3938,7 +3977,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);
}
@ -7486,11 +7525,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;
@ -7534,7 +7578,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;
}
@ -9267,7 +9316,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);
}
}
@ -9293,7 +9344,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>());
}
@ -9302,7 +9355,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>());
}
@ -9326,7 +9381,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>());
}
}
@ -9364,7 +9423,8 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
SetProperty(closure_scope,
scope_info.parameter_name(i),
Handle<Object>(element),
NONE),
NONE,
kNonStrictMode),
Handle<JSObject>());
}
}
@ -9385,7 +9445,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>());
}
}

View 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,

View 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,

View 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_;
};

View 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

View File

@ -742,7 +742,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);
}
}
@ -759,7 +761,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.
}
@ -1403,7 +1406,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);
}
@ -1750,7 +1754,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;
}
@ -1771,7 +1777,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;
}
@ -1866,7 +1874,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;
}
}
@ -1897,7 +1906,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.
@ -1935,7 +1946,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.
@ -3450,7 +3463,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()) {
@ -3465,7 +3480,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()) {

View 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);
}

View File

@ -2641,7 +2641,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);
}
@ -2710,7 +2712,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);
}

View 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);
}

View 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);
}

View 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.

View 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();

View 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);
}

View 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_;

View 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();

View 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);

View 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

View 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);
}
})();