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:
parent
bb0c22f11c
commit
98aea3c353
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
215
src/builtins.h
215
src/builtins.h
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
102
src/ic.cc
@ -343,7 +343,7 @@ void StoreIC::Clear(Address address, Code* target) {
|
||||
if (target->ic_state() == UNINITIALIZED) return;
|
||||
ClearInlinedVersion(address);
|
||||
SetTargetAtAddress(address,
|
||||
target->extra_ic_state() == kStoreICStrict
|
||||
(target->extra_ic_state() == kStrictMode)
|
||||
? initialize_stub_strict()
|
||||
: initialize_stub());
|
||||
}
|
||||
@ -366,7 +366,10 @@ void KeyedStoreIC::RestoreInlinedVersion(Address address) {
|
||||
|
||||
void KeyedStoreIC::Clear(Address address, Code* target) {
|
||||
if (target->ic_state() == UNINITIALIZED) return;
|
||||
SetTargetAtAddress(address, initialize_stub());
|
||||
SetTargetAtAddress(address,
|
||||
(target->extra_ic_state() == kStrictMode)
|
||||
? initialize_stub_strict()
|
||||
: initialize_stub());
|
||||
}
|
||||
|
||||
|
||||
@ -1227,7 +1230,8 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
||||
if (receiver->HasExternalArrayElements()) {
|
||||
MaybeObject* probe =
|
||||
StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver,
|
||||
false);
|
||||
false,
|
||||
kNonStrictMode);
|
||||
stub = probe->IsFailure() ?
|
||||
NULL : Code::cast(probe->ToObjectUnchecked());
|
||||
} else if (receiver->HasIndexedInterceptor()) {
|
||||
@ -1383,7 +1387,7 @@ static bool LookupForWrite(JSObject* object,
|
||||
|
||||
|
||||
MaybeObject* StoreIC::Store(State state,
|
||||
Code::ExtraICState extra_ic_state,
|
||||
StrictModeFlag strict_mode,
|
||||
Handle<Object> object,
|
||||
Handle<String> name,
|
||||
Handle<Object> value) {
|
||||
@ -1413,11 +1417,11 @@ MaybeObject* StoreIC::Store(State state,
|
||||
#ifdef DEBUG
|
||||
if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
|
||||
#endif
|
||||
Builtins::Name target = (extra_ic_state == kStoreICStrict)
|
||||
Builtins::Name target = (strict_mode == kStrictMode)
|
||||
? Builtins::StoreIC_ArrayLength_Strict
|
||||
: Builtins::StoreIC_ArrayLength;
|
||||
set_target(Builtins::builtin(target));
|
||||
return receiver->SetProperty(*name, *value, NONE);
|
||||
return receiver->SetProperty(*name, *value, NONE, strict_mode);
|
||||
}
|
||||
|
||||
// Lookup the property locally in the receiver.
|
||||
@ -1441,13 +1445,15 @@ MaybeObject* StoreIC::Store(State state,
|
||||
// Index is an offset from the end of the object.
|
||||
int offset = map->instance_size() + (index * kPointerSize);
|
||||
if (PatchInlinedStore(address(), map, offset)) {
|
||||
set_target(megamorphic_stub());
|
||||
set_target((strict_mode == kStrictMode)
|
||||
? megamorphic_stub_strict()
|
||||
: megamorphic_stub());
|
||||
#ifdef DEBUG
|
||||
if (FLAG_trace_ic) {
|
||||
PrintF("[StoreIC : inline patch %s]\n", *name->ToCString());
|
||||
}
|
||||
#endif
|
||||
return receiver->SetProperty(*name, *value, NONE);
|
||||
return receiver->SetProperty(*name, *value, NONE, strict_mode);
|
||||
#ifdef DEBUG
|
||||
|
||||
} else {
|
||||
@ -1474,11 +1480,16 @@ MaybeObject* StoreIC::Store(State state,
|
||||
|
||||
// If no inlined store ic was patched, generate a stub for this
|
||||
// store.
|
||||
UpdateCaches(&lookup, state, extra_ic_state, receiver, name, value);
|
||||
UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
|
||||
} else {
|
||||
// Strict mode doesn't allow setting non-existent global property.
|
||||
if (extra_ic_state == kStoreICStrict && IsContextual(object)) {
|
||||
return ReferenceError("not_defined", name);
|
||||
// Strict mode doesn't allow setting non-existent global property
|
||||
// or an assignment to a read only property.
|
||||
if (strict_mode == kStrictMode) {
|
||||
if (lookup.IsFound() && lookup.IsReadOnly()) {
|
||||
return TypeError("strict_read_only_property", object, name);
|
||||
} else if (IsContextual(object)) {
|
||||
return ReferenceError("not_defined", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1486,7 +1497,7 @@ MaybeObject* StoreIC::Store(State state,
|
||||
if (receiver->IsJSGlobalProxy()) {
|
||||
// Generate a generic stub that goes to the runtime when we see a global
|
||||
// proxy as receiver.
|
||||
Code* stub = (extra_ic_state == kStoreICStrict)
|
||||
Code* stub = (strict_mode == kStrictMode)
|
||||
? global_proxy_stub_strict()
|
||||
: global_proxy_stub();
|
||||
if (target() != stub) {
|
||||
@ -1498,13 +1509,13 @@ MaybeObject* StoreIC::Store(State state,
|
||||
}
|
||||
|
||||
// Set the property.
|
||||
return receiver->SetProperty(*name, *value, NONE);
|
||||
return receiver->SetProperty(*name, *value, NONE, strict_mode);
|
||||
}
|
||||
|
||||
|
||||
void StoreIC::UpdateCaches(LookupResult* lookup,
|
||||
State state,
|
||||
Code::ExtraICState extra_ic_state,
|
||||
StrictModeFlag strict_mode,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<String> name,
|
||||
Handle<Object> value) {
|
||||
@ -1526,7 +1537,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
||||
switch (type) {
|
||||
case FIELD: {
|
||||
maybe_code = StubCache::ComputeStoreField(
|
||||
*name, *receiver, lookup->GetFieldIndex(), NULL, extra_ic_state);
|
||||
*name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
|
||||
break;
|
||||
}
|
||||
case MAP_TRANSITION: {
|
||||
@ -1536,7 +1547,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
||||
Handle<Map> transition(lookup->GetTransitionMap());
|
||||
int index = transition->PropertyIndexFor(*name);
|
||||
maybe_code = StubCache::ComputeStoreField(
|
||||
*name, *receiver, index, *transition, extra_ic_state);
|
||||
*name, *receiver, index, *transition, strict_mode);
|
||||
break;
|
||||
}
|
||||
case NORMAL: {
|
||||
@ -1548,10 +1559,10 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
||||
JSGlobalPropertyCell* cell =
|
||||
JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
|
||||
maybe_code = StubCache::ComputeStoreGlobal(
|
||||
*name, *global, cell, extra_ic_state);
|
||||
*name, *global, cell, strict_mode);
|
||||
} else {
|
||||
if (lookup->holder() != *receiver) return;
|
||||
maybe_code = StubCache::ComputeStoreNormal(extra_ic_state);
|
||||
maybe_code = StubCache::ComputeStoreNormal(strict_mode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1560,13 +1571,13 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
||||
AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
|
||||
if (v8::ToCData<Address>(callback->setter()) == 0) return;
|
||||
maybe_code = StubCache::ComputeStoreCallback(
|
||||
*name, *receiver, callback, extra_ic_state);
|
||||
*name, *receiver, callback, strict_mode);
|
||||
break;
|
||||
}
|
||||
case INTERCEPTOR: {
|
||||
ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
|
||||
maybe_code = StubCache::ComputeStoreInterceptor(
|
||||
*name, *receiver, extra_ic_state);
|
||||
*name, *receiver, strict_mode);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1583,7 +1594,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
||||
} else if (state == MONOMORPHIC) {
|
||||
// Only move to megamorphic if the target changes.
|
||||
if (target() != Code::cast(code)) {
|
||||
set_target(extra_ic_state == kStoreICStrict
|
||||
set_target((strict_mode == kStrictMode)
|
||||
? megamorphic_stub_strict()
|
||||
: megamorphic_stub());
|
||||
}
|
||||
@ -1599,6 +1610,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
||||
|
||||
|
||||
MaybeObject* KeyedStoreIC::Store(State state,
|
||||
StrictModeFlag strict_mode,
|
||||
Handle<Object> object,
|
||||
Handle<Object> key,
|
||||
Handle<Object> value) {
|
||||
@ -1630,11 +1642,11 @@ MaybeObject* KeyedStoreIC::Store(State state,
|
||||
|
||||
// Update inline cache and stub cache.
|
||||
if (FLAG_use_ic) {
|
||||
UpdateCaches(&lookup, state, receiver, name, value);
|
||||
UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
|
||||
}
|
||||
|
||||
// Set the property.
|
||||
return receiver->SetProperty(*name, *value, NONE);
|
||||
return receiver->SetProperty(*name, *value, NONE, strict_mode);
|
||||
}
|
||||
|
||||
// Do not use ICs for objects that require access checks (including
|
||||
@ -1643,23 +1655,25 @@ MaybeObject* KeyedStoreIC::Store(State state,
|
||||
ASSERT(!(use_ic && object->IsJSGlobalProxy()));
|
||||
|
||||
if (use_ic) {
|
||||
Code* stub = generic_stub();
|
||||
Code* stub =
|
||||
(strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub();
|
||||
if (state == UNINITIALIZED) {
|
||||
if (object->IsJSObject()) {
|
||||
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
|
||||
if (receiver->HasExternalArrayElements()) {
|
||||
MaybeObject* probe =
|
||||
StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver, true);
|
||||
StubCache::ComputeKeyedLoadOrStoreExternalArray(
|
||||
*receiver, true, strict_mode);
|
||||
stub = probe->IsFailure() ?
|
||||
NULL : Code::cast(probe->ToObjectUnchecked());
|
||||
} else if (receiver->HasPixelElements()) {
|
||||
MaybeObject* probe =
|
||||
StubCache::ComputeKeyedStorePixelArray(*receiver);
|
||||
StubCache::ComputeKeyedStorePixelArray(*receiver, strict_mode);
|
||||
stub = probe->IsFailure() ?
|
||||
NULL : Code::cast(probe->ToObjectUnchecked());
|
||||
} else if (key->IsSmi() && receiver->map()->has_fast_elements()) {
|
||||
MaybeObject* probe =
|
||||
StubCache::ComputeKeyedStoreSpecialized(*receiver);
|
||||
StubCache::ComputeKeyedStoreSpecialized(*receiver, strict_mode);
|
||||
stub = probe->IsFailure() ?
|
||||
NULL : Code::cast(probe->ToObjectUnchecked());
|
||||
}
|
||||
@ -1669,12 +1683,13 @@ MaybeObject* KeyedStoreIC::Store(State state,
|
||||
}
|
||||
|
||||
// Set the property.
|
||||
return Runtime::SetObjectProperty(object, key, value, NONE);
|
||||
return Runtime::SetObjectProperty(object, key, value, NONE, strict_mode);
|
||||
}
|
||||
|
||||
|
||||
void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
|
||||
State state,
|
||||
StrictModeFlag strict_mode,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<String> name,
|
||||
Handle<Object> value) {
|
||||
@ -1701,8 +1716,8 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
|
||||
|
||||
switch (type) {
|
||||
case FIELD: {
|
||||
maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver,
|
||||
lookup->GetFieldIndex());
|
||||
maybe_code = StubCache::ComputeKeyedStoreField(
|
||||
*name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode);
|
||||
break;
|
||||
}
|
||||
case MAP_TRANSITION: {
|
||||
@ -1711,8 +1726,8 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
|
||||
ASSERT(type == MAP_TRANSITION);
|
||||
Handle<Map> transition(lookup->GetTransitionMap());
|
||||
int index = transition->PropertyIndexFor(*name);
|
||||
maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver,
|
||||
index, *transition);
|
||||
maybe_code = StubCache::ComputeKeyedStoreField(
|
||||
*name, *receiver, index, *transition, strict_mode);
|
||||
break;
|
||||
}
|
||||
// fall through.
|
||||
@ -1720,7 +1735,9 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
|
||||
default: {
|
||||
// Always rewrite to the generic case so that we do not
|
||||
// repeatedly try to rewrite.
|
||||
maybe_code = generic_stub();
|
||||
maybe_code = (strict_mode == kStrictMode)
|
||||
? generic_stub_strict()
|
||||
: generic_stub();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1735,7 +1752,9 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
|
||||
if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
|
||||
set_target(Code::cast(code));
|
||||
} else if (state == MONOMORPHIC) {
|
||||
set_target(megamorphic_stub());
|
||||
set_target((strict_mode == kStrictMode)
|
||||
? megamorphic_stub_strict()
|
||||
: megamorphic_stub());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -1836,8 +1855,11 @@ MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) {
|
||||
StoreIC ic;
|
||||
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
|
||||
Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
|
||||
return ic.Store(state, extra_ic_state, args.at<Object>(0),
|
||||
args.at<String>(1), args.at<Object>(2));
|
||||
return ic.Store(state,
|
||||
static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
|
||||
args.at<Object>(0),
|
||||
args.at<String>(1),
|
||||
args.at<Object>(2));
|
||||
}
|
||||
|
||||
|
||||
@ -1901,7 +1923,11 @@ MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(Arguments args) {
|
||||
ASSERT(args.length() == 3);
|
||||
KeyedStoreIC ic;
|
||||
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
|
||||
return ic.Store(state, args.at<Object>(0), args.at<Object>(1),
|
||||
Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
|
||||
return ic.Store(state,
|
||||
static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
|
||||
args.at<Object>(0),
|
||||
args.at<Object>(1),
|
||||
args.at<Object>(2));
|
||||
}
|
||||
|
||||
|
45
src/ic.h
45
src/ic.h
@ -398,16 +398,10 @@ class KeyedLoadIC: public IC {
|
||||
|
||||
class StoreIC: public IC {
|
||||
public:
|
||||
|
||||
enum StoreICStrictMode {
|
||||
kStoreICNonStrict = kNonStrictMode,
|
||||
kStoreICStrict = kStrictMode
|
||||
};
|
||||
|
||||
StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); }
|
||||
|
||||
MUST_USE_RESULT MaybeObject* Store(State state,
|
||||
Code::ExtraICState extra_ic_state,
|
||||
StrictModeFlag strict_mode,
|
||||
Handle<Object> object,
|
||||
Handle<String> name,
|
||||
Handle<Object> value);
|
||||
@ -416,10 +410,11 @@ class StoreIC: public IC {
|
||||
static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
|
||||
static void GenerateMiss(MacroAssembler* masm);
|
||||
static void GenerateMegamorphic(MacroAssembler* masm,
|
||||
Code::ExtraICState extra_ic_state);
|
||||
StrictModeFlag strict_mode);
|
||||
static void GenerateArrayLength(MacroAssembler* masm);
|
||||
static void GenerateNormal(MacroAssembler* masm);
|
||||
static void GenerateGlobalProxy(MacroAssembler* masm);
|
||||
static void GenerateGlobalProxy(MacroAssembler* masm,
|
||||
StrictModeFlag strict_mode);
|
||||
|
||||
// Clear the use of an inlined version.
|
||||
static void ClearInlinedVersion(Address address);
|
||||
@ -433,11 +428,18 @@ class StoreIC: public IC {
|
||||
// lookup result.
|
||||
void UpdateCaches(LookupResult* lookup,
|
||||
State state,
|
||||
Code::ExtraICState extra_ic_state,
|
||||
StrictModeFlag strict_mode,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<String> name,
|
||||
Handle<Object> value);
|
||||
|
||||
void set_target(Code* code) {
|
||||
// Strict mode must be preserved across IC patching.
|
||||
ASSERT((code->extra_ic_state() & kStrictMode) ==
|
||||
(target()->extra_ic_state() & kStrictMode));
|
||||
IC::set_target(code);
|
||||
}
|
||||
|
||||
// Stub accessors.
|
||||
static Code* megamorphic_stub() {
|
||||
return Builtins::builtin(Builtins::StoreIC_Megamorphic);
|
||||
@ -473,6 +475,7 @@ class KeyedStoreIC: public IC {
|
||||
KeyedStoreIC() : IC(NO_EXTRA_FRAME) { }
|
||||
|
||||
MUST_USE_RESULT MaybeObject* Store(State state,
|
||||
StrictModeFlag strict_mode,
|
||||
Handle<Object> object,
|
||||
Handle<Object> name,
|
||||
Handle<Object> value);
|
||||
@ -480,8 +483,9 @@ class KeyedStoreIC: public IC {
|
||||
// Code generators for stub routines. Only called once at startup.
|
||||
static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
|
||||
static void GenerateMiss(MacroAssembler* masm);
|
||||
static void GenerateRuntimeSetProperty(MacroAssembler* masm);
|
||||
static void GenerateGeneric(MacroAssembler* masm);
|
||||
static void GenerateRuntimeSetProperty(MacroAssembler* masm,
|
||||
StrictModeFlag strict_mode);
|
||||
static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
|
||||
|
||||
// Clear the inlined version so the IC is always hit.
|
||||
static void ClearInlinedVersion(Address address);
|
||||
@ -493,20 +497,37 @@ class KeyedStoreIC: public IC {
|
||||
// Update the inline cache.
|
||||
void UpdateCaches(LookupResult* lookup,
|
||||
State state,
|
||||
StrictModeFlag strict_mode,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<String> name,
|
||||
Handle<Object> value);
|
||||
|
||||
void set_target(Code* code) {
|
||||
// Strict mode must be preserved across IC patching.
|
||||
ASSERT((code->extra_ic_state() & kStrictMode) ==
|
||||
(target()->extra_ic_state() & kStrictMode));
|
||||
IC::set_target(code);
|
||||
}
|
||||
|
||||
// Stub accessors.
|
||||
static Code* initialize_stub() {
|
||||
return Builtins::builtin(Builtins::KeyedStoreIC_Initialize);
|
||||
}
|
||||
static Code* initialize_stub_strict() {
|
||||
return Builtins::builtin(Builtins::KeyedStoreIC_Initialize_Strict);
|
||||
}
|
||||
static Code* megamorphic_stub() {
|
||||
return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
|
||||
}
|
||||
static Code* megamorphic_stub_strict() {
|
||||
return Builtins::builtin(Builtins::KeyedStoreIC_Generic_Strict);
|
||||
}
|
||||
static Code* generic_stub() {
|
||||
return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
|
||||
}
|
||||
static Code* generic_stub_strict() {
|
||||
return Builtins::builtin(Builtins::KeyedStoreIC_Generic_Strict);
|
||||
}
|
||||
|
||||
static void Clear(Address address, Code* target);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
138
src/runtime.cc
138
src/runtime.cc
@ -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>());
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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_;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user