| 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_STUB_CACHE_H_ | 5 #ifndef V8_STUB_CACHE_H_ |
| 6 #define V8_STUB_CACHE_H_ | 6 #define V8_STUB_CACHE_H_ |
| 7 | 7 |
| 8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
| 9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 class StubCache { | 47 class StubCache { |
| 48 public: | 48 public: |
| 49 struct Entry { | 49 struct Entry { |
| 50 Name* key; | 50 Name* key; |
| 51 Code* value; | 51 Code* value; |
| 52 Map* map; | 52 Map* map; |
| 53 }; | 53 }; |
| 54 | 54 |
| 55 void Initialize(); | 55 void Initialize(); |
| 56 | 56 |
| 57 Handle<JSObject> StubHolder(Handle<JSObject> receiver, | |
| 58 Handle<JSObject> holder); | |
| 59 | |
| 60 Handle<Code> FindIC(Handle<Name> name, Handle<Map> stub_holder_map, | |
| 61 Code::Kind kind, | |
| 62 ExtraICState extra_state = kNoExtraICState, | |
| 63 CacheHolderFlag cache_holder = kCacheOnReceiver); | |
| 64 | |
| 65 Handle<Code> FindHandler(Handle<Name> name, Handle<Map> map, Code::Kind kind, | |
| 66 CacheHolderFlag cache_holder, Code::StubType type); | |
| 67 | |
| 68 Handle<Code> ComputeMonomorphicIC(Code::Kind kind, | 57 Handle<Code> ComputeMonomorphicIC(Code::Kind kind, |
| 69 Handle<Name> name, | 58 Handle<Name> name, |
| 70 Handle<HeapType> type, | 59 Handle<HeapType> type, |
| 71 Handle<Code> handler, | 60 Handle<Code> handler, |
| 72 ExtraICState extra_ic_state); | 61 ExtraICState extra_ic_state); |
| 73 | 62 |
| 74 Handle<Code> ComputeLoadNonexistent(Handle<Name> name, Handle<HeapType> type); | 63 Handle<Code> ComputeLoadNonexistent(Handle<Name> name, Handle<HeapType> type); |
| 75 | 64 |
| 76 Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map); | 65 Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map); |
| 77 | 66 |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly); | 260 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly); |
| 272 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptor); | 261 DECLARE_RUNTIME_FUNCTION(LoadPropertyWithInterceptor); |
| 273 DECLARE_RUNTIME_FUNCTION(StoreInterceptorProperty); | 262 DECLARE_RUNTIME_FUNCTION(StoreInterceptorProperty); |
| 274 DECLARE_RUNTIME_FUNCTION(KeyedLoadPropertyWithInterceptor); | 263 DECLARE_RUNTIME_FUNCTION(KeyedLoadPropertyWithInterceptor); |
| 275 | 264 |
| 276 | 265 |
| 277 enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER }; | 266 enum PrototypeCheckType { CHECK_ALL_MAPS, SKIP_RECEIVER }; |
| 278 enum IcCheckType { ELEMENT, PROPERTY }; | 267 enum IcCheckType { ELEMENT, PROPERTY }; |
| 279 | 268 |
| 280 | 269 |
| 281 // The stub compilers compile stubs for the stub cache. | 270 class PropertyAccessCompiler BASE_EMBEDDED { |
| 282 class StubCompiler BASE_EMBEDDED { | |
| 283 public: | 271 public: |
| 284 explicit StubCompiler(Isolate* isolate, | 272 static Builtins::Name MissBuiltin(Code::Kind kind) { |
| 285 ExtraICState extra_ic_state = kNoExtraICState) | 273 switch (kind) { |
| 286 : isolate_(isolate), extra_ic_state_(extra_ic_state), | 274 case Code::LOAD_IC: |
| 287 masm_(isolate, NULL, 256) { } | 275 return Builtins::kLoadIC_Miss; |
| 276 case Code::STORE_IC: |
| 277 return Builtins::kStoreIC_Miss; |
| 278 case Code::KEYED_LOAD_IC: |
| 279 return Builtins::kKeyedLoadIC_Miss; |
| 280 case Code::KEYED_STORE_IC: |
| 281 return Builtins::kKeyedStoreIC_Miss; |
| 282 default: |
| 283 UNREACHABLE(); |
| 284 } |
| 285 return Builtins::kLoadIC_Miss; |
| 286 } |
| 287 |
| 288 static void TailCallBuiltin(MacroAssembler* masm, Builtins::Name name); |
| 289 |
| 290 protected: |
| 291 PropertyAccessCompiler(Isolate* isolate, Code::Kind kind, |
| 292 ExtraICState extra_ic_state, |
| 293 CacheHolderFlag cache_holder) |
| 294 : registers_(GetCallingConvention(kind)), |
| 295 kind_(kind), |
| 296 cache_holder_(cache_holder), |
| 297 isolate_(isolate), |
| 298 extra_ic_state_(extra_ic_state), |
| 299 masm_(isolate, NULL, 256) {} |
| 300 |
| 301 Code::Kind kind() const { return kind_; } |
| 302 CacheHolderFlag cache_holder() const { return cache_holder_; } |
| 303 ExtraICState extra_state() const { return extra_ic_state_; } |
| 304 MacroAssembler* masm() { return &masm_; } |
| 305 Isolate* isolate() const { return isolate_; } |
| 306 Heap* heap() const { return isolate()->heap(); } |
| 307 Factory* factory() const { return isolate()->factory(); } |
| 308 |
| 309 Register receiver() const { return registers_[0]; } |
| 310 Register name() const { return registers_[1]; } |
| 311 Register scratch1() const { return registers_[2]; } |
| 312 Register scratch2() const { return registers_[3]; } |
| 313 Register scratch3() const { return registers_[4]; } |
| 314 |
| 315 // Calling convention between indexed store IC and handler. |
| 316 Register transition_map() const { return scratch1(); } |
| 317 |
| 318 static Register* GetCallingConvention(Code::Kind); |
| 319 static Register* load_calling_convention(); |
| 320 static Register* store_calling_convention(); |
| 321 static Register* keyed_store_calling_convention(); |
| 322 |
| 323 Register* registers_; |
| 324 |
| 325 static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code); |
| 326 |
| 327 Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name); |
| 328 Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<Name> name); |
| 329 |
| 330 private: |
| 331 Code::Kind kind_; |
| 332 CacheHolderFlag cache_holder_; |
| 333 |
| 334 Isolate* isolate_; |
| 335 const ExtraICState extra_ic_state_; |
| 336 MacroAssembler masm_; |
| 337 }; |
| 338 |
| 339 |
| 340 class PropertyICCompiler : public PropertyAccessCompiler { |
| 341 public: |
| 342 PropertyICCompiler(Isolate* isolate, Code::Kind kind, |
| 343 ExtraICState extra_ic_state = kNoExtraICState, |
| 344 CacheHolderFlag cache_holder = kCacheOnReceiver) |
| 345 : PropertyAccessCompiler(isolate, kind, extra_ic_state, cache_holder) {} |
| 346 |
| 347 static Handle<Code> Find(Handle<Name> name, Handle<Map> stub_holder_map, |
| 348 Code::Kind kind, |
| 349 ExtraICState extra_state = kNoExtraICState, |
| 350 CacheHolderFlag cache_holder = kCacheOnReceiver); |
| 288 | 351 |
| 289 Handle<Code> CompileLoadInitialize(Code::Flags flags); | 352 Handle<Code> CompileLoadInitialize(Code::Flags flags); |
| 290 Handle<Code> CompileLoadPreMonomorphic(Code::Flags flags); | 353 Handle<Code> CompileLoadPreMonomorphic(Code::Flags flags); |
| 291 Handle<Code> CompileLoadMegamorphic(Code::Flags flags); | 354 Handle<Code> CompileLoadMegamorphic(Code::Flags flags); |
| 292 | |
| 293 Handle<Code> CompileStoreInitialize(Code::Flags flags); | 355 Handle<Code> CompileStoreInitialize(Code::Flags flags); |
| 294 Handle<Code> CompileStorePreMonomorphic(Code::Flags flags); | 356 Handle<Code> CompileStorePreMonomorphic(Code::Flags flags); |
| 295 Handle<Code> CompileStoreGeneric(Code::Flags flags); | 357 Handle<Code> CompileStoreGeneric(Code::Flags flags); |
| 296 Handle<Code> CompileStoreMegamorphic(Code::Flags flags); | 358 Handle<Code> CompileStoreMegamorphic(Code::Flags flags); |
| 297 | 359 |
| 298 // Static functions for generating parts of stubs. | 360 Handle<Code> CompileMonomorphic(Handle<HeapType> type, Handle<Code> handler, |
| 299 static void GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 361 Handle<Name> name, IcCheckType check); |
| 300 int index, | 362 |
| 301 Register prototype); | 363 Handle<Code> CompilePolymorphic(TypeHandleList* types, |
| 364 CodeHandleList* handlers, Handle<Name> name, |
| 365 Code::StubType type, IcCheckType check); |
| 366 |
| 367 Handle<Code> CompileIndexedStoreMonomorphic(Handle<Map> receiver_map, |
| 368 KeyedAccessStoreMode store_mode); |
| 369 Handle<Code> CompileIndexedStorePolymorphic(MapHandleList* receiver_maps, |
| 370 KeyedAccessStoreMode store_mode); |
| 371 |
| 372 private: |
| 373 bool IncludesNumberType(TypeHandleList* types); |
| 374 |
| 375 Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name, |
| 376 InlineCacheState state = MONOMORPHIC); |
| 377 |
| 378 Logger::LogEventsAndTags log_kind(Handle<Code> code) { |
| 379 if (kind() == Code::LOAD_IC) { |
| 380 return code->ic_state() == MONOMORPHIC ? Logger::LOAD_IC_TAG |
| 381 : Logger::LOAD_POLYMORPHIC_IC_TAG; |
| 382 } else if (kind() == Code::KEYED_LOAD_IC) { |
| 383 return code->ic_state() == MONOMORPHIC |
| 384 ? Logger::KEYED_LOAD_IC_TAG |
| 385 : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG; |
| 386 } else if (kind() == Code::STORE_IC) { |
| 387 return code->ic_state() == MONOMORPHIC ? Logger::STORE_IC_TAG |
| 388 : Logger::STORE_POLYMORPHIC_IC_TAG; |
| 389 } else { |
| 390 ASSERT_EQ(Code::KEYED_STORE_IC, kind()); |
| 391 return code->ic_state() == MONOMORPHIC |
| 392 ? Logger::KEYED_STORE_IC_TAG |
| 393 : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG; |
| 394 } |
| 395 } |
| 396 |
| 397 Handle<Code> CompileIndexedStorePolymorphic(MapHandleList* receiver_maps, |
| 398 CodeHandleList* handler_stubs, |
| 399 MapHandleList* transitioned_maps); |
| 400 }; |
| 401 |
| 402 |
| 403 class PropertyHandlerCompiler : public PropertyAccessCompiler { |
| 404 public: |
| 405 static Handle<Code> Find(Handle<Name> name, Handle<Map> map, Code::Kind kind, |
| 406 CacheHolderFlag cache_holder, Code::StubType type); |
| 407 |
| 408 protected: |
| 409 PropertyHandlerCompiler(Isolate* isolate, Code::Kind kind, |
| 410 ExtraICState extra_ic_state, |
| 411 CacheHolderFlag cache_holder) |
| 412 : PropertyAccessCompiler(isolate, kind, extra_ic_state, cache_holder) {} |
| 413 |
| 414 virtual ~PropertyHandlerCompiler() {} |
| 415 |
| 416 virtual Register FrontendHeader(Handle<HeapType> type, Register object_reg, |
| 417 Handle<JSObject> holder, Handle<Name> name, |
| 418 Label* miss) { |
| 419 UNREACHABLE(); |
| 420 return receiver(); |
| 421 } |
| 422 |
| 423 virtual void FrontendFooter(Handle<Name> name, Label* miss) { UNREACHABLE(); } |
| 424 |
| 425 Register Frontend(Handle<HeapType> type, Register object_reg, |
| 426 Handle<JSObject> holder, Handle<Name> name); |
| 427 |
| 428 // TODO(verwaest): Make non-static. |
| 429 static void GenerateFastApiCall(MacroAssembler* masm, |
| 430 const CallOptimization& optimization, |
| 431 Handle<Map> receiver_map, Register receiver, |
| 432 Register scratch, bool is_store, int argc, |
| 433 Register* values); |
| 302 | 434 |
| 303 // Helper function used to check that the dictionary doesn't contain | 435 // Helper function used to check that the dictionary doesn't contain |
| 304 // the property. This function may return false negatives, so miss_label | 436 // the property. This function may return false negatives, so miss_label |
| 305 // must always call a backup property check that is complete. | 437 // must always call a backup property check that is complete. |
| 306 // This function is safe to call if the receiver has fast properties. | 438 // This function is safe to call if the receiver has fast properties. |
| 307 // Name must be unique and receiver must be a heap object. | 439 // Name must be unique and receiver must be a heap object. |
| 308 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 440 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, |
| 309 Label* miss_label, | 441 Label* miss_label, |
| 310 Register receiver, | 442 Register receiver, |
| 311 Handle<Name> name, | 443 Handle<Name> name, |
| 312 Register r0, | 444 Register r0, |
| 313 Register r1); | 445 Register r1); |
| 314 | 446 |
| 315 // Generates prototype loading code that uses the objects from the | |
| 316 // context we were in when this function was called. If the context | |
| 317 // has changed, a jump to miss is performed. This ties the generated | |
| 318 // code to a particular context and so must not be used in cases | |
| 319 // where the generated code is not allowed to have references to | |
| 320 // objects from a context. | |
| 321 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm, | |
| 322 int index, | |
| 323 Register prototype, | |
| 324 Label* miss); | |
| 325 | |
| 326 static void GenerateFastPropertyLoad(MacroAssembler* masm, | |
| 327 Register dst, | |
| 328 Register src, | |
| 329 bool inobject, | |
| 330 int index, | |
| 331 Representation representation); | |
| 332 | |
| 333 static void GenerateLoadArrayLength(MacroAssembler* masm, | |
| 334 Register receiver, | |
| 335 Register scratch, | |
| 336 Label* miss_label); | |
| 337 | |
| 338 static void GenerateLoadFunctionPrototype(MacroAssembler* masm, | |
| 339 Register receiver, | |
| 340 Register scratch1, | |
| 341 Register scratch2, | |
| 342 Label* miss_label); | |
| 343 | |
| 344 // Generate code to check that a global property cell is empty. Create | 447 // Generate code to check that a global property cell is empty. Create |
| 345 // the property cell at compilation time if no cell exists for the | 448 // the property cell at compilation time if no cell exists for the |
| 346 // property. | 449 // property. |
| 347 static void GenerateCheckPropertyCell(MacroAssembler* masm, | 450 static void GenerateCheckPropertyCell(MacroAssembler* masm, |
| 348 Handle<JSGlobalObject> global, | 451 Handle<JSGlobalObject> global, |
| 349 Handle<Name> name, | 452 Handle<Name> name, |
| 350 Register scratch, | 453 Register scratch, |
| 351 Label* miss); | 454 Label* miss); |
| 352 | 455 |
| 353 static void TailCallBuiltin(MacroAssembler* masm, Builtins::Name name); | |
| 354 | |
| 355 // Generates code that verifies that the property holder has not changed | 456 // Generates code that verifies that the property holder has not changed |
| 356 // (checking maps of objects in the prototype chain for fast and global | 457 // (checking maps of objects in the prototype chain for fast and global |
| 357 // objects or doing negative lookup for slow objects, ensures that the | 458 // objects or doing negative lookup for slow objects, ensures that the |
| 358 // property cells for global objects are still empty) and checks that the map | 459 // property cells for global objects are still empty) and checks that the map |
| 359 // of the holder has not changed. If necessary the function also generates | 460 // of the holder has not changed. If necessary the function also generates |
| 360 // code for security check in case of global object holders. Helps to make | 461 // code for security check in case of global object holders. Helps to make |
| 361 // sure that the current IC is still valid. | 462 // sure that the current IC is still valid. |
| 362 // | 463 // |
| 363 // The scratch and holder registers are always clobbered, but the object | 464 // The scratch and holder registers are always clobbered, but the object |
| 364 // register is only clobbered if it the same as the holder register. The | 465 // register is only clobbered if it the same as the holder register. The |
| 365 // function returns a register containing the holder - either object_reg or | 466 // function returns a register containing the holder - either object_reg or |
| 366 // holder_reg. | 467 // holder_reg. |
| 367 Register CheckPrototypes(Handle<HeapType> type, | 468 Register CheckPrototypes(Handle<HeapType> type, |
| 368 Register object_reg, | 469 Register object_reg, |
| 369 Handle<JSObject> holder, | 470 Handle<JSObject> holder, |
| 370 Register holder_reg, | 471 Register holder_reg, |
| 371 Register scratch1, | 472 Register scratch1, |
| 372 Register scratch2, | 473 Register scratch2, |
| 373 Handle<Name> name, | 474 Handle<Name> name, |
| 374 Label* miss, | 475 Label* miss, |
| 375 PrototypeCheckType check = CHECK_ALL_MAPS); | 476 PrototypeCheckType check = CHECK_ALL_MAPS); |
| 376 | 477 |
| 377 static void GenerateFastApiCall(MacroAssembler* masm, | 478 Handle<Code> GetCode(Code::Kind kind, Code::StubType type, Handle<Name> name); |
| 378 const CallOptimization& optimization, | |
| 379 Handle<Map> receiver_map, | |
| 380 Register receiver, | |
| 381 Register scratch, | |
| 382 bool is_store, | |
| 383 int argc, | |
| 384 Register* values); | |
| 385 | |
| 386 protected: | |
| 387 Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name); | |
| 388 Handle<Code> GetCodeWithFlags(Code::Flags flags, Handle<Name> name); | |
| 389 | |
| 390 ExtraICState extra_state() { return extra_ic_state_; } | |
| 391 | |
| 392 MacroAssembler* masm() { return &masm_; } | |
| 393 | |
| 394 static void LookupPostInterceptor(Handle<JSObject> holder, | |
| 395 Handle<Name> name, | |
| 396 LookupResult* lookup); | |
| 397 | |
| 398 Isolate* isolate() { return isolate_; } | |
| 399 Heap* heap() { return isolate()->heap(); } | |
| 400 Factory* factory() { return isolate()->factory(); } | |
| 401 | |
| 402 static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code); | |
| 403 | |
| 404 private: | |
| 405 Isolate* isolate_; | |
| 406 const ExtraICState extra_ic_state_; | |
| 407 MacroAssembler masm_; | |
| 408 }; | 479 }; |
| 409 | 480 |
| 410 | 481 |
| 411 enum FrontendCheckType { PERFORM_INITIAL_CHECKS, SKIP_INITIAL_CHECKS }; | 482 class NamedLoadHandlerCompiler : public PropertyHandlerCompiler { |
| 483 public: |
| 484 NamedLoadHandlerCompiler(Isolate* isolate, Code::Kind kind = Code::LOAD_IC, |
| 485 ExtraICState extra_ic_state = kNoExtraICState, |
| 486 CacheHolderFlag cache_holder = kCacheOnReceiver) |
| 487 : PropertyHandlerCompiler(isolate, kind, extra_ic_state, cache_holder) {} |
| 412 | 488 |
| 413 | 489 virtual ~NamedLoadHandlerCompiler() {} |
| 414 class BaseLoadStoreStubCompiler: public StubCompiler { | |
| 415 public: | |
| 416 BaseLoadStoreStubCompiler(Isolate* isolate, Code::Kind kind, | |
| 417 ExtraICState extra_ic_state = kNoExtraICState, | |
| 418 CacheHolderFlag cache_holder = kCacheOnReceiver) | |
| 419 : StubCompiler(isolate, extra_ic_state), | |
| 420 kind_(kind), | |
| 421 cache_holder_(cache_holder) { | |
| 422 InitializeRegisters(); | |
| 423 } | |
| 424 virtual ~BaseLoadStoreStubCompiler() { } | |
| 425 | |
| 426 Handle<Code> CompileMonomorphicIC(Handle<HeapType> type, | |
| 427 Handle<Code> handler, | |
| 428 Handle<Name> name); | |
| 429 | |
| 430 Handle<Code> CompilePolymorphicIC(TypeHandleList* types, | |
| 431 CodeHandleList* handlers, | |
| 432 Handle<Name> name, | |
| 433 Code::StubType type, | |
| 434 IcCheckType check); | |
| 435 | |
| 436 static Builtins::Name MissBuiltin(Code::Kind kind) { | |
| 437 switch (kind) { | |
| 438 case Code::LOAD_IC: return Builtins::kLoadIC_Miss; | |
| 439 case Code::STORE_IC: return Builtins::kStoreIC_Miss; | |
| 440 case Code::KEYED_LOAD_IC: return Builtins::kKeyedLoadIC_Miss; | |
| 441 case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Miss; | |
| 442 default: UNREACHABLE(); | |
| 443 } | |
| 444 return Builtins::kLoadIC_Miss; | |
| 445 } | |
| 446 | |
| 447 protected: | |
| 448 virtual Register HandlerFrontendHeader(Handle<HeapType> type, | |
| 449 Register object_reg, | |
| 450 Handle<JSObject> holder, | |
| 451 Handle<Name> name, | |
| 452 Label* miss) = 0; | |
| 453 | |
| 454 virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss) = 0; | |
| 455 | |
| 456 Register HandlerFrontend(Handle<HeapType> type, | |
| 457 Register object_reg, | |
| 458 Handle<JSObject> holder, | |
| 459 Handle<Name> name); | |
| 460 | |
| 461 Handle<Code> GetCode(Code::Kind kind, | |
| 462 Code::StubType type, | |
| 463 Handle<Name> name); | |
| 464 | |
| 465 Handle<Code> GetICCode(Code::Kind kind, | |
| 466 Code::StubType type, | |
| 467 Handle<Name> name, | |
| 468 InlineCacheState state = MONOMORPHIC); | |
| 469 Code::Kind kind() { return kind_; } | |
| 470 | |
| 471 Logger::LogEventsAndTags log_kind(Handle<Code> code) { | |
| 472 if (!code->is_inline_cache_stub()) return Logger::STUB_TAG; | |
| 473 if (kind_ == Code::LOAD_IC) { | |
| 474 return code->ic_state() == MONOMORPHIC | |
| 475 ? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG; | |
| 476 } else if (kind_ == Code::KEYED_LOAD_IC) { | |
| 477 return code->ic_state() == MONOMORPHIC | |
| 478 ? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG; | |
| 479 } else if (kind_ == Code::STORE_IC) { | |
| 480 return code->ic_state() == MONOMORPHIC | |
| 481 ? Logger::STORE_IC_TAG : Logger::STORE_POLYMORPHIC_IC_TAG; | |
| 482 } else { | |
| 483 return code->ic_state() == MONOMORPHIC | |
| 484 ? Logger::KEYED_STORE_IC_TAG : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG; | |
| 485 } | |
| 486 } | |
| 487 | |
| 488 Register receiver() { return registers_[0]; } | |
| 489 Register name() { return registers_[1]; } | |
| 490 Register scratch1() { return registers_[2]; } | |
| 491 Register scratch2() { return registers_[3]; } | |
| 492 Register scratch3() { return registers_[4]; } | |
| 493 | |
| 494 void InitializeRegisters(); | |
| 495 | |
| 496 bool IncludesNumberType(TypeHandleList* types); | |
| 497 | |
| 498 Code::Kind kind_; | |
| 499 CacheHolderFlag cache_holder_; | |
| 500 Register* registers_; | |
| 501 }; | |
| 502 | |
| 503 | |
| 504 class LoadStubCompiler: public BaseLoadStoreStubCompiler { | |
| 505 public: | |
| 506 LoadStubCompiler(Isolate* isolate, Code::Kind kind = Code::LOAD_IC, | |
| 507 ExtraICState extra_ic_state = kNoExtraICState, | |
| 508 CacheHolderFlag cache_holder = kCacheOnReceiver) | |
| 509 : BaseLoadStoreStubCompiler(isolate, kind, extra_ic_state, cache_holder) { | |
| 510 } | |
| 511 virtual ~LoadStubCompiler() { } | |
| 512 static Register* registers(); | |
| 513 | 490 |
| 514 Handle<Code> CompileLoadField(Handle<HeapType> type, | 491 Handle<Code> CompileLoadField(Handle<HeapType> type, |
| 515 Handle<JSObject> holder, | 492 Handle<JSObject> holder, |
| 516 Handle<Name> name, | 493 Handle<Name> name, |
| 517 FieldIndex index, | 494 FieldIndex index, |
| 518 Representation representation); | 495 Representation representation); |
| 519 | 496 |
| 520 Handle<Code> CompileLoadCallback(Handle<HeapType> type, | 497 Handle<Code> CompileLoadCallback(Handle<HeapType> type, |
| 521 Handle<JSObject> holder, | 498 Handle<JSObject> holder, |
| 522 Handle<Name> name, | 499 Handle<Name> name, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 534 | 511 |
| 535 Handle<Code> CompileLoadInterceptor(Handle<HeapType> type, | 512 Handle<Code> CompileLoadInterceptor(Handle<HeapType> type, |
| 536 Handle<JSObject> holder, | 513 Handle<JSObject> holder, |
| 537 Handle<Name> name); | 514 Handle<Name> name); |
| 538 | 515 |
| 539 Handle<Code> CompileLoadViaGetter(Handle<HeapType> type, | 516 Handle<Code> CompileLoadViaGetter(Handle<HeapType> type, |
| 540 Handle<JSObject> holder, | 517 Handle<JSObject> holder, |
| 541 Handle<Name> name, | 518 Handle<Name> name, |
| 542 Handle<JSFunction> getter); | 519 Handle<JSFunction> getter); |
| 543 | 520 |
| 544 static void GenerateLoadViaGetter(MacroAssembler* masm, | |
| 545 Handle<HeapType> type, | |
| 546 Register receiver, | |
| 547 Handle<JSFunction> getter); | |
| 548 | |
| 549 static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) { | |
| 550 GenerateLoadViaGetter( | |
| 551 masm, Handle<HeapType>::null(), no_reg, Handle<JSFunction>()); | |
| 552 } | |
| 553 | |
| 554 Handle<Code> CompileLoadNonexistent(Handle<HeapType> type, | 521 Handle<Code> CompileLoadNonexistent(Handle<HeapType> type, |
| 555 Handle<JSObject> last, | 522 Handle<JSObject> last, |
| 556 Handle<Name> name); | 523 Handle<Name> name); |
| 557 | 524 |
| 558 Handle<Code> CompileLoadGlobal(Handle<HeapType> type, | 525 Handle<Code> CompileLoadGlobal(Handle<HeapType> type, |
| 559 Handle<GlobalObject> holder, | 526 Handle<GlobalObject> holder, |
| 560 Handle<PropertyCell> cell, | 527 Handle<PropertyCell> cell, |
| 561 Handle<Name> name, | 528 Handle<Name> name, |
| 562 bool is_dont_delete); | 529 bool is_dont_delete); |
| 563 | 530 |
| 564 protected: | 531 static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<HeapType> type, |
| 565 ContextualMode contextual_mode() { | 532 Register receiver, |
| 566 return LoadIC::GetContextualMode(extra_state()); | 533 Handle<JSFunction> getter); |
| 534 |
| 535 static void GenerateLoadViaGetterForDeopt(MacroAssembler* masm) { |
| 536 GenerateLoadViaGetter(masm, Handle<HeapType>::null(), no_reg, |
| 537 Handle<JSFunction>()); |
| 567 } | 538 } |
| 568 | 539 |
| 569 virtual Register HandlerFrontendHeader(Handle<HeapType> type, | 540 static void GenerateLoadFunctionPrototype(MacroAssembler* masm, |
| 570 Register object_reg, | 541 Register receiver, |
| 571 Handle<JSObject> holder, | 542 Register scratch1, |
| 572 Handle<Name> name, | 543 Register scratch2, |
| 573 Label* miss); | 544 Label* miss_label); |
| 574 | 545 |
| 575 virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss); | 546 protected: |
| 547 virtual Register FrontendHeader(Handle<HeapType> type, Register object_reg, |
| 548 Handle<JSObject> holder, Handle<Name> name, |
| 549 Label* miss); |
| 576 | 550 |
| 577 Register CallbackHandlerFrontend(Handle<HeapType> type, | 551 virtual void FrontendFooter(Handle<Name> name, Label* miss); |
| 578 Register object_reg, | 552 |
| 579 Handle<JSObject> holder, | 553 private: |
| 580 Handle<Name> name, | 554 Register CallbackFrontend(Handle<HeapType> type, Register object_reg, |
| 581 Handle<Object> callback); | 555 Handle<JSObject> holder, Handle<Name> name, |
| 582 void NonexistentHandlerFrontend(Handle<HeapType> type, | 556 Handle<Object> callback); |
| 583 Handle<JSObject> last, | 557 void NonexistentFrontend(Handle<HeapType> type, Handle<JSObject> last, |
| 584 Handle<Name> name); | 558 Handle<Name> name); |
| 585 | 559 |
| 586 void GenerateLoadField(Register reg, | 560 void GenerateLoadField(Register reg, |
| 587 Handle<JSObject> holder, | 561 Handle<JSObject> holder, |
| 588 FieldIndex field, | 562 FieldIndex field, |
| 589 Representation representation); | 563 Representation representation); |
| 590 void GenerateLoadConstant(Handle<Object> value); | 564 void GenerateLoadConstant(Handle<Object> value); |
| 591 void GenerateLoadCallback(Register reg, | 565 void GenerateLoadCallback(Register reg, |
| 592 Handle<ExecutableAccessorInfo> callback); | 566 Handle<ExecutableAccessorInfo> callback); |
| 593 void GenerateLoadCallback(const CallOptimization& call_optimization, | 567 void GenerateLoadCallback(const CallOptimization& call_optimization, |
| 594 Handle<Map> receiver_map); | 568 Handle<Map> receiver_map); |
| 595 void GenerateLoadInterceptor(Register holder_reg, | 569 void GenerateLoadInterceptor(Register holder_reg, |
| 596 Handle<Object> object, | 570 Handle<Object> object, |
| 597 Handle<JSObject> holder, | 571 Handle<JSObject> holder, |
| 598 LookupResult* lookup, | 572 LookupResult* lookup, |
| 599 Handle<Name> name); | 573 Handle<Name> name); |
| 600 void GenerateLoadPostInterceptor(Register reg, | 574 void GenerateLoadPostInterceptor(Register reg, |
| 601 Handle<JSObject> interceptor_holder, | 575 Handle<JSObject> interceptor_holder, |
| 602 Handle<Name> name, | 576 Handle<Name> name, |
| 603 LookupResult* lookup); | 577 LookupResult* lookup); |
| 604 | 578 |
| 605 private: | 579 // Generates prototype loading code that uses the objects from the |
| 580 // context we were in when this function was called. If the context |
| 581 // has changed, a jump to miss is performed. This ties the generated |
| 582 // code to a particular context and so must not be used in cases |
| 583 // where the generated code is not allowed to have references to |
| 584 // objects from a context. |
| 585 static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm, |
| 586 int index, |
| 587 Register prototype, |
| 588 Label* miss); |
| 589 |
| 590 |
| 606 Register scratch4() { return registers_[5]; } | 591 Register scratch4() { return registers_[5]; } |
| 607 friend class BaseLoadStoreStubCompiler; | |
| 608 }; | 592 }; |
| 609 | 593 |
| 610 | 594 |
| 611 class KeyedLoadStubCompiler : public StubCompiler { | 595 class NamedStoreHandlerCompiler : public PropertyHandlerCompiler { |
| 612 public: | 596 public: |
| 613 KeyedLoadStubCompiler(Isolate* isolate, | 597 NamedStoreHandlerCompiler(Isolate* isolate, Code::Kind kind = Code::STORE_IC) |
| 614 ExtraICState extra_ic_state = kNoExtraICState) | 598 // Handlers do not use strict mode. |
| 615 : StubCompiler(isolate, extra_ic_state) { | 599 : PropertyHandlerCompiler(isolate, kind, kNoExtraICState, |
| 616 registers_ = LoadStubCompiler::registers(); | 600 kCacheOnReceiver) {} |
| 617 } | |
| 618 | 601 |
| 619 Handle<Code> CompileLoadElement(Handle<Map> receiver_map); | 602 virtual ~NamedStoreHandlerCompiler() {} |
| 620 | |
| 621 void CompileElementHandlers(MapHandleList* receiver_maps, | |
| 622 CodeHandleList* handlers); | |
| 623 | |
| 624 static void GenerateLoadDictionaryElement(MacroAssembler* masm); | |
| 625 | |
| 626 Register receiver() { return registers_[0]; } | |
| 627 Register name() { return registers_[1]; } | |
| 628 Register scratch1() { return registers_[2]; } | |
| 629 Register scratch2() { return registers_[3]; } | |
| 630 Register scratch3() { return registers_[4]; } | |
| 631 | |
| 632 private: | |
| 633 static Register* registers(); | |
| 634 Register* registers_; | |
| 635 }; | |
| 636 | |
| 637 | |
| 638 class StoreStubCompiler: public BaseLoadStoreStubCompiler { | |
| 639 public: | |
| 640 StoreStubCompiler(Isolate* isolate, | |
| 641 ExtraICState extra_ic_state, | |
| 642 Code::Kind kind = Code::STORE_IC) | |
| 643 : BaseLoadStoreStubCompiler(isolate, kind, extra_ic_state) {} | |
| 644 | |
| 645 virtual ~StoreStubCompiler() { } | |
| 646 | 603 |
| 647 Handle<Code> CompileStoreTransition(Handle<JSObject> object, | 604 Handle<Code> CompileStoreTransition(Handle<JSObject> object, |
| 648 LookupResult* lookup, | 605 LookupResult* lookup, |
| 649 Handle<Map> transition, | 606 Handle<Map> transition, |
| 650 Handle<Name> name); | 607 Handle<Name> name); |
| 651 | 608 |
| 652 Handle<Code> CompileStoreField(Handle<JSObject> object, | 609 Handle<Code> CompileStoreField(Handle<JSObject> object, |
| 653 LookupResult* lookup, | 610 LookupResult* lookup, |
| 654 Handle<Name> name); | 611 Handle<Name> name); |
| 655 | 612 |
| 656 Handle<Code> CompileStoreArrayLength(Handle<JSObject> object, | 613 Handle<Code> CompileStoreArrayLength(Handle<JSObject> object, |
| 657 LookupResult* lookup, | 614 LookupResult* lookup, |
| 658 Handle<Name> name); | 615 Handle<Name> name); |
| 659 | 616 |
| 617 Handle<Code> CompileStoreCallback(Handle<JSObject> object, |
| 618 Handle<JSObject> holder, Handle<Name> name, |
| 619 Handle<ExecutableAccessorInfo> callback); |
| 620 |
| 621 Handle<Code> CompileStoreCallback(Handle<JSObject> object, |
| 622 Handle<JSObject> holder, Handle<Name> name, |
| 623 const CallOptimization& call_optimization); |
| 624 |
| 625 Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, |
| 626 Handle<JSObject> holder, Handle<Name> name, |
| 627 Handle<JSFunction> setter); |
| 628 |
| 629 Handle<Code> CompileStoreInterceptor(Handle<JSObject> object, |
| 630 Handle<Name> name); |
| 631 |
| 632 |
| 633 static void GenerateStoreViaSetter(MacroAssembler* masm, |
| 634 Handle<HeapType> type, Register receiver, |
| 635 Handle<JSFunction> setter); |
| 636 |
| 637 static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) { |
| 638 GenerateStoreViaSetter(masm, Handle<HeapType>::null(), no_reg, |
| 639 Handle<JSFunction>()); |
| 640 } |
| 641 |
| 642 protected: |
| 643 virtual Register FrontendHeader(Handle<HeapType> type, Register object_reg, |
| 644 Handle<JSObject> holder, Handle<Name> name, |
| 645 Label* miss); |
| 646 |
| 647 virtual void FrontendFooter(Handle<Name> name, Label* miss); |
| 648 void GenerateRestoreName(MacroAssembler* masm, Label* label, |
| 649 Handle<Name> name); |
| 650 |
| 651 private: |
| 660 void GenerateStoreArrayLength(); | 652 void GenerateStoreArrayLength(); |
| 661 | 653 |
| 662 void GenerateNegativeHolderLookup(MacroAssembler* masm, | 654 void GenerateNegativeHolderLookup(MacroAssembler* masm, |
| 663 Handle<JSObject> holder, | 655 Handle<JSObject> holder, |
| 664 Register holder_reg, | 656 Register holder_reg, |
| 665 Handle<Name> name, | 657 Handle<Name> name, |
| 666 Label* miss); | 658 Label* miss); |
| 667 | 659 |
| 668 void GenerateStoreTransition(MacroAssembler* masm, | 660 void GenerateStoreTransition(MacroAssembler* masm, |
| 669 Handle<JSObject> object, | 661 Handle<JSObject> object, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 682 void GenerateStoreField(MacroAssembler* masm, | 674 void GenerateStoreField(MacroAssembler* masm, |
| 683 Handle<JSObject> object, | 675 Handle<JSObject> object, |
| 684 LookupResult* lookup, | 676 LookupResult* lookup, |
| 685 Register receiver_reg, | 677 Register receiver_reg, |
| 686 Register name_reg, | 678 Register name_reg, |
| 687 Register value_reg, | 679 Register value_reg, |
| 688 Register scratch1, | 680 Register scratch1, |
| 689 Register scratch2, | 681 Register scratch2, |
| 690 Label* miss_label); | 682 Label* miss_label); |
| 691 | 683 |
| 692 Handle<Code> CompileStoreCallback(Handle<JSObject> object, | |
| 693 Handle<JSObject> holder, | |
| 694 Handle<Name> name, | |
| 695 Handle<ExecutableAccessorInfo> callback); | |
| 696 | |
| 697 Handle<Code> CompileStoreCallback(Handle<JSObject> object, | |
| 698 Handle<JSObject> holder, | |
| 699 Handle<Name> name, | |
| 700 const CallOptimization& call_optimization); | |
| 701 | |
| 702 static void GenerateStoreViaSetter(MacroAssembler* masm, | |
| 703 Handle<HeapType> type, | |
| 704 Register receiver, | |
| 705 Handle<JSFunction> setter); | |
| 706 | |
| 707 static void GenerateStoreViaSetterForDeopt(MacroAssembler* masm) { | |
| 708 GenerateStoreViaSetter( | |
| 709 masm, Handle<HeapType>::null(), no_reg, Handle<JSFunction>()); | |
| 710 } | |
| 711 | |
| 712 Handle<Code> CompileStoreViaSetter(Handle<JSObject> object, | |
| 713 Handle<JSObject> holder, | |
| 714 Handle<Name> name, | |
| 715 Handle<JSFunction> setter); | |
| 716 | |
| 717 Handle<Code> CompileStoreInterceptor(Handle<JSObject> object, | |
| 718 Handle<Name> name); | |
| 719 | |
| 720 static Builtins::Name SlowBuiltin(Code::Kind kind) { | 684 static Builtins::Name SlowBuiltin(Code::Kind kind) { |
| 721 switch (kind) { | 685 switch (kind) { |
| 722 case Code::STORE_IC: return Builtins::kStoreIC_Slow; | 686 case Code::STORE_IC: return Builtins::kStoreIC_Slow; |
| 723 case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Slow; | 687 case Code::KEYED_STORE_IC: return Builtins::kKeyedStoreIC_Slow; |
| 724 default: UNREACHABLE(); | 688 default: UNREACHABLE(); |
| 725 } | 689 } |
| 726 return Builtins::kStoreIC_Slow; | 690 return Builtins::kStoreIC_Slow; |
| 727 } | 691 } |
| 728 | 692 |
| 729 protected: | |
| 730 virtual Register HandlerFrontendHeader(Handle<HeapType> type, | |
| 731 Register object_reg, | |
| 732 Handle<JSObject> holder, | |
| 733 Handle<Name> name, | |
| 734 Label* miss); | |
| 735 | |
| 736 virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss); | |
| 737 void GenerateRestoreName(MacroAssembler* masm, | |
| 738 Label* label, | |
| 739 Handle<Name> name); | |
| 740 | |
| 741 private: | |
| 742 static Register* registers(); | |
| 743 static Register value(); | 693 static Register value(); |
| 744 friend class BaseLoadStoreStubCompiler; | |
| 745 }; | 694 }; |
| 746 | 695 |
| 747 | 696 |
| 748 class KeyedStoreStubCompiler: public StoreStubCompiler { | 697 class IndexedHandlerCompiler : public PropertyHandlerCompiler { |
| 749 public: | 698 public: |
| 750 KeyedStoreStubCompiler(Isolate* isolate, | 699 IndexedHandlerCompiler(Isolate* isolate, |
| 751 ExtraICState extra_ic_state) | 700 ExtraICState extra_ic_state = kNoExtraICState) |
| 752 : StoreStubCompiler(isolate, extra_ic_state, Code::KEYED_STORE_IC) {} | 701 : PropertyHandlerCompiler(isolate, Code::KEYED_LOAD_IC, extra_ic_state, |
| 702 kCacheOnReceiver) {} |
| 753 | 703 |
| 754 Handle<Code> CompileStoreElement(Handle<Map> receiver_map); | 704 virtual ~IndexedHandlerCompiler() {} |
| 755 | 705 |
| 756 Handle<Code> CompileStorePolymorphic(MapHandleList* receiver_maps, | 706 void CompileElementHandlers(MapHandleList* receiver_maps, |
| 757 CodeHandleList* handler_stubs, | 707 CodeHandleList* handlers); |
| 758 MapHandleList* transitioned_maps); | |
| 759 | 708 |
| 760 Handle<Code> CompileStoreElementPolymorphic(MapHandleList* receiver_maps); | 709 static void GenerateLoadDictionaryElement(MacroAssembler* masm); |
| 761 | |
| 762 static void GenerateStoreDictionaryElement(MacroAssembler* masm); | 710 static void GenerateStoreDictionaryElement(MacroAssembler* masm); |
| 763 | |
| 764 private: | |
| 765 static Register* registers(); | |
| 766 | |
| 767 KeyedAccessStoreMode store_mode() { | |
| 768 return KeyedStoreIC::GetKeyedAccessStoreMode(extra_state()); | |
| 769 } | |
| 770 | |
| 771 Register transition_map() { return scratch1(); } | |
| 772 | |
| 773 friend class BaseLoadStoreStubCompiler; | |
| 774 }; | 711 }; |
| 775 | 712 |
| 776 | 713 |
| 777 // Holds information about possible function call optimizations. | 714 // Holds information about possible function call optimizations. |
| 778 class CallOptimization BASE_EMBEDDED { | 715 class CallOptimization BASE_EMBEDDED { |
| 779 public: | 716 public: |
| 780 explicit CallOptimization(LookupResult* lookup); | 717 explicit CallOptimization(LookupResult* lookup); |
| 781 | 718 |
| 782 explicit CallOptimization(Handle<JSFunction> function); | 719 explicit CallOptimization(Handle<JSFunction> function); |
| 783 | 720 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 Handle<JSFunction> constant_function_; | 764 Handle<JSFunction> constant_function_; |
| 828 bool is_simple_api_call_; | 765 bool is_simple_api_call_; |
| 829 Handle<FunctionTemplateInfo> expected_receiver_type_; | 766 Handle<FunctionTemplateInfo> expected_receiver_type_; |
| 830 Handle<CallHandlerInfo> api_call_info_; | 767 Handle<CallHandlerInfo> api_call_info_; |
| 831 }; | 768 }; |
| 832 | 769 |
| 833 | 770 |
| 834 } } // namespace v8::internal | 771 } } // namespace v8::internal |
| 835 | 772 |
| 836 #endif // V8_STUB_CACHE_H_ | 773 #endif // V8_STUB_CACHE_H_ |
| OLD | NEW |