OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |