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