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