OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_IC_H_ | 5 #ifndef V8_IC_H_ |
6 #define V8_IC_H_ | 6 #define V8_IC_H_ |
7 | 7 |
8 #include "src/ic/ic-state.h" | 8 #include "src/ic/ic-state.h" |
9 #include "src/macro-assembler.h" | 9 #include "src/macro-assembler.h" |
10 | 10 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 | 52 |
53 // Alias the inline cache state type to make the IC code more readable. | 53 // Alias the inline cache state type to make the IC code more readable. |
54 typedef InlineCacheState State; | 54 typedef InlineCacheState State; |
55 | 55 |
56 // The IC code is either invoked with no extra frames on the stack | 56 // The IC code is either invoked with no extra frames on the stack |
57 // or with a single extra frame for supporting calls. | 57 // or with a single extra frame for supporting calls. |
58 enum FrameDepth { NO_EXTRA_FRAME = 0, EXTRA_CALL_FRAME = 1 }; | 58 enum FrameDepth { NO_EXTRA_FRAME = 0, EXTRA_CALL_FRAME = 1 }; |
59 | 59 |
60 // Construct the IC structure with the given number of extra | 60 // Construct the IC structure with the given number of extra |
61 // JavaScript frames on the stack. | 61 // JavaScript frames on the stack. |
62 IC(FrameDepth depth, Isolate* isolate); | 62 IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL, |
| 63 bool for_queries_only = false); |
63 virtual ~IC() {} | 64 virtual ~IC() {} |
64 | 65 |
65 State state() const { return state_; } | 66 State state() const { return state_; } |
66 inline Address address() const; | 67 inline Address address() const; |
67 | 68 |
68 // Compute the current IC state based on the target stub, receiver and name. | 69 // Compute the current IC state based on the target stub, receiver and name. |
69 void UpdateState(Handle<Object> receiver, Handle<Object> name); | 70 void UpdateState(Handle<Object> receiver, Handle<Object> name); |
70 | 71 |
71 bool IsNameCompatibleWithPrototypeFailure(Handle<Object> name); | 72 bool IsNameCompatibleWithPrototypeFailure(Handle<Object> name); |
72 void MarkPrototypeFailure(Handle<Object> name) { | 73 void MarkPrototypeFailure(Handle<Object> name) { |
73 DCHECK(IsNameCompatibleWithPrototypeFailure(name)); | 74 DCHECK(IsNameCompatibleWithPrototypeFailure(name)); |
| 75 old_state_ = state_; |
74 state_ = PROTOTYPE_FAILURE; | 76 state_ = PROTOTYPE_FAILURE; |
75 } | 77 } |
76 | 78 |
77 // If the stub contains weak maps then this function adds the stub to | 79 // If the stub contains weak maps then this function adds the stub to |
78 // the dependent code array of each weak map. | 80 // the dependent code array of each weak map. |
79 static void RegisterWeakMapDependency(Handle<Code> stub); | 81 static void RegisterWeakMapDependency(Handle<Code> stub); |
80 | 82 |
81 // This function is called when a weak map in the stub is dying, | 83 // This function is called when a weak map in the stub is dying, |
82 // invalidates the stub by setting maps in it to undefined. | 84 // invalidates the stub by setting maps in it to undefined. |
83 static void InvalidateMaps(Code* stub); | 85 static void InvalidateMaps(Code* stub); |
84 | 86 |
85 // Clear the inline cache to initial state. | 87 // Clear the inline cache to initial state. |
86 static void Clear(Isolate* isolate, Address address, | 88 static void Clear(Isolate* isolate, Address address, |
87 ConstantPoolArray* constant_pool); | 89 ConstantPoolArray* constant_pool); |
88 | 90 |
89 // Clear the vector-based inline cache to initial state. | 91 // Clear the vector-based inline cache to initial state. |
90 static void Clear(Isolate* isolate, Code::Kind kind, Code* host, | 92 static void Clear(Isolate* isolate, Code::Kind kind, Code* host, |
91 TypeFeedbackVector* vector, FeedbackVectorICSlot slot); | 93 FeedbackNexus* nexus); |
92 | 94 |
93 #ifdef DEBUG | 95 #ifdef DEBUG |
94 bool IsLoadStub() const { | 96 bool IsLoadStub() const { |
95 return target()->is_load_stub() || target()->is_keyed_load_stub(); | 97 return target()->is_load_stub() || target()->is_keyed_load_stub(); |
96 } | 98 } |
97 | 99 |
98 bool IsStoreStub() const { | 100 bool IsStoreStub() const { |
99 return target()->is_store_stub() || target()->is_keyed_store_stub(); | 101 return target()->is_store_stub() || target()->is_keyed_store_stub(); |
100 } | 102 } |
101 | 103 |
102 bool IsCallStub() const { return target()->is_call_stub(); } | 104 bool IsCallStub() const { return target()->is_call_stub(); } |
103 #endif | 105 #endif |
104 | 106 |
105 template <class TypeClass> | 107 template <class TypeClass> |
106 static JSFunction* GetRootConstructor(TypeClass* type, | 108 static JSFunction* GetRootConstructor(TypeClass* type, |
107 Context* native_context); | 109 Context* native_context); |
108 static inline Handle<Map> GetHandlerCacheHolder(HeapType* type, | 110 static inline Handle<Map> GetHandlerCacheHolder(HeapType* type, |
109 bool receiver_is_holder, | 111 bool receiver_is_holder, |
110 Isolate* isolate, | 112 Isolate* isolate, |
111 CacheHolderFlag* flag); | 113 CacheHolderFlag* flag); |
112 static inline Handle<Map> GetICCacheHolder(HeapType* type, Isolate* isolate, | 114 static inline Handle<Map> GetICCacheHolder(HeapType* type, Isolate* isolate, |
113 CacheHolderFlag* flag); | 115 CacheHolderFlag* flag); |
114 | 116 |
115 static bool IsCleared(Code* code) { | 117 static bool IsCleared(Code* code) { |
116 InlineCacheState state = code->ic_state(); | 118 InlineCacheState state = code->ic_state(); |
117 return state == UNINITIALIZED || state == PREMONOMORPHIC; | 119 return state == UNINITIALIZED || state == PREMONOMORPHIC; |
118 } | 120 } |
119 | 121 |
| 122 static bool IsCleared(FeedbackNexus* nexus) { |
| 123 InlineCacheState state = nexus->StateFromFeedback(); |
| 124 return state == UNINITIALIZED || state == PREMONOMORPHIC; |
| 125 } |
| 126 |
120 // Utility functions to convert maps to types and back. There are two special | 127 // Utility functions to convert maps to types and back. There are two special |
121 // cases: | 128 // cases: |
122 // - The heap_number_map is used as a marker which includes heap numbers as | 129 // - The heap_number_map is used as a marker which includes heap numbers as |
123 // well as smis. | 130 // well as smis. |
124 // - The oddball map is only used for booleans. | 131 // - The oddball map is only used for booleans. |
125 static Handle<Map> TypeToMap(HeapType* type, Isolate* isolate); | 132 static Handle<Map> TypeToMap(HeapType* type, Isolate* isolate); |
126 template <class T> | 133 template <class T> |
127 static typename T::TypeHandle MapToType(Handle<Map> map, | 134 static typename T::TypeHandle MapToType(Handle<Map> map, |
128 typename T::Region* region); | 135 typename T::Region* region); |
129 | 136 |
(...skipping 12 matching lines...) Expand all Loading... |
142 SharedFunctionInfo* GetSharedFunctionInfo() const; | 149 SharedFunctionInfo* GetSharedFunctionInfo() const; |
143 // Get the code object of the caller. | 150 // Get the code object of the caller. |
144 Code* GetCode() const; | 151 Code* GetCode() const; |
145 // Get the original (non-breakpointed) code object of the caller. | 152 // Get the original (non-breakpointed) code object of the caller. |
146 Code* GetOriginalCode() const; | 153 Code* GetOriginalCode() const; |
147 | 154 |
148 // Set the call-site target. | 155 // Set the call-site target. |
149 inline void set_target(Code* code); | 156 inline void set_target(Code* code); |
150 bool is_target_set() { return target_set_; } | 157 bool is_target_set() { return target_set_; } |
151 | 158 |
| 159 bool UseVector() const { |
| 160 bool use = (FLAG_vector_ics && |
| 161 (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC)) || |
| 162 kind() == Code::CALL_IC; |
| 163 // If we are supposed to use the nexus, verify the nexus is non-null. |
| 164 DCHECK(!use || nexus_ != NULL); |
| 165 return use; |
| 166 } |
| 167 |
152 char TransitionMarkFromState(IC::State state); | 168 char TransitionMarkFromState(IC::State state); |
153 void TraceIC(const char* type, Handle<Object> name); | 169 void TraceIC(const char* type, Handle<Object> name); |
154 void TraceIC(const char* type, Handle<Object> name, State old_state, | 170 void TraceIC(const char* type, Handle<Object> name, State old_state, |
155 State new_state); | 171 State new_state); |
156 | 172 |
157 MaybeHandle<Object> TypeError(const char* type, Handle<Object> object, | 173 MaybeHandle<Object> TypeError(const char* type, Handle<Object> object, |
158 Handle<Object> key); | 174 Handle<Object> key); |
159 MaybeHandle<Object> ReferenceError(const char* type, Handle<Name> name); | 175 MaybeHandle<Object> ReferenceError(const char* type, Handle<Name> name); |
160 | 176 |
161 // Access the target code for the given IC address. | 177 // Access the target code for the given IC address. |
162 static inline Code* GetTargetAtAddress(Address address, | 178 static inline Code* GetTargetAtAddress(Address address, |
163 ConstantPoolArray* constant_pool); | 179 ConstantPoolArray* constant_pool); |
164 static inline void SetTargetAtAddress(Address address, Code* target, | 180 static inline void SetTargetAtAddress(Address address, Code* target, |
165 ConstantPoolArray* constant_pool); | 181 ConstantPoolArray* constant_pool); |
166 static void OnTypeFeedbackChanged(Isolate* isolate, Address address, | 182 static void OnTypeFeedbackChanged(Isolate* isolate, Address address, |
167 State old_state, State new_state, | 183 State old_state, State new_state, |
168 bool target_remains_ic_stub); | 184 bool target_remains_ic_stub); |
| 185 // As a vector-based IC, type feedback must be updated differently. |
| 186 static void OnTypeFeedbackChanged(Isolate* isolate, Code* host, |
| 187 TypeFeedbackVector* vector, State old_state, |
| 188 State new_state); |
169 static void PostPatching(Address address, Code* target, Code* old_target); | 189 static void PostPatching(Address address, Code* target, Code* old_target); |
170 | 190 |
171 // Compute the handler either by compiling or by retrieving a cached version. | 191 // Compute the handler either by compiling or by retrieving a cached version. |
172 Handle<Code> ComputeHandler(LookupIterator* lookup, | 192 Handle<Code> ComputeHandler(LookupIterator* lookup, |
173 Handle<Object> value = Handle<Code>::null()); | 193 Handle<Object> value = Handle<Code>::null()); |
174 virtual Handle<Code> CompileHandler(LookupIterator* lookup, | 194 virtual Handle<Code> CompileHandler(LookupIterator* lookup, |
175 Handle<Object> value, | 195 Handle<Object> value, |
176 CacheHolderFlag cache_holder) { | 196 CacheHolderFlag cache_holder) { |
177 UNREACHABLE(); | 197 UNREACHABLE(); |
178 return Handle<Code>::null(); | 198 return Handle<Code>::null(); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 } | 242 } |
223 } | 243 } |
224 | 244 |
225 Map* FirstTargetMap() { | 245 Map* FirstTargetMap() { |
226 FindTargetMaps(); | 246 FindTargetMaps(); |
227 return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL; | 247 return target_maps_.length() > 0 ? *target_maps_.at(0) : NULL; |
228 } | 248 } |
229 | 249 |
230 inline void UpdateTarget(); | 250 inline void UpdateTarget(); |
231 | 251 |
| 252 Handle<TypeFeedbackVector> vector() const { return nexus()->vector_handle(); } |
| 253 FeedbackVectorICSlot slot() const { return nexus()->slot(); } |
| 254 State saved_state() const { |
| 255 return state() == PROTOTYPE_FAILURE ? old_state_ : state(); |
| 256 } |
| 257 |
| 258 template <class NexusClass> |
| 259 NexusClass* casted_nexus() { |
| 260 return static_cast<NexusClass*>(nexus_); |
| 261 } |
| 262 FeedbackNexus* nexus() const { return nexus_; } |
| 263 |
| 264 inline Code* get_host(); |
| 265 |
232 private: | 266 private: |
233 inline Code* raw_target() const; | 267 inline Code* raw_target() const; |
234 inline ConstantPoolArray* constant_pool() const; | 268 inline ConstantPoolArray* constant_pool() const; |
235 inline ConstantPoolArray* raw_constant_pool() const; | 269 inline ConstantPoolArray* raw_constant_pool() const; |
236 | 270 |
237 void FindTargetMaps() { | 271 void FindTargetMaps() { |
238 if (target_maps_set_) return; | 272 if (target_maps_set_) return; |
239 target_maps_set_ = true; | 273 target_maps_set_ = true; |
240 if (state_ == MONOMORPHIC) { | 274 if (state_ == MONOMORPHIC) { |
241 Map* map = target_->FindFirstMap(); | 275 Map* map = target_->FindFirstMap(); |
(...skipping 14 matching lines...) Expand all Loading... |
256 | 290 |
257 Isolate* isolate_; | 291 Isolate* isolate_; |
258 | 292 |
259 // The constant pool of the code which originally called the IC (which might | 293 // The constant pool of the code which originally called the IC (which might |
260 // be for the breakpointed copy of the original code). | 294 // be for the breakpointed copy of the original code). |
261 Handle<ConstantPoolArray> raw_constant_pool_; | 295 Handle<ConstantPoolArray> raw_constant_pool_; |
262 | 296 |
263 // The original code target that missed. | 297 // The original code target that missed. |
264 Handle<Code> target_; | 298 Handle<Code> target_; |
265 bool target_set_; | 299 bool target_set_; |
| 300 State old_state_; // For saving if we marked as prototype failure. |
266 State state_; | 301 State state_; |
267 Code::Kind kind_; | 302 Code::Kind kind_; |
268 Handle<HeapType> receiver_type_; | 303 Handle<HeapType> receiver_type_; |
269 MaybeHandle<Code> maybe_handler_; | 304 MaybeHandle<Code> maybe_handler_; |
270 | 305 |
271 ExtraICState extra_ic_state_; | 306 ExtraICState extra_ic_state_; |
272 MapHandleList target_maps_; | 307 MapHandleList target_maps_; |
273 bool target_maps_set_; | 308 bool target_maps_set_; |
274 | 309 |
| 310 FeedbackNexus* nexus_; |
| 311 |
275 DISALLOW_IMPLICIT_CONSTRUCTORS(IC); | 312 DISALLOW_IMPLICIT_CONSTRUCTORS(IC); |
276 }; | 313 }; |
277 | 314 |
278 | 315 |
279 // An IC_Utility encapsulates IC::UtilityId. It exists mainly because you | 316 // An IC_Utility encapsulates IC::UtilityId. It exists mainly because you |
280 // cannot make forward declarations to an enum. | 317 // cannot make forward declarations to an enum. |
281 class IC_Utility { | 318 class IC_Utility { |
282 public: | 319 public: |
283 explicit IC_Utility(IC::UtilityId id) | 320 explicit IC_Utility(IC::UtilityId id) |
284 : address_(IC::AddressFromUtilityId(id)), id_(id) {} | 321 : address_(IC::AddressFromUtilityId(id)), id_(id) {} |
285 | 322 |
286 Address address() const { return address_; } | 323 Address address() const { return address_; } |
287 | 324 |
288 IC::UtilityId id() const { return id_; } | 325 IC::UtilityId id() const { return id_; } |
289 | 326 |
290 private: | 327 private: |
291 Address address_; | 328 Address address_; |
292 IC::UtilityId id_; | 329 IC::UtilityId id_; |
293 }; | 330 }; |
294 | 331 |
295 | 332 |
296 class CallIC : public IC { | 333 class CallIC : public IC { |
297 public: | 334 public: |
298 explicit CallIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) {} | 335 CallIC(Isolate* isolate, CallICNexus* nexus) |
| 336 : IC(EXTRA_CALL_FRAME, isolate, nexus) { |
| 337 DCHECK(nexus != NULL); |
| 338 } |
299 | 339 |
300 void PatchMegamorphic(Handle<Object> function, | 340 void PatchMegamorphic(Handle<Object> function); |
301 Handle<TypeFeedbackVector> vector, | |
302 FeedbackVectorICSlot slot); | |
303 | 341 |
304 void HandleMiss(Handle<Object> receiver, Handle<Object> function, | 342 void HandleMiss(Handle<Object> receiver, Handle<Object> function); |
305 Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot); | |
306 | 343 |
307 // Returns true if a custom handler was installed. | 344 // Returns true if a custom handler was installed. |
308 bool DoCustomHandler(Handle<Object> receiver, Handle<Object> function, | 345 bool DoCustomHandler(Handle<Object> receiver, Handle<Object> function, |
309 Handle<TypeFeedbackVector> vector, | 346 const CallICState& callic_state); |
310 FeedbackVectorICSlot slot, const CallICState& state); | |
311 | 347 |
312 // Code generator routines. | 348 // Code generator routines. |
313 static Handle<Code> initialize_stub(Isolate* isolate, int argc, | 349 static Handle<Code> initialize_stub(Isolate* isolate, int argc, |
314 CallICState::CallType call_type); | 350 CallICState::CallType call_type); |
315 | 351 |
316 static void Clear(Isolate* isolate, Code* host, TypeFeedbackVector* vector, | 352 static void Clear(Isolate* isolate, Code* host, CallICNexus* nexus); |
317 FeedbackVectorICSlot slot); | |
318 | |
319 private: | |
320 static inline IC::State FeedbackToState(Isolate* isolate, | |
321 TypeFeedbackVector* vector, | |
322 FeedbackVectorICSlot slot); | |
323 | |
324 inline Code* get_host(); | |
325 | |
326 // As a vector-based IC, type feedback must be updated differently. | |
327 static void OnTypeFeedbackChanged(Isolate* isolate, Code* host, | |
328 TypeFeedbackVector* vector, State old_state, | |
329 State new_state); | |
330 }; | 353 }; |
331 | 354 |
332 | 355 |
333 class LoadIC : public IC { | 356 class LoadIC : public IC { |
334 public: | 357 public: |
335 static ExtraICState ComputeExtraICState(ContextualMode contextual_mode) { | 358 static ExtraICState ComputeExtraICState(ContextualMode contextual_mode) { |
336 return LoadICState(contextual_mode).GetExtraICState(); | 359 return LoadICState(contextual_mode).GetExtraICState(); |
337 } | 360 } |
338 | 361 |
339 ContextualMode contextual_mode() const { | 362 ContextualMode contextual_mode() const { |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 | 738 |
716 // Support functions for interceptor handlers. | 739 // Support functions for interceptor handlers. |
717 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly); | 740 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly); |
718 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptor); | 741 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptor); |
719 DECLARE_RUNTIME_FUNCTION(LoadElementWithInterceptor); | 742 DECLARE_RUNTIME_FUNCTION(LoadElementWithInterceptor); |
720 DECLARE_RUNTIME_FUNCTION(StorePropertyWithInterceptor); | 743 DECLARE_RUNTIME_FUNCTION(StorePropertyWithInterceptor); |
721 } | 744 } |
722 } // namespace v8::internal | 745 } // namespace v8::internal |
723 | 746 |
724 #endif // V8_IC_H_ | 747 #endif // V8_IC_H_ |
OLD | NEW |