Index: src/ic.cc |
diff --git a/src/ic.cc b/src/ic.cc |
index 4f75ade0e8edd96f0b8fad7cbae1125543e171bf..4772a7947d5f042d6123beb182e1eb725c28f61e 100644 |
--- a/src/ic.cc |
+++ b/src/ic.cc |
@@ -343,7 +343,7 @@ void StoreIC::Clear(Address address, Code* target) { |
if (target->ic_state() == UNINITIALIZED) return; |
ClearInlinedVersion(address); |
SetTargetAtAddress(address, |
- target->extra_ic_state() == kStoreICStrict |
+ target->extra_ic_state() == kStrictMode |
? initialize_stub_strict() |
: initialize_stub()); |
} |
@@ -366,7 +366,10 @@ void KeyedStoreIC::RestoreInlinedVersion(Address address) { |
void KeyedStoreIC::Clear(Address address, Code* target) { |
if (target->ic_state() == UNINITIALIZED) return; |
- SetTargetAtAddress(address, initialize_stub()); |
+ SetTargetAtAddress(address, |
+ target->extra_ic_state() == kStrictMode |
+ ? initialize_stub_strict() |
+ : initialize_stub()); |
} |
@@ -1227,7 +1230,8 @@ MaybeObject* KeyedLoadIC::Load(State state, |
if (receiver->HasExternalArrayElements()) { |
MaybeObject* probe = |
StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver, |
- false); |
+ false, |
+ kNonStrictMode); |
stub = probe->IsFailure() ? |
NULL : Code::cast(probe->ToObjectUnchecked()); |
} else if (receiver->HasIndexedInterceptor()) { |
@@ -1383,7 +1387,7 @@ static bool LookupForWrite(JSObject* object, |
MaybeObject* StoreIC::Store(State state, |
- Code::ExtraICState extra_ic_state, |
+ StrictModeFlag strict_mode, |
Handle<Object> object, |
Handle<String> name, |
Handle<Object> value) { |
@@ -1413,11 +1417,11 @@ MaybeObject* StoreIC::Store(State state, |
#ifdef DEBUG |
if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); |
#endif |
- Builtins::Name target = (extra_ic_state == kStoreICStrict) |
+ Builtins::Name target = (strict_mode == kStrictMode) |
? Builtins::StoreIC_ArrayLength_Strict |
: Builtins::StoreIC_ArrayLength; |
set_target(Builtins::builtin(target)); |
- return receiver->SetProperty(*name, *value, NONE); |
+ return receiver->SetProperty(*name, *value, NONE, strict_mode); |
} |
// Lookup the property locally in the receiver. |
@@ -1441,13 +1445,15 @@ MaybeObject* StoreIC::Store(State state, |
// Index is an offset from the end of the object. |
int offset = map->instance_size() + (index * kPointerSize); |
if (PatchInlinedStore(address(), map, offset)) { |
- set_target(megamorphic_stub()); |
+ set_target(strict_mode == kStrictMode |
+ ? megamorphic_stub_strict() |
+ : megamorphic_stub()); |
#ifdef DEBUG |
if (FLAG_trace_ic) { |
PrintF("[StoreIC : inline patch %s]\n", *name->ToCString()); |
} |
#endif |
- return receiver->SetProperty(*name, *value, NONE); |
+ return receiver->SetProperty(*name, *value, NONE, strict_mode); |
#ifdef DEBUG |
} else { |
@@ -1474,11 +1480,15 @@ 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); |
+ if (strict_mode == kStrictMode) { |
+ if (lookup.IsFound() && lookup.IsReadOnly()) { |
+ return TypeError("strict_rdonly_property", object, name); |
+ } else if (IsContextual(object)) { |
+ return ReferenceError("not_defined", name); |
+ } |
} |
} |
} |
@@ -1486,7 +1496,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 +1508,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 +1536,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 +1546,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 +1558,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 +1570,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 +1593,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 +1609,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 +1641,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 +1654,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 +1682,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 +1715,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 +1725,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 +1734,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 +1751,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 +1854,20 @@ 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)); |
+ ASSERT(extra_ic_state == kStrictMode || extra_ic_state == kNonStrictMode); |
+ MaybeObject* result = ic.Store(state, |
+ static_cast<StrictModeFlag>(extra_ic_state), |
+ args.at<Object>(0), |
+ args.at<String>(1), |
+ args.at<Object>(2)); |
+ // If this assert triggers the IC strict mode was changed. |
+ // The strict mode flag must be preserved on the IC. |
+ // |
+ // ic.target() doesn't appear to be valid in some cases when exiting from |
+ // ic.Store. Could it be crankshaft OSR? |
+ // |
+ // ASSERT(extra_ic_state == ic.target()->extra_ic_state()); |
+ return result; |
} |
@@ -1901,8 +1931,21 @@ 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), |
- args.at<Object>(2)); |
+ Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
+ ASSERT(extra_ic_state == kStrictMode || extra_ic_state == kNonStrictMode); |
+ MaybeObject* result = ic.Store(state, |
+ static_cast<StrictModeFlag>(extra_ic_state), |
+ args.at<Object>(0), |
+ args.at<Object>(1), |
+ args.at<Object>(2)); |
+ // If this assert triggers the IC strict mode was changed. |
+ // The strict mode flag must be preserved on the IC. |
+ // |
+ // ic.target() doesn't appear to be valid in some cases when exiting from |
+ // ic.Store. Could it be crankshaft OSR? |
+ // |
+ // ASSERT(extra_ic_state == ic.target()->extra_ic_state()); |
+ return result; |
} |