| 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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 static void RegisterWeakMapDependency(Handle<Code> stub); | 81 static void RegisterWeakMapDependency(Handle<Code> stub); |
| 82 | 82 |
| 83 // 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, |
| 84 // invalidates the stub by setting maps in it to undefined. | 84 // invalidates the stub by setting maps in it to undefined. |
| 85 static void InvalidateMaps(Code* stub); | 85 static void InvalidateMaps(Code* stub); |
| 86 | 86 |
| 87 // Clear the inline cache to initial state. | 87 // Clear the inline cache to initial state. |
| 88 static void Clear(Isolate* isolate, Address address, | 88 static void Clear(Isolate* isolate, Address address, |
| 89 ConstantPoolArray* constant_pool); | 89 ConstantPoolArray* constant_pool); |
| 90 | 90 |
| 91 // Clear the vector-based inline cache to initial state. | |
| 92 template <class Nexus> | |
| 93 static void Clear(Isolate* isolate, Code::Kind kind, Code* host, | |
| 94 Nexus* nexus); | |
| 95 | |
| 96 #ifdef DEBUG | 91 #ifdef DEBUG |
| 97 bool IsLoadStub() const { | 92 bool IsLoadStub() const { |
| 98 return target()->is_load_stub() || target()->is_keyed_load_stub(); | 93 return target()->is_load_stub() || target()->is_keyed_load_stub(); |
| 99 } | 94 } |
| 100 | 95 |
| 101 bool IsStoreStub() const { | 96 bool IsStoreStub() const { |
| 102 return target()->is_store_stub() || target()->is_keyed_store_stub(); | 97 return target()->is_store_stub() || target()->is_keyed_store_stub(); |
| 103 } | 98 } |
| 104 | 99 |
| 105 bool IsCallStub() const { return target()->is_call_stub(); } | 100 bool IsCallStub() const { return target()->is_call_stub(); } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 | 154 |
| 160 bool UseVector() const { | 155 bool UseVector() const { |
| 161 bool use = (FLAG_vector_ics && | 156 bool use = (FLAG_vector_ics && |
| 162 (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC)) || | 157 (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC)) || |
| 163 kind() == Code::CALL_IC; | 158 kind() == Code::CALL_IC; |
| 164 // If we are supposed to use the nexus, verify the nexus is non-null. | 159 // If we are supposed to use the nexus, verify the nexus is non-null. |
| 165 DCHECK(!use || nexus_ != NULL); | 160 DCHECK(!use || nexus_ != NULL); |
| 166 return use; | 161 return use; |
| 167 } | 162 } |
| 168 | 163 |
| 164 // Configure for most states. |
| 165 void ConfigureVectorState(IC::State new_state); |
| 166 // Configure the vector for MONOMORPHIC. |
| 167 void ConfigureVectorState(Handle<Name> name, Handle<HeapType> type, |
| 168 Handle<Code> handler); |
| 169 // Configure the vector for POLYMORPHIC. |
| 170 void ConfigureVectorState(Handle<Name> name, TypeHandleList* types, |
| 171 CodeHandleList* handlers); |
| 172 |
| 169 char TransitionMarkFromState(IC::State state); | 173 char TransitionMarkFromState(IC::State state); |
| 170 void TraceIC(const char* type, Handle<Object> name); | 174 void TraceIC(const char* type, Handle<Object> name); |
| 171 void TraceIC(const char* type, Handle<Object> name, State old_state, | 175 void TraceIC(const char* type, Handle<Object> name, State old_state, |
| 172 State new_state); | 176 State new_state); |
| 173 | 177 |
| 174 MaybeHandle<Object> TypeError(const char* type, Handle<Object> object, | 178 MaybeHandle<Object> TypeError(const char* type, Handle<Object> object, |
| 175 Handle<Object> key); | 179 Handle<Object> key); |
| 176 MaybeHandle<Object> ReferenceError(const char* type, Handle<Name> name); | 180 MaybeHandle<Object> ReferenceError(const char* type, Handle<Name> name); |
| 177 | 181 |
| 178 // Access the target code for the given IC address. | 182 // Access the target code for the given IC address. |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 inline Code* get_host(); | 269 inline Code* get_host(); |
| 266 | 270 |
| 267 private: | 271 private: |
| 268 inline Code* raw_target() const; | 272 inline Code* raw_target() const; |
| 269 inline ConstantPoolArray* constant_pool() const; | 273 inline ConstantPoolArray* constant_pool() const; |
| 270 inline ConstantPoolArray* raw_constant_pool() const; | 274 inline ConstantPoolArray* raw_constant_pool() const; |
| 271 | 275 |
| 272 void FindTargetMaps() { | 276 void FindTargetMaps() { |
| 273 if (target_maps_set_) return; | 277 if (target_maps_set_) return; |
| 274 target_maps_set_ = true; | 278 target_maps_set_ = true; |
| 275 if (state_ == MONOMORPHIC) { | 279 if (UseVector()) { |
| 276 Map* map = target_->FindFirstMap(); | 280 nexus()->ExtractMaps(&target_maps_); |
| 277 if (map != NULL) target_maps_.Add(handle(map)); | 281 } else { |
| 278 } else if (state_ != UNINITIALIZED && state_ != PREMONOMORPHIC) { | 282 if (state_ == MONOMORPHIC) { |
| 279 target_->FindAllMaps(&target_maps_); | 283 Map* map = target_->FindFirstMap(); |
| 284 if (map != NULL) target_maps_.Add(handle(map)); |
| 285 } else if (state_ != UNINITIALIZED && state_ != PREMONOMORPHIC) { |
| 286 target_->FindAllMaps(&target_maps_); |
| 287 } |
| 280 } | 288 } |
| 281 } | 289 } |
| 282 | 290 |
| 283 // Frame pointer for the frame that uses (calls) the IC. | 291 // Frame pointer for the frame that uses (calls) the IC. |
| 284 Address fp_; | 292 Address fp_; |
| 285 | 293 |
| 286 // All access to the program counter of an IC structure is indirect | 294 // All access to the program counter of an IC structure is indirect |
| 287 // to make the code GC safe. This feature is crucial since | 295 // to make the code GC safe. This feature is crucial since |
| 288 // GetProperty and SetProperty are called and they in turn might | 296 // GetProperty and SetProperty are called and they in turn might |
| 289 // invoke the garbage collector. | 297 // invoke the garbage collector. |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 class LoadIC : public IC { | 365 class LoadIC : public IC { |
| 358 public: | 366 public: |
| 359 static ExtraICState ComputeExtraICState(ContextualMode contextual_mode) { | 367 static ExtraICState ComputeExtraICState(ContextualMode contextual_mode) { |
| 360 return LoadICState(contextual_mode).GetExtraICState(); | 368 return LoadICState(contextual_mode).GetExtraICState(); |
| 361 } | 369 } |
| 362 | 370 |
| 363 ContextualMode contextual_mode() const { | 371 ContextualMode contextual_mode() const { |
| 364 return LoadICState::GetContextualMode(extra_ic_state()); | 372 return LoadICState::GetContextualMode(extra_ic_state()); |
| 365 } | 373 } |
| 366 | 374 |
| 367 explicit LoadIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) { | 375 LoadIC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus = NULL) |
| 376 : IC(depth, isolate, nexus) { |
| 377 DCHECK(!FLAG_vector_ics || nexus != NULL); |
| 368 DCHECK(IsLoadStub()); | 378 DCHECK(IsLoadStub()); |
| 369 } | 379 } |
| 370 | 380 |
| 381 // TODO(mvstanton): The for_queries_only is because we have a case where we |
| 382 // construct an IC only to gather the contextual mode, and we don't have |
| 383 // vector/slot information. for_queries_only is a temporary hack to enable the |
| 384 // strong DCHECK protection around vector/slot. |
| 385 LoadIC(FrameDepth depth, Isolate* isolate, bool for_queries_only) |
| 386 : IC(depth, isolate, NULL, for_queries_only) { |
| 387 DCHECK(IsLoadStub()); |
| 388 } |
| 389 |
| 371 // Returns if this IC is for contextual (no explicit receiver) | 390 // Returns if this IC is for contextual (no explicit receiver) |
| 372 // access to properties. | 391 // access to properties. |
| 373 bool IsUndeclaredGlobal(Handle<Object> receiver) { | 392 bool IsUndeclaredGlobal(Handle<Object> receiver) { |
| 374 if (receiver->IsGlobalObject()) { | 393 if (receiver->IsGlobalObject()) { |
| 375 return contextual_mode() == CONTEXTUAL; | 394 return contextual_mode() == CONTEXTUAL; |
| 376 } else { | 395 } else { |
| 377 DCHECK(contextual_mode() != CONTEXTUAL); | 396 DCHECK(contextual_mode() != CONTEXTUAL); |
| 378 return false; | 397 return false; |
| 379 } | 398 } |
| 380 } | 399 } |
| 381 | 400 |
| 382 // Code generator routines. | 401 // Code generator routines. |
| 383 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } | 402 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } |
| 384 static void GeneratePreMonomorphic(MacroAssembler* masm) { | 403 static void GeneratePreMonomorphic(MacroAssembler* masm) { |
| 385 GenerateMiss(masm); | 404 GenerateMiss(masm); |
| 386 } | 405 } |
| 387 static void GenerateMiss(MacroAssembler* masm); | 406 static void GenerateMiss(MacroAssembler* masm); |
| 388 static void GenerateNormal(MacroAssembler* masm); | 407 static void GenerateNormal(MacroAssembler* masm); |
| 389 static void GenerateRuntimeGetProperty(MacroAssembler* masm); | 408 static void GenerateRuntimeGetProperty(MacroAssembler* masm); |
| 390 | 409 |
| 391 static Handle<Code> initialize_stub(Isolate* isolate, | 410 static Handle<Code> initialize_stub(Isolate* isolate, |
| 392 ExtraICState extra_state); | 411 ExtraICState extra_state); |
| 393 static Handle<Code> initialize_stub_in_optimized_code( | 412 static Handle<Code> initialize_stub_in_optimized_code( |
| 394 Isolate* isolate, ExtraICState extra_state); | 413 Isolate* isolate, ExtraICState extra_state); |
| 395 | 414 |
| 396 MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object, | 415 MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object, |
| 397 Handle<Name> name); | 416 Handle<Name> name); |
| 398 | 417 |
| 418 static void Clear(Isolate* isolate, Code* host, LoadICNexus* nexus); |
| 419 |
| 399 protected: | 420 protected: |
| 400 inline void set_target(Code* code); | 421 inline void set_target(Code* code); |
| 401 | 422 |
| 402 Handle<Code> slow_stub() const { | 423 Handle<Code> slow_stub() const { |
| 403 if (kind() == Code::LOAD_IC) { | 424 if (kind() == Code::LOAD_IC) { |
| 404 return isolate()->builtins()->LoadIC_Slow(); | 425 return isolate()->builtins()->LoadIC_Slow(); |
| 405 } else { | 426 } else { |
| 406 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); | 427 DCHECK_EQ(Code::KEYED_LOAD_IC, kind()); |
| 407 return isolate()->builtins()->KeyedLoadIC_Slow(); | 428 return isolate()->builtins()->KeyedLoadIC_Slow(); |
| 408 } | 429 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 427 | 448 |
| 428 static void Clear(Isolate* isolate, Address address, Code* target, | 449 static void Clear(Isolate* isolate, Address address, Code* target, |
| 429 ConstantPoolArray* constant_pool); | 450 ConstantPoolArray* constant_pool); |
| 430 | 451 |
| 431 friend class IC; | 452 friend class IC; |
| 432 }; | 453 }; |
| 433 | 454 |
| 434 | 455 |
| 435 class KeyedLoadIC : public LoadIC { | 456 class KeyedLoadIC : public LoadIC { |
| 436 public: | 457 public: |
| 437 explicit KeyedLoadIC(FrameDepth depth, Isolate* isolate) | 458 KeyedLoadIC(FrameDepth depth, Isolate* isolate, |
| 438 : LoadIC(depth, isolate) { | 459 KeyedLoadICNexus* nexus = NULL) |
| 460 : LoadIC(depth, isolate, nexus) { |
| 461 DCHECK(!FLAG_vector_ics || nexus != NULL); |
| 439 DCHECK(target()->is_keyed_load_stub()); | 462 DCHECK(target()->is_keyed_load_stub()); |
| 440 } | 463 } |
| 441 | 464 |
| 442 MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object, | 465 MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object, |
| 443 Handle<Object> key); | 466 Handle<Object> key); |
| 444 | 467 |
| 445 // Code generator routines. | 468 // Code generator routines. |
| 446 static void GenerateMiss(MacroAssembler* masm); | 469 static void GenerateMiss(MacroAssembler* masm); |
| 447 static void GenerateRuntimeGetProperty(MacroAssembler* masm); | 470 static void GenerateRuntimeGetProperty(MacroAssembler* masm); |
| 448 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } | 471 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } |
| 449 static void GeneratePreMonomorphic(MacroAssembler* masm) { | 472 static void GeneratePreMonomorphic(MacroAssembler* masm) { |
| 450 GenerateMiss(masm); | 473 GenerateMiss(masm); |
| 451 } | 474 } |
| 452 static void GenerateGeneric(MacroAssembler* masm); | 475 static void GenerateGeneric(MacroAssembler* masm); |
| 453 | 476 |
| 454 // Bit mask to be tested against bit field for the cases when | 477 // Bit mask to be tested against bit field for the cases when |
| 455 // generic stub should go into slow case. | 478 // generic stub should go into slow case. |
| 456 // Access check is necessary explicitly since generic stub does not perform | 479 // Access check is necessary explicitly since generic stub does not perform |
| 457 // map checks. | 480 // map checks. |
| 458 static const int kSlowCaseBitFieldMask = | 481 static const int kSlowCaseBitFieldMask = |
| 459 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor); | 482 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor); |
| 460 | 483 |
| 461 static Handle<Code> initialize_stub(Isolate* isolate); | 484 static Handle<Code> initialize_stub(Isolate* isolate); |
| 462 static Handle<Code> initialize_stub_in_optimized_code(Isolate* isolate); | 485 static Handle<Code> initialize_stub_in_optimized_code(Isolate* isolate); |
| 463 static Handle<Code> generic_stub(Isolate* isolate); | 486 static Handle<Code> generic_stub(Isolate* isolate); |
| 464 static Handle<Code> pre_monomorphic_stub(Isolate* isolate); | 487 static Handle<Code> pre_monomorphic_stub(Isolate* isolate); |
| 465 | 488 |
| 489 static void Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus); |
| 490 |
| 466 protected: | 491 protected: |
| 467 // receiver is HeapObject because it could be a String or a JSObject | 492 // receiver is HeapObject because it could be a String or a JSObject |
| 468 Handle<Code> LoadElementStub(Handle<HeapObject> receiver); | 493 Handle<Code> LoadElementStub(Handle<HeapObject> receiver); |
| 469 virtual Handle<Code> pre_monomorphic_stub() const { | 494 virtual Handle<Code> pre_monomorphic_stub() const { |
| 470 return pre_monomorphic_stub(isolate()); | 495 return pre_monomorphic_stub(isolate()); |
| 471 } | 496 } |
| 472 | 497 |
| 473 private: | 498 private: |
| 474 Handle<Code> generic_stub() const { return generic_stub(isolate()); } | 499 Handle<Code> generic_stub() const { return generic_stub(isolate()); } |
| 475 | 500 |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 | 757 |
| 733 // Support functions for interceptor handlers. | 758 // Support functions for interceptor handlers. |
| 734 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly); | 759 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly); |
| 735 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptor); | 760 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptor); |
| 736 DECLARE_RUNTIME_FUNCTION(LoadElementWithInterceptor); | 761 DECLARE_RUNTIME_FUNCTION(LoadElementWithInterceptor); |
| 737 DECLARE_RUNTIME_FUNCTION(StorePropertyWithInterceptor); | 762 DECLARE_RUNTIME_FUNCTION(StorePropertyWithInterceptor); |
| 738 } | 763 } |
| 739 } // namespace v8::internal | 764 } // namespace v8::internal |
| 740 | 765 |
| 741 #endif // V8_IC_H_ | 766 #endif // V8_IC_H_ |
| OLD | NEW |