Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(492)

Unified Diff: src/ic.cc

Issue 6576024: (early draft) Strict mode - throw exception on assignment to read only property. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Assign to read only property in strict mode. Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
}
« no previous file with comments | « src/ic.h ('k') | src/ic-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698