| Index: src/ic.cc
|
| diff --git a/src/ic.cc b/src/ic.cc
|
| index 8e282adc34b43bf0f70b3dab9d2934f50835d6f2..62ab0f213e9302a7d182ffd406bcfb9ea0482b3e 100644
|
| --- a/src/ic.cc
|
| +++ b/src/ic.cc
|
| @@ -342,7 +342,10 @@ void StoreIC::ClearInlinedVersion(Address address) {
|
| void StoreIC::Clear(Address address, Code* target) {
|
| if (target->ic_state() == UNINITIALIZED) return;
|
| ClearInlinedVersion(address);
|
| - SetTargetAtAddress(address, initialize_stub());
|
| + SetTargetAtAddress(address,
|
| + target->extra_ic_state() == kStoreICStrict
|
| + ? initialize_stub_strict()
|
| + : initialize_stub());
|
| }
|
|
|
|
|
| @@ -1368,6 +1371,7 @@ static bool LookupForWrite(JSObject* object,
|
|
|
|
|
| MaybeObject* StoreIC::Store(State state,
|
| + Code::ExtraICState extra_ic_state,
|
| Handle<Object> object,
|
| Handle<String> name,
|
| Handle<Object> value) {
|
| @@ -1397,8 +1401,10 @@ MaybeObject* StoreIC::Store(State state,
|
| #ifdef DEBUG
|
| if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
|
| #endif
|
| - Code* target = Builtins::builtin(Builtins::StoreIC_ArrayLength);
|
| - set_target(target);
|
| + Builtins::Name target = (extra_ic_state == kStoreICStrict)
|
| + ? Builtins::StoreIC_ArrayLength_Strict
|
| + : Builtins::StoreIC_ArrayLength;
|
| + set_target(Builtins::builtin(target));
|
| return receiver->SetProperty(*name, *value, NONE);
|
| }
|
|
|
| @@ -1456,15 +1462,23 @@ MaybeObject* StoreIC::Store(State state,
|
|
|
| // If no inlined store ic was patched, generate a stub for this
|
| // store.
|
| - UpdateCaches(&lookup, state, receiver, name, value);
|
| + UpdateCaches(&lookup, state, extra_ic_state, 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 (receiver->IsJSGlobalProxy()) {
|
| // Generate a generic stub that goes to the runtime when we see a global
|
| // proxy as receiver.
|
| - if (target() != global_proxy_stub()) {
|
| - set_target(global_proxy_stub());
|
| + Code* stub = (extra_ic_state == kStoreICStrict)
|
| + ? global_proxy_stub_strict()
|
| + : global_proxy_stub();
|
| + if (target() != stub) {
|
| + set_target(stub);
|
| #ifdef DEBUG
|
| TraceIC("StoreIC", name, state, target());
|
| #endif
|
| @@ -1478,6 +1492,7 @@ MaybeObject* StoreIC::Store(State state,
|
|
|
| void StoreIC::UpdateCaches(LookupResult* lookup,
|
| State state,
|
| + Code::ExtraICState extra_ic_state,
|
| Handle<JSObject> receiver,
|
| Handle<String> name,
|
| Handle<Object> value) {
|
| @@ -1498,8 +1513,8 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
| Object* code = NULL;
|
| switch (type) {
|
| case FIELD: {
|
| - maybe_code = StubCache::ComputeStoreField(*name, *receiver,
|
| - lookup->GetFieldIndex());
|
| + maybe_code = StubCache::ComputeStoreField(
|
| + *name, *receiver, lookup->GetFieldIndex(), NULL, extra_ic_state);
|
| break;
|
| }
|
| case MAP_TRANSITION: {
|
| @@ -1508,8 +1523,8 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
| ASSERT(type == MAP_TRANSITION);
|
| Handle<Map> transition(lookup->GetTransitionMap());
|
| int index = transition->PropertyIndexFor(*name);
|
| - maybe_code = StubCache::ComputeStoreField(*name, *receiver,
|
| - index, *transition);
|
| + maybe_code = StubCache::ComputeStoreField(
|
| + *name, *receiver, index, *transition, extra_ic_state);
|
| break;
|
| }
|
| case NORMAL: {
|
| @@ -1520,10 +1535,11 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
| Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
|
| JSGlobalPropertyCell* cell =
|
| JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
|
| - maybe_code = StubCache::ComputeStoreGlobal(*name, *global, cell);
|
| + maybe_code = StubCache::ComputeStoreGlobal(
|
| + *name, *global, cell, extra_ic_state);
|
| } else {
|
| if (lookup->holder() != *receiver) return;
|
| - maybe_code = StubCache::ComputeStoreNormal();
|
| + maybe_code = StubCache::ComputeStoreNormal(extra_ic_state);
|
| }
|
| break;
|
| }
|
| @@ -1531,12 +1547,14 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
| if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
|
| AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
|
| if (v8::ToCData<Address>(callback->setter()) == 0) return;
|
| - maybe_code = StubCache::ComputeStoreCallback(*name, *receiver, callback);
|
| + maybe_code = StubCache::ComputeStoreCallback(
|
| + *name, *receiver, callback, extra_ic_state);
|
| break;
|
| }
|
| case INTERCEPTOR: {
|
| ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
|
| - maybe_code = StubCache::ComputeStoreInterceptor(*name, *receiver);
|
| + maybe_code = StubCache::ComputeStoreInterceptor(
|
| + *name, *receiver, extra_ic_state);
|
| break;
|
| }
|
| default:
|
| @@ -1552,7 +1570,11 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
| set_target(Code::cast(code));
|
| } else if (state == MONOMORPHIC) {
|
| // Only move to megamorphic if the target changes.
|
| - if (target() != Code::cast(code)) set_target(megamorphic_stub());
|
| + if (target() != Code::cast(code)) {
|
| + set_target(extra_ic_state == kStoreICStrict
|
| + ? megamorphic_stub_strict()
|
| + : megamorphic_stub());
|
| + }
|
| } else if (state == MEGAMORPHIC) {
|
| // Update the stub cache.
|
| StubCache::Set(*name, receiver->map(), Code::cast(code));
|
| @@ -1795,8 +1817,9 @@ MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) {
|
| ASSERT(args.length() == 3);
|
| StoreIC ic;
|
| IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
|
| - return ic.Store(state, args.at<Object>(0), args.at<String>(1),
|
| - args.at<Object>(2));
|
| + 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));
|
| }
|
|
|
|
|
|
|