| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 | 35 |
| 36 | 36 |
| 37 const int kMaxKeyedPolymorphism = 4; | 37 const int kMaxKeyedPolymorphism = 4; |
| 38 | 38 |
| 39 | 39 |
| 40 // IC_UTIL_LIST defines all utility functions called from generated | 40 // IC_UTIL_LIST defines all utility functions called from generated |
| 41 // inline caching code. The argument for the macro, ICU, is the function name. | 41 // inline caching code. The argument for the macro, ICU, is the function name. |
| 42 #define IC_UTIL_LIST(ICU) \ | 42 #define IC_UTIL_LIST(ICU) \ |
| 43 ICU(LoadIC_Miss) \ | 43 ICU(LoadIC_Miss) \ |
| 44 ICU(KeyedLoadIC_Miss) \ | 44 ICU(KeyedLoadIC_Miss) \ |
| 45 ICU(CallIC_Miss) \ | |
| 46 ICU(KeyedCallIC_Miss) \ | |
| 47 ICU(StoreIC_Miss) \ | 45 ICU(StoreIC_Miss) \ |
| 48 ICU(StoreIC_ArrayLength) \ | 46 ICU(StoreIC_ArrayLength) \ |
| 49 ICU(StoreIC_Slow) \ | 47 ICU(StoreIC_Slow) \ |
| 50 ICU(SharedStoreIC_ExtendStorage) \ | 48 ICU(SharedStoreIC_ExtendStorage) \ |
| 51 ICU(KeyedStoreIC_Miss) \ | 49 ICU(KeyedStoreIC_Miss) \ |
| 52 ICU(KeyedStoreIC_Slow) \ | 50 ICU(KeyedStoreIC_Slow) \ |
| 53 /* Utilities for IC stubs. */ \ | 51 /* Utilities for IC stubs. */ \ |
| 54 ICU(StoreCallbackProperty) \ | 52 ICU(StoreCallbackProperty) \ |
| 55 ICU(LoadPropertyWithInterceptorOnly) \ | 53 ICU(LoadPropertyWithInterceptorOnly) \ |
| 56 ICU(LoadPropertyWithInterceptorForLoad) \ | 54 ICU(LoadPropertyWithInterceptorForLoad) \ |
| 57 ICU(LoadPropertyWithInterceptorForCall) \ | 55 ICU(LoadPropertyWithInterceptorForCall) \ |
| 58 ICU(KeyedLoadPropertyWithInterceptor) \ | 56 ICU(KeyedLoadPropertyWithInterceptor) \ |
| 59 ICU(StoreInterceptorProperty) \ | 57 ICU(StoreInterceptorProperty) \ |
| 60 ICU(CompareIC_Miss) \ | 58 ICU(CompareIC_Miss) \ |
| 61 ICU(BinaryOpIC_Miss) \ | 59 ICU(BinaryOpIC_Miss) \ |
| 62 ICU(CompareNilIC_Miss) \ | 60 ICU(CompareNilIC_Miss) \ |
| 63 ICU(Unreachable) \ | 61 ICU(Unreachable) \ |
| 64 ICU(ToBooleanIC_Miss) | 62 ICU(ToBooleanIC_Miss) |
| 65 // | 63 // |
| 66 // IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC, | 64 // IC is the base class for LoadIC, StoreIC, KeyedLoadIC, and KeyedStoreIC. |
| 67 // and KeyedStoreIC. | |
| 68 // | 65 // |
| 69 class IC { | 66 class IC { |
| 70 public: | 67 public: |
| 71 // The ids for utility called from the generated code. | 68 // The ids for utility called from the generated code. |
| 72 enum UtilityId { | 69 enum UtilityId { |
| 73 #define CONST_NAME(name) k##name, | 70 #define CONST_NAME(name) k##name, |
| 74 IC_UTIL_LIST(CONST_NAME) | 71 IC_UTIL_LIST(CONST_NAME) |
| 75 #undef CONST_NAME | 72 #undef CONST_NAME |
| 76 kUtilityCount | 73 kUtilityCount |
| 77 }; | 74 }; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 107 static void Clear(Isolate* isolate, Address address); | 104 static void Clear(Isolate* isolate, Address address); |
| 108 | 105 |
| 109 #ifdef DEBUG | 106 #ifdef DEBUG |
| 110 bool IsLoadStub() const { | 107 bool IsLoadStub() const { |
| 111 return target()->is_load_stub() || target()->is_keyed_load_stub(); | 108 return target()->is_load_stub() || target()->is_keyed_load_stub(); |
| 112 } | 109 } |
| 113 | 110 |
| 114 bool IsStoreStub() const { | 111 bool IsStoreStub() const { |
| 115 return target()->is_store_stub() || target()->is_keyed_store_stub(); | 112 return target()->is_store_stub() || target()->is_keyed_store_stub(); |
| 116 } | 113 } |
| 117 | |
| 118 bool IsCallStub() const { | |
| 119 return target()->is_call_stub() || target()->is_keyed_call_stub(); | |
| 120 } | |
| 121 #endif | 114 #endif |
| 122 | 115 |
| 123 // Determines which map must be used for keeping the code stub. | 116 // Determines which map must be used for keeping the code stub. |
| 124 // These methods should not be called with undefined or null. | 117 // These methods should not be called with undefined or null. |
| 125 static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object); | 118 static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object); |
| 126 // TODO(verwaest): This currently returns a HeapObject rather than JSObject* | 119 // TODO(verwaest): This currently returns a HeapObject rather than JSObject* |
| 127 // since loading the IC for loading the length from strings are stored on | 120 // since loading the IC for loading the length from strings are stored on |
| 128 // the string map directly, rather than on the JSObject-typed prototype. | 121 // the string map directly, rather than on the JSObject-typed prototype. |
| 129 static inline HeapObject* GetCodeCacheHolder(Isolate* isolate, | 122 static inline HeapObject* GetCodeCacheHolder(Isolate* isolate, |
| 130 Object* object, | 123 Object* object, |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 | 270 |
| 278 Address address() const { return address_; } | 271 Address address() const { return address_; } |
| 279 | 272 |
| 280 IC::UtilityId id() const { return id_; } | 273 IC::UtilityId id() const { return id_; } |
| 281 private: | 274 private: |
| 282 Address address_; | 275 Address address_; |
| 283 IC::UtilityId id_; | 276 IC::UtilityId id_; |
| 284 }; | 277 }; |
| 285 | 278 |
| 286 | 279 |
| 287 class CallICBase: public IC { | |
| 288 public: | |
| 289 // Returns a JSFunction or a Failure. | |
| 290 MUST_USE_RESULT MaybeObject* LoadFunction(Handle<Object> object, | |
| 291 Handle<String> name); | |
| 292 | |
| 293 protected: | |
| 294 CallICBase(Code::Kind kind, Isolate* isolate) | |
| 295 : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {} | |
| 296 | |
| 297 // Compute a monomorphic stub if possible, otherwise return a null handle. | |
| 298 Handle<Code> ComputeMonomorphicStub(LookupResult* lookup, | |
| 299 Handle<Object> object, | |
| 300 Handle<String> name); | |
| 301 | |
| 302 // Update the inline cache and the global stub cache based on the lookup | |
| 303 // result. | |
| 304 void UpdateCaches(LookupResult* lookup, | |
| 305 Handle<Object> object, | |
| 306 Handle<String> name); | |
| 307 | |
| 308 // Returns a JSFunction if the object can be called as a function, and | |
| 309 // patches the stack to be ready for the call. Otherwise, it returns the | |
| 310 // undefined value. | |
| 311 Handle<Object> TryCallAsFunction(Handle<Object> object); | |
| 312 | |
| 313 void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object); | |
| 314 | |
| 315 static void Clear(Address address, Code* target); | |
| 316 | |
| 317 // Platform-specific code generation functions used by both call and | |
| 318 // keyed call. | |
| 319 static void GenerateMiss(MacroAssembler* masm, | |
| 320 int argc, | |
| 321 IC::UtilityId id, | |
| 322 ExtraICState extra_state); | |
| 323 | |
| 324 static void GenerateNormal(MacroAssembler* masm, int argc); | |
| 325 | |
| 326 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, | |
| 327 int argc, | |
| 328 Code::Kind kind, | |
| 329 ExtraICState extra_state); | |
| 330 | |
| 331 virtual Handle<Code> megamorphic_stub(); | |
| 332 virtual Handle<Code> pre_monomorphic_stub(); | |
| 333 | |
| 334 Code::Kind kind_; | |
| 335 | |
| 336 friend class IC; | |
| 337 }; | |
| 338 | |
| 339 | |
| 340 class CallIC: public CallICBase { | |
| 341 public: | |
| 342 explicit CallIC(Isolate* isolate) | |
| 343 : CallICBase(Code::CALL_IC, isolate) { | |
| 344 ASSERT(target()->is_call_stub()); | |
| 345 } | |
| 346 | |
| 347 // Code generator routines. | |
| 348 static void GenerateInitialize(MacroAssembler* masm, | |
| 349 int argc, | |
| 350 ExtraICState extra_state) { | |
| 351 GenerateMiss(masm, argc, extra_state); | |
| 352 } | |
| 353 | |
| 354 static void GenerateMiss(MacroAssembler* masm, | |
| 355 int argc, | |
| 356 ExtraICState extra_state) { | |
| 357 CallICBase::GenerateMiss(masm, argc, IC::kCallIC_Miss, extra_state); | |
| 358 } | |
| 359 | |
| 360 static void GenerateMegamorphic(MacroAssembler* masm, | |
| 361 int argc, | |
| 362 ExtraICState extra_ic_state); | |
| 363 | |
| 364 static void GenerateNormal(MacroAssembler* masm, int argc) { | |
| 365 CallICBase::GenerateNormal(masm, argc); | |
| 366 GenerateMiss(masm, argc, kNoExtraICState); | |
| 367 } | |
| 368 bool TryUpdateExtraICState(LookupResult* lookup, Handle<Object> object); | |
| 369 }; | |
| 370 | |
| 371 | |
| 372 class KeyedCallIC: public CallICBase { | |
| 373 public: | |
| 374 explicit KeyedCallIC(Isolate* isolate) | |
| 375 : CallICBase(Code::KEYED_CALL_IC, isolate) { | |
| 376 ASSERT(target()->is_keyed_call_stub()); | |
| 377 } | |
| 378 | |
| 379 MUST_USE_RESULT MaybeObject* LoadFunction(Handle<Object> object, | |
| 380 Handle<Object> key); | |
| 381 | |
| 382 // Code generator routines. | |
| 383 static void GenerateInitialize(MacroAssembler* masm, int argc) { | |
| 384 GenerateMiss(masm, argc); | |
| 385 } | |
| 386 | |
| 387 static void GenerateMiss(MacroAssembler* masm, int argc) { | |
| 388 CallICBase::GenerateMiss(masm, argc, IC::kKeyedCallIC_Miss, | |
| 389 kNoExtraICState); | |
| 390 } | |
| 391 | |
| 392 static void GenerateMegamorphic(MacroAssembler* masm, int argc); | |
| 393 static void GenerateNormal(MacroAssembler* masm, int argc); | |
| 394 static void GenerateNonStrictArguments(MacroAssembler* masm, int argc); | |
| 395 }; | |
| 396 | |
| 397 | |
| 398 class LoadIC: public IC { | 280 class LoadIC: public IC { |
| 399 public: | 281 public: |
| 400 // ExtraICState bits | 282 // ExtraICState bits |
| 401 class Contextual: public BitField<ContextualMode, 0, 1> {}; | 283 class ContextualModeBits: public BitField<ContextualMode, 0, 1> {}; |
| 402 STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0); | 284 STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0); |
| 403 | 285 |
| 404 static ExtraICState ComputeExtraICState(ContextualMode mode) { | 286 static ExtraICState ComputeExtraICState(ContextualMode contextual_mode) { |
| 405 return Contextual::encode(mode); | 287 return ContextualModeBits::encode(contextual_mode); |
| 406 } | 288 } |
| 407 | 289 |
| 408 static ContextualMode GetContextualMode(ExtraICState state) { | 290 static ContextualMode GetContextualMode(ExtraICState state) { |
| 409 return Contextual::decode(state); | 291 return ContextualModeBits::decode(state); |
| 410 } | 292 } |
| 411 | 293 |
| 412 ContextualMode contextual_mode() const { | 294 ContextualMode contextual_mode() const { |
| 413 return Contextual::decode(extra_ic_state()); | 295 return ContextualModeBits::decode(extra_ic_state()); |
| 414 } | 296 } |
| 415 | 297 |
| 416 explicit LoadIC(FrameDepth depth, Isolate* isolate) | 298 explicit LoadIC(FrameDepth depth, Isolate* isolate) |
| 417 : IC(depth, isolate) { | 299 : IC(depth, isolate) { |
| 418 ASSERT(IsLoadStub()); | 300 ASSERT(IsLoadStub()); |
| 419 } | 301 } |
| 420 | 302 |
| 421 // Returns if this IC is for contextual (no explicit receiver) | 303 // Returns if this IC is for contextual (no explicit receiver) |
| 422 // access to properties. | 304 // access to properties. |
| 423 bool IsUndeclaredGlobal(Handle<Object> receiver) { | 305 bool IsUndeclaredGlobal(Handle<Object> receiver) { |
| 424 if (receiver->IsGlobalObject()) { | 306 if (receiver->IsGlobalObject()) { |
| 425 return contextual_mode() == CONTEXTUAL; | 307 return contextual_mode() == CONTEXTUAL; |
| 426 } else { | 308 } else { |
| 427 ASSERT(contextual_mode() != CONTEXTUAL); | 309 ASSERT(contextual_mode() != CONTEXTUAL); |
| 428 return false; | 310 return false; |
| 429 } | 311 } |
| 430 } | 312 } |
| 431 | 313 |
| 432 // Code generator routines. | 314 // Code generator routines. |
| 433 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } | 315 static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } |
| 434 static void GeneratePreMonomorphic(MacroAssembler* masm) { | 316 static void GeneratePreMonomorphic(MacroAssembler* masm) { |
| 435 GenerateMiss(masm); | 317 GenerateMiss(masm); |
| 436 } | 318 } |
| 437 static void GenerateMiss(MacroAssembler* masm); | 319 static void GenerateMiss(MacroAssembler* masm); |
| 438 static void GenerateMegamorphic(MacroAssembler* masm, ContextualMode mode); | 320 static void GenerateMegamorphic(MacroAssembler* masm, |
| 321 ExtraICState extra_state); |
| 439 static void GenerateNormal(MacroAssembler* masm); | 322 static void GenerateNormal(MacroAssembler* masm); |
| 440 static void GenerateRuntimeGetProperty(MacroAssembler* masm); | 323 static void GenerateRuntimeGetProperty(MacroAssembler* masm); |
| 441 | 324 |
| 442 static Handle<Code> initialize_stub(Isolate* isolate, ContextualMode mode); | 325 static Handle<Code> initialize_stub(Isolate* isolate, |
| 326 ExtraICState extra_state); |
| 443 | 327 |
| 444 MUST_USE_RESULT MaybeObject* Load(Handle<Object> object, | 328 MUST_USE_RESULT MaybeObject* Load(Handle<Object> object, |
| 445 Handle<String> name); | 329 Handle<String> name); |
| 446 | 330 |
| 447 protected: | 331 protected: |
| 448 virtual Code::Kind kind() const { return Code::LOAD_IC; } | 332 virtual Code::Kind kind() const { return Code::LOAD_IC; } |
| 449 | 333 |
| 450 void set_target(Code* code) { | 334 void set_target(Code* code) { |
| 451 // The contextual mode must be preserved across IC patching. | 335 // The contextual mode must be preserved across IC patching. |
| 452 ASSERT(GetContextualMode(code->extra_ic_state()) == | 336 ASSERT(GetContextualMode(code->extra_ic_state()) == |
| (...skipping 16 matching lines...) Expand all Loading... |
| 469 | 353 |
| 470 virtual Handle<Code> CompileHandler(LookupResult* lookup, | 354 virtual Handle<Code> CompileHandler(LookupResult* lookup, |
| 471 Handle<Object> object, | 355 Handle<Object> object, |
| 472 Handle<String> name, | 356 Handle<String> name, |
| 473 Handle<Object> unused, | 357 Handle<Object> unused, |
| 474 InlineCacheHolderFlag cache_holder); | 358 InlineCacheHolderFlag cache_holder); |
| 475 | 359 |
| 476 private: | 360 private: |
| 477 // Stub accessors. | 361 // Stub accessors. |
| 478 static Handle<Code> pre_monomorphic_stub(Isolate* isolate, | 362 static Handle<Code> pre_monomorphic_stub(Isolate* isolate, |
| 479 ContextualMode mode); | 363 ExtraICState exstra_state); |
| 480 | 364 |
| 481 virtual Handle<Code> pre_monomorphic_stub() { | 365 virtual Handle<Code> pre_monomorphic_stub() { |
| 482 return pre_monomorphic_stub(isolate(), contextual_mode()); | 366 return pre_monomorphic_stub(isolate(), extra_ic_state()); |
| 483 } | 367 } |
| 484 | 368 |
| 485 Handle<Code> SimpleFieldLoad(int offset, | 369 Handle<Code> SimpleFieldLoad(int offset, |
| 486 bool inobject = true, | 370 bool inobject = true, |
| 487 Representation representation = | 371 Representation representation = |
| 488 Representation::Tagged()); | 372 Representation::Tagged()); |
| 489 | 373 |
| 490 static void Clear(Isolate* isolate, Address address, Code* target); | 374 static void Clear(Isolate* isolate, Address address, Code* target); |
| 491 | 375 |
| 492 friend class IC; | 376 friend class IC; |
| (...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 | 879 |
| 996 | 880 |
| 997 // Helper for BinaryOpIC and CompareIC. | 881 // Helper for BinaryOpIC and CompareIC. |
| 998 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK }; | 882 enum InlinedSmiCheck { ENABLE_INLINED_SMI_CHECK, DISABLE_INLINED_SMI_CHECK }; |
| 999 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check); | 883 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check); |
| 1000 | 884 |
| 1001 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure); | 885 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure); |
| 1002 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure); | 886 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure); |
| 1003 DECLARE_RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss); | 887 DECLARE_RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss); |
| 1004 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure); | 888 DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure); |
| 1005 DECLARE_RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_MissFromStubFailure); | |
| 1006 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss); | 889 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss); |
| 1007 DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss); | 890 DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss); |
| 1008 DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_MissWithAllocationSite); | 891 DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_MissWithAllocationSite); |
| 1009 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss); | 892 DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss); |
| 1010 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss); | 893 DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss); |
| 1011 | 894 |
| 1012 | 895 |
| 1013 } } // namespace v8::internal | 896 } } // namespace v8::internal |
| 1014 | 897 |
| 1015 #endif // V8_IC_H_ | 898 #endif // V8_IC_H_ |
| OLD | NEW |