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

Side by Side Diff: src/ic.cc

Issue 25253002: Move TryRemoveInvalidPrototypeDependentStub onto the IC class. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 2 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 return ""; 69 return "";
70 } 70 }
71 71
72 72
73 void IC::TraceIC(const char* type, 73 void IC::TraceIC(const char* type,
74 Handle<Object> name, 74 Handle<Object> name,
75 Code* new_target) { 75 Code* new_target) {
76 if (FLAG_trace_ic) { 76 if (FLAG_trace_ic) {
77 State new_state = new_target->ic_state(); 77 State new_state = new_target->ic_state();
78 PrintF("[%s in ", type); 78 PrintF("[%s in ", type);
79 Isolate* isolate = new_target->GetIsolate(); 79 StackFrameIterator it(isolate());
80 StackFrameIterator it(isolate);
81 while (it.frame()->fp() != this->fp()) it.Advance(); 80 while (it.frame()->fp() != this->fp()) it.Advance();
82 StackFrame* raw_frame = it.frame(); 81 StackFrame* raw_frame = it.frame();
83 if (raw_frame->is_internal()) { 82 if (raw_frame->is_internal()) {
84 Code* apply_builtin = isolate->builtins()->builtin( 83 Code* apply_builtin = isolate()->builtins()->builtin(
85 Builtins::kFunctionApply); 84 Builtins::kFunctionApply);
86 if (raw_frame->unchecked_code() == apply_builtin) { 85 if (raw_frame->unchecked_code() == apply_builtin) {
87 PrintF("apply from "); 86 PrintF("apply from ");
88 it.Advance(); 87 it.Advance();
89 raw_frame = it.frame(); 88 raw_frame = it.frame();
90 } 89 }
91 } 90 }
92 JavaScriptFrame::PrintTop(isolate, stdout, false, true); 91 JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
93 Code::ExtraICState extra_state = new_target->extra_ic_state(); 92 Code::ExtraICState extra_state = new_target->extra_ic_state();
94 const char* modifier = 93 const char* modifier =
95 GetTransitionMarkModifier(Code::GetKeyedAccessStoreMode(extra_state)); 94 GetTransitionMarkModifier(Code::GetKeyedAccessStoreMode(extra_state));
96 PrintF(" (%c->%c%s)", 95 PrintF(" (%c->%c%s)",
97 TransitionMarkFromState(state()), 96 TransitionMarkFromState(state()),
98 TransitionMarkFromState(new_state), 97 TransitionMarkFromState(new_state),
99 modifier); 98 modifier);
100 name->Print(); 99 name->Print();
101 PrintF("]\n"); 100 PrintF("]\n");
102 } 101 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 // Return the address in the original code. This is the place where 171 // Return the address in the original code. This is the place where
173 // the call which has been overwritten by the DebugBreakXXX resides 172 // the call which has been overwritten by the DebugBreakXXX resides
174 // and the place where the inline cache system should look. 173 // and the place where the inline cache system should look.
175 intptr_t delta = 174 intptr_t delta =
176 original_code->instruction_start() - code->instruction_start(); 175 original_code->instruction_start() - code->instruction_start();
177 return addr + delta; 176 return addr + delta;
178 } 177 }
179 #endif 178 #endif
180 179
181 180
182 static bool TryRemoveInvalidPrototypeDependentStub(Code* target, 181 bool IC::TryRemoveInvalidPrototypeDependentStub(Object* receiver,
183 Object* receiver, 182 Object* name) {
184 Object* name) { 183 DisallowHeapAllocation no_gc;
185 if (target->is_keyed_stub()) { 184
185 if (target()->is_keyed_stub()) {
186 // Determine whether the failure is due to a name failure. 186 // Determine whether the failure is due to a name failure.
187 if (!name->IsName()) return false; 187 if (!name->IsName()) return false;
188 Name* stub_name = target->FindFirstName(); 188 Name* stub_name = target()->FindFirstName();
189 if (Name::cast(name) != stub_name) return false; 189 if (Name::cast(name) != stub_name) return false;
190 } 190 }
191 191
192 InlineCacheHolderFlag cache_holder = 192 InlineCacheHolderFlag cache_holder =
193 Code::ExtractCacheHolderFromFlags(target->flags()); 193 Code::ExtractCacheHolderFromFlags(target()->flags());
194 194
195 Isolate* isolate = target->GetIsolate();
196 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) { 195 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) {
197 // The stub was generated for JSObject but called for non-JSObject. 196 // The stub was generated for JSObject but called for non-JSObject.
198 // IC::GetCodeCacheHolder is not applicable. 197 // IC::GetCodeCacheHolder is not applicable.
199 return false; 198 return false;
200 } else if (cache_holder == PROTOTYPE_MAP && 199 } else if (cache_holder == PROTOTYPE_MAP &&
201 receiver->GetPrototype(isolate)->IsNull()) { 200 receiver->GetPrototype(isolate())->IsNull()) {
202 // IC::GetCodeCacheHolder is not applicable. 201 // IC::GetCodeCacheHolder is not applicable.
203 return false; 202 return false;
204 } 203 }
205 Map* map = IC::GetCodeCacheHolder(isolate, receiver, cache_holder)->map(); 204 Map* map = IC::GetCodeCacheHolder(isolate(), receiver, cache_holder)->map();
206 205
207 // Decide whether the inline cache failed because of changes to the 206 // Decide whether the inline cache failed because of changes to the
208 // receiver itself or changes to one of its prototypes. 207 // receiver itself or changes to one of its prototypes.
209 // 208 //
210 // If there are changes to the receiver itself, the map of the 209 // If there are changes to the receiver itself, the map of the
211 // receiver will have changed and the current target will not be in 210 // receiver will have changed and the current target will not be in
212 // the receiver map's code cache. Therefore, if the current target 211 // the receiver map's code cache. Therefore, if the current target
213 // is in the receiver map's code cache, the inline cache failed due 212 // is in the receiver map's code cache, the inline cache failed due
214 // to prototype check failure. 213 // to prototype check failure.
215 int index = map->IndexInCodeCache(name, target); 214 int index = map->IndexInCodeCache(name, *target());
216 if (index >= 0) { 215 if (index >= 0) {
217 map->RemoveFromCodeCache(String::cast(name), target, index); 216 map->RemoveFromCodeCache(String::cast(name), *target(), index);
218 // Handlers are stored in addition to the ICs on the map. Remove those, too. 217 // Handlers are stored in addition to the ICs on the map. Remove those, too.
219 Code* handler = target->FindFirstHandler(); 218 Code* handler = target()->FindFirstHandler();
220 if (handler != NULL) { 219 if (handler != NULL) {
221 index = map->IndexInCodeCache(name, handler); 220 index = map->IndexInCodeCache(name, handler);
222 if (index >= 0) { 221 if (index >= 0) {
223 map->RemoveFromCodeCache(String::cast(name), handler, index); 222 map->RemoveFromCodeCache(String::cast(name), handler, index);
224 } 223 }
225 } 224 }
226 return true; 225 return true;
227 } 226 }
228 227
229 // The stub is not in the cache. We've ruled out all other kinds of failure 228 // The stub is not in the cache. We've ruled out all other kinds of failure
230 // except for proptotype chain changes, a deprecated map, a map that's 229 // except for proptotype chain changes, a deprecated map, a map that's
231 // different from the one that the stub expects, elements kind changes, or a 230 // different from the one that the stub expects, elements kind changes, or a
232 // constant global property that will become mutable. Threat all those 231 // constant global property that will become mutable. Threat all those
233 // situations as prototype failures (stay monomorphic if possible). 232 // situations as prototype failures (stay monomorphic if possible).
234 233
235 // If the IC is shared between multiple receivers (slow dictionary mode), then 234 // If the IC is shared between multiple receivers (slow dictionary mode), then
236 // the map cannot be deprecated and the stub invalidated. 235 // the map cannot be deprecated and the stub invalidated.
237 if (cache_holder == OWN_MAP) { 236 if (cache_holder == OWN_MAP) {
238 Map* old_map = target->FindFirstMap(); 237 Map* old_map = target()->FindFirstMap();
239 if (old_map == map) return true; 238 if (old_map == map) return true;
240 if (old_map != NULL) { 239 if (old_map != NULL) {
241 if (old_map->is_deprecated()) return true; 240 if (old_map->is_deprecated()) return true;
242 if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(), 241 if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
243 map->elements_kind())) { 242 map->elements_kind())) {
244 return true; 243 return true;
245 } 244 }
246 } 245 }
247 } 246 }
248 247
249 if (receiver->IsGlobalObject()) { 248 if (receiver->IsGlobalObject()) {
250 if (!name->IsName()) return false; 249 if (!name->IsName()) return false;
251 Isolate* isolate = target->GetIsolate(); 250 LookupResult lookup(isolate());
252 LookupResult lookup(isolate);
253 GlobalObject* global = GlobalObject::cast(receiver); 251 GlobalObject* global = GlobalObject::cast(receiver);
254 global->LocalLookupRealNamedProperty(Name::cast(name), &lookup); 252 global->LocalLookupRealNamedProperty(Name::cast(name), &lookup);
255 if (!lookup.IsFound()) return false; 253 if (!lookup.IsFound()) return false;
256 PropertyCell* cell = global->GetPropertyCell(&lookup); 254 PropertyCell* cell = global->GetPropertyCell(&lookup);
257 return cell->type()->IsConstant(); 255 return cell->type()->IsConstant();
258 } 256 }
259 257
260 return false; 258 return false;
261 } 259 }
262 260
263 261
264 void IC::UpdateState(Object* receiver, Object* name) { 262 void IC::UpdateState(Object* receiver, Object* name) {
265 if (state() != MONOMORPHIC || !name->IsString()) return; 263 if (state() != MONOMORPHIC || !name->IsString()) return;
266 if (receiver->IsUndefined() || receiver->IsNull()) return; 264 if (receiver->IsUndefined() || receiver->IsNull()) return;
267 265
268 Code::Kind kind = target()->kind(); 266 Code::Kind kind = target()->kind();
269 // Remove the target from the code cache if it became invalid 267 // Remove the target from the code cache if it became invalid
270 // because of changes in the prototype chain to avoid hitting it 268 // because of changes in the prototype chain to avoid hitting it
271 // again. 269 // again.
272 // Call stubs handle this later to allow extra IC state 270 // Call stubs handle this later to allow extra IC state
273 // transitions. 271 // transitions.
274 if (kind != Code::CALL_IC && kind != Code::KEYED_CALL_IC && 272 if (kind != Code::CALL_IC && kind != Code::KEYED_CALL_IC &&
275 TryRemoveInvalidPrototypeDependentStub(*target_, receiver, name)) { 273 TryRemoveInvalidPrototypeDependentStub(receiver, name)) {
276 MarkMonomorphicPrototypeFailure(); 274 MarkMonomorphicPrototypeFailure();
277 return; 275 return;
278 } 276 }
279 277
280 // The builtins object is special. It only changes when JavaScript 278 // The builtins object is special. It only changes when JavaScript
281 // builtins are loaded lazily. It is important to keep inline 279 // builtins are loaded lazily. It is important to keep inline
282 // caches for the builtins object monomorphic. Therefore, if we get 280 // caches for the builtins object monomorphic. Therefore, if we get
283 // an inline cache miss for the builtins object after lazily loading 281 // an inline cache miss for the builtins object after lazily loading
284 // JavaScript builtins, we return uninitialized as the state to 282 // JavaScript builtins, we return uninitialized as the state to
285 // force the inline cache back to monomorphic state. 283 // force the inline cache back to monomorphic state.
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 if (state() == UNINITIALIZED) { 734 if (state() == UNINITIALIZED) {
737 // This is the first time we execute this inline cache. 735 // This is the first time we execute this inline cache.
738 // Set the target to the pre monomorphic stub to delay 736 // Set the target to the pre monomorphic stub to delay
739 // setting the monomorphic state. 737 // setting the monomorphic state.
740 code = isolate()->stub_cache()->ComputeCallPreMonomorphic( 738 code = isolate()->stub_cache()->ComputeCallPreMonomorphic(
741 argc, kind_, extra_ic_state); 739 argc, kind_, extra_ic_state);
742 } else if (state() == MONOMORPHIC) { 740 } else if (state() == MONOMORPHIC) {
743 if (kind_ == Code::CALL_IC && 741 if (kind_ == Code::CALL_IC &&
744 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { 742 TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
745 code = ComputeMonomorphicStub(lookup, extra_ic_state, object, name); 743 code = ComputeMonomorphicStub(lookup, extra_ic_state, object, name);
746 } else if (TryRemoveInvalidPrototypeDependentStub(*target(), 744 } else if (TryRemoveInvalidPrototypeDependentStub(*object, *name)) {
747 *object,
748 *name)) {
749 MarkMonomorphicPrototypeFailure(); 745 MarkMonomorphicPrototypeFailure();
750 code = ComputeMonomorphicStub(lookup, extra_ic_state, object, name); 746 code = ComputeMonomorphicStub(lookup, extra_ic_state, object, name);
751 } else { 747 } else {
752 code = isolate()->stub_cache()->ComputeCallMegamorphic( 748 code = isolate()->stub_cache()->ComputeCallMegamorphic(
753 argc, kind_, extra_ic_state); 749 argc, kind_, extra_ic_state);
754 } 750 }
755 } else { 751 } else {
756 code = ComputeMonomorphicStub(lookup, extra_ic_state, object, name); 752 code = ComputeMonomorphicStub(lookup, extra_ic_state, object, name);
757 } 753 }
758 754
(...skipping 2216 matching lines...) Expand 10 before | Expand all | Expand 10 after
2975 #undef ADDR 2971 #undef ADDR
2976 }; 2972 };
2977 2973
2978 2974
2979 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2975 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2980 return IC_utilities[id]; 2976 return IC_utilities[id];
2981 } 2977 }
2982 2978
2983 2979
2984 } } // namespace v8::internal 2980 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698