| 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 |