Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(263)

Side by Side Diff: src/x64/stub-cache-x64.cc

Issue 2124021: Comment the code for loading and calling with interceptor. (Closed)
Patch Set: Minor corrections Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« src/arm/stub-cache-arm.cc ('K') | « src/ia32/stub-cache-ia32.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 class LoadInterceptorCompiler BASE_EMBEDDED { 423 class LoadInterceptorCompiler BASE_EMBEDDED {
424 public: 424 public:
425 explicit LoadInterceptorCompiler(Register name) : name_(name) {} 425 explicit LoadInterceptorCompiler(Register name) : name_(name) {}
426 426
427 void CompileCacheable(MacroAssembler* masm, 427 void CompileCacheable(MacroAssembler* masm,
428 StubCompiler* stub_compiler, 428 StubCompiler* stub_compiler,
429 Register receiver, 429 Register receiver,
430 Register holder, 430 Register holder,
431 Register scratch1, 431 Register scratch1,
432 Register scratch2, 432 Register scratch2,
433 JSObject* holder_obj, 433 JSObject* interceptor_holder,
434 LookupResult* lookup, 434 LookupResult* lookup,
435 String* name, 435 String* name,
436 Label* miss_label) { 436 Label* miss_label) {
437 AccessorInfo* callback = NULL; 437 AccessorInfo* callback = NULL;
438 bool optimize = false; 438 bool optimize = false;
439 // So far the most popular follow ups for interceptor loads are FIELD 439 // So far the most popular follow ups for interceptor loads are FIELD
440 // and CALLBACKS, so inline only them, other cases may be added 440 // and CALLBACKS, so inline only them, other cases may be added
441 // later. 441 // later.
442 if (lookup->type() == FIELD) { 442 if (lookup->type() == FIELD) {
443 optimize = true; 443 optimize = true;
444 } else if (lookup->type() == CALLBACKS) { 444 } else if (lookup->type() == CALLBACKS) {
445 Object* callback_object = lookup->GetCallbackObject(); 445 Object* callback_object = lookup->GetCallbackObject();
446 if (callback_object->IsAccessorInfo()) { 446 if (callback_object->IsAccessorInfo()) {
447 callback = AccessorInfo::cast(callback_object); 447 callback = AccessorInfo::cast(callback_object);
448 optimize = callback->getter() != NULL; 448 optimize = callback->getter() != NULL;
449 } 449 }
450 } 450 }
451 451
452 if (!optimize) { 452 if (!optimize) {
453 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); 453 CompileRegular(masm, receiver, holder, scratch2, interceptor_holder,
454 miss_label);
454 return; 455 return;
455 } 456 }
456 457
457 // Note: starting a frame here makes GC aware of pointers pushed below. 458 // Note: starting a frame here makes GC aware of pointers pushed below.
458 __ EnterInternalFrame(); 459 __ EnterInternalFrame();
459 460
460 if (lookup->type() == CALLBACKS) { 461 if (lookup->type() == CALLBACKS) {
461 __ push(receiver); 462 __ push(receiver);
462 } 463 }
463 __ push(holder); 464 __ push(holder);
464 __ push(name_); 465 __ push(name_);
465 466
467 // Invoke an interceptor. Note: map checks from receiver to
468 // interceptor's holder has been compiled before (see a caller
469 // of this method.)
466 CompileCallLoadPropertyWithInterceptor(masm, 470 CompileCallLoadPropertyWithInterceptor(masm,
467 receiver, 471 receiver,
468 holder, 472 holder,
469 name_, 473 name_,
470 holder_obj); 474 interceptor_holder);
471 475
476 // Check if interceptor provided a value for property. If it's
477 // the case, return immediately.
472 Label interceptor_failed; 478 Label interceptor_failed;
473 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); 479 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
474 __ j(equal, &interceptor_failed); 480 __ j(equal, &interceptor_failed);
475 __ LeaveInternalFrame(); 481 __ LeaveInternalFrame();
476 __ ret(0); 482 __ ret(0);
477 483
478 __ bind(&interceptor_failed); 484 __ bind(&interceptor_failed);
479 __ pop(name_); 485 __ pop(name_);
480 __ pop(holder); 486 __ pop(holder);
481 if (lookup->type() == CALLBACKS) { 487 if (lookup->type() == CALLBACKS) {
482 __ pop(receiver); 488 __ pop(receiver);
483 } 489 }
484 490
485 __ LeaveInternalFrame(); 491 __ LeaveInternalFrame();
486 492
487 if (lookup->type() == FIELD) { 493 if (lookup->type() == FIELD) {
488 holder = stub_compiler->CheckPrototypes(holder_obj, 494 // We found FIELD property in prototype chain of interceptor's holder.
495 // Check that the maps from interceptor's holder to field's holder
496 // haven't changed...
497 holder = stub_compiler->CheckPrototypes(interceptor_holder,
489 holder, 498 holder,
490 lookup->holder(), 499 lookup->holder(),
491 scratch1, 500 scratch1,
492 scratch2, 501 scratch2,
493 name, 502 name,
494 miss_label); 503 miss_label);
504 // ... and retrieve a field from field's holder.
495 stub_compiler->GenerateFastPropertyLoad(masm, 505 stub_compiler->GenerateFastPropertyLoad(masm,
496 rax, 506 rax,
497 holder, 507 holder,
498 lookup->holder(), 508 lookup->holder(),
499 lookup->GetFieldIndex()); 509 lookup->GetFieldIndex());
500 __ ret(0); 510 __ ret(0);
501 } else { 511 } else {
512 // We found CALLBACKS property in prototype chain of interceptor's
513 // holder.
502 ASSERT(lookup->type() == CALLBACKS); 514 ASSERT(lookup->type() == CALLBACKS);
503 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); 515 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
504 ASSERT(callback != NULL); 516 ASSERT(callback != NULL);
505 ASSERT(callback->getter() != NULL); 517 ASSERT(callback->getter() != NULL);
506 518
519 // Prepare for tail call. Push receiver to stack after return address.
507 Label cleanup; 520 Label cleanup;
508 __ pop(scratch2); 521 __ pop(scratch2); // return address
509 __ push(receiver); 522 __ push(receiver);
510 __ push(scratch2); 523 __ push(scratch2);
511 524
512 holder = stub_compiler->CheckPrototypes(holder_obj, holder, 525 // Check that the maps from interceptor's holder to callback's holder
526 // haven't changed.
527 holder = stub_compiler->CheckPrototypes(interceptor_holder, holder,
513 lookup->holder(), scratch1, 528 lookup->holder(), scratch1,
514 scratch2, 529 scratch2,
515 name, 530 name,
516 &cleanup); 531 &cleanup);
517 532
518 __ pop(scratch2); // save old return address 533 // Continue tail call preparation: push remaining parameters after
534 // return address.
535 __ pop(scratch2); // return address
519 __ push(holder); 536 __ push(holder);
520 __ Move(holder, Handle<AccessorInfo>(callback)); 537 __ Move(holder, Handle<AccessorInfo>(callback));
521 __ push(holder); 538 __ push(holder);
522 __ push(FieldOperand(holder, AccessorInfo::kDataOffset)); 539 __ push(FieldOperand(holder, AccessorInfo::kDataOffset));
523 __ push(name_); 540 __ push(name_);
524 __ push(scratch2); // restore old return address 541 __ push(scratch2); // restore return address
525 542
543 // Tail call to runtime.
526 ExternalReference ref = 544 ExternalReference ref =
527 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); 545 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
528 __ TailCallExternalReference(ref, 5, 1); 546 __ TailCallExternalReference(ref, 5, 1);
529 547
548 // Clean up code: we pushed receiver after return address and
549 // need to remove it from there.
530 __ bind(&cleanup); 550 __ bind(&cleanup);
531 __ pop(scratch1); 551 __ pop(scratch1); // return address
532 __ pop(scratch2); 552 __ pop(scratch2); // receiver
533 __ push(scratch1); 553 __ push(scratch1);
534 } 554 }
535 } 555 }
536 556
537 557
538 void CompileRegular(MacroAssembler* masm, 558 void CompileRegular(MacroAssembler* masm,
539 Register receiver, 559 Register receiver,
540 Register holder, 560 Register holder,
541 Register scratch, 561 Register scratch,
542 JSObject* holder_obj, 562 JSObject* interceptor_holder,
543 Label* miss_label) { 563 Label* miss_label) {
544 __ pop(scratch); // save old return address 564 __ pop(scratch); // save old return address
545 PushInterceptorArguments(masm, receiver, holder, name_, holder_obj); 565 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
546 __ push(scratch); // restore old return address 566 __ push(scratch); // restore old return address
547 567
548 ExternalReference ref = ExternalReference( 568 ExternalReference ref = ExternalReference(
549 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); 569 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
550 __ TailCallExternalReference(ref, 5, 1); 570 __ TailCallExternalReference(ref, 5, 1);
551 } 571 }
552 572
553 private: 573 private:
554 Register name_; 574 Register name_;
555 }; 575 };
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
697 miss); 717 miss);
698 } 718 }
699 } 719 }
700 720
701 private: 721 private:
702 void CompileCacheable(MacroAssembler* masm, 722 void CompileCacheable(MacroAssembler* masm,
703 JSObject* object, 723 JSObject* object,
704 Register receiver, 724 Register receiver,
705 Register scratch1, 725 Register scratch1,
706 Register scratch2, 726 Register scratch2,
707 JSObject* holder_obj, 727 JSObject* interceptor_holder,
708 LookupResult* lookup, 728 LookupResult* lookup,
709 String* name, 729 String* name,
710 const CallOptimization& optimization, 730 const CallOptimization& optimization,
711 Label* miss_label) { 731 Label* miss_label) {
712 ASSERT(optimization.is_constant_call()); 732 ASSERT(optimization.is_constant_call());
713 ASSERT(!lookup->holder()->IsGlobalObject()); 733 ASSERT(!lookup->holder()->IsGlobalObject());
714 734
715 int depth1 = kInvalidProtoDepth; 735 int depth1 = kInvalidProtoDepth;
716 int depth2 = kInvalidProtoDepth; 736 int depth2 = kInvalidProtoDepth;
717 bool can_do_fast_api_call = false; 737 bool can_do_fast_api_call = false;
718 if (optimization.is_simple_api_call() && 738 if (optimization.is_simple_api_call() &&
719 !lookup->holder()->IsGlobalObject()) { 739 !lookup->holder()->IsGlobalObject()) {
720 depth1 = optimization.GetPrototypeDepthOfExpectedType(object, holder_obj); 740 depth1 =
741 optimization.GetPrototypeDepthOfExpectedType(object,
742 interceptor_holder);
721 if (depth1 == kInvalidProtoDepth) { 743 if (depth1 == kInvalidProtoDepth) {
722 depth2 = optimization.GetPrototypeDepthOfExpectedType(holder_obj, 744 depth2 =
723 lookup->holder()); 745 optimization.GetPrototypeDepthOfExpectedType(interceptor_holder,
746 lookup->holder());
724 } 747 }
725 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || 748 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) ||
726 (depth2 != kInvalidProtoDepth); 749 (depth2 != kInvalidProtoDepth);
727 } 750 }
728 751
729 __ IncrementCounter(&Counters::call_const_interceptor, 1); 752 __ IncrementCounter(&Counters::call_const_interceptor, 1);
730 753
731 if (can_do_fast_api_call) { 754 if (can_do_fast_api_call) {
732 __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1); 755 __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1);
733 ReserveSpaceForFastApiCall(masm, scratch1); 756 ReserveSpaceForFastApiCall(masm, scratch1);
734 } 757 }
735 758
759 // Check that the maps from receiver to interceptor's holder
760 // haven't changed and thus we can invoke interceptor.
736 Label miss_cleanup; 761 Label miss_cleanup;
737 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; 762 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
738 Register holder = 763 Register holder =
739 stub_compiler_->CheckPrototypes(object, receiver, holder_obj, 764 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
740 scratch1, scratch2, name, 765 scratch1, scratch2, name,
741 depth1, miss); 766 depth1, miss);
742 767
768 // Invoke an interceptor and if it provides a value,
769 // branch to |regular_invoke|.
743 Label regular_invoke; 770 Label regular_invoke;
744 LoadWithInterceptor(masm, receiver, holder, holder_obj, &regular_invoke); 771 LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
772 &regular_invoke);
745 773
746 // Generate code for the failed interceptor case. 774 // Interceptor returned nothing for this property. Try to use cached
775 // constant function.
747 776
748 // Check the lookup is still valid. 777 // Check that the maps from interceptor's holder to constant function's
749 stub_compiler_->CheckPrototypes(holder_obj, receiver, 778 // holder haven't changed and thus we can use cached constant function.
779 stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
750 lookup->holder(), 780 lookup->holder(),
751 scratch1, scratch2, name, 781 scratch1, scratch2, name,
752 depth2, miss); 782 depth2, miss);
753 783
784 // Invoke function.
754 if (can_do_fast_api_call) { 785 if (can_do_fast_api_call) {
755 GenerateFastApiCall(masm, optimization, arguments_.immediate()); 786 GenerateFastApiCall(masm, optimization, arguments_.immediate());
756 } else { 787 } else {
757 __ InvokeFunction(optimization.constant_function(), arguments_, 788 __ InvokeFunction(optimization.constant_function(), arguments_,
758 JUMP_FUNCTION); 789 JUMP_FUNCTION);
759 } 790 }
760 791
792 // Deferred code for fast API call case---clean preallocated space.
761 if (can_do_fast_api_call) { 793 if (can_do_fast_api_call) {
762 __ bind(&miss_cleanup); 794 __ bind(&miss_cleanup);
763 FreeSpaceForFastApiCall(masm, scratch1); 795 FreeSpaceForFastApiCall(masm, scratch1);
764 __ jmp(miss_label); 796 __ jmp(miss_label);
765 } 797 }
766 798
799 // Invoke a regular function.
767 __ bind(&regular_invoke); 800 __ bind(&regular_invoke);
768 if (can_do_fast_api_call) { 801 if (can_do_fast_api_call) {
769 FreeSpaceForFastApiCall(masm, scratch1); 802 FreeSpaceForFastApiCall(masm, scratch1);
770 } 803 }
771 } 804 }
772 805
773 void CompileRegular(MacroAssembler* masm, 806 void CompileRegular(MacroAssembler* masm,
774 JSObject* object, 807 JSObject* object,
775 Register receiver, 808 Register receiver,
776 Register scratch1, 809 Register scratch1,
777 Register scratch2, 810 Register scratch2,
778 String* name, 811 String* name,
779 JSObject* holder_obj, 812 JSObject* interceptor_holder,
780 Label* miss_label) { 813 Label* miss_label) {
781 Register holder = 814 Register holder =
782 stub_compiler_->CheckPrototypes(object, receiver, holder_obj, 815 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
783 scratch1, scratch2, name, 816 scratch1, scratch2, name,
784 miss_label); 817 miss_label);
785 818
786 __ EnterInternalFrame(); 819 __ EnterInternalFrame();
787 // Save the name_ register across the call. 820 // Save the name_ register across the call.
788 __ push(name_); 821 __ push(name_);
789 822
790 PushInterceptorArguments(masm, 823 PushInterceptorArguments(masm,
791 receiver, 824 receiver,
792 holder, 825 holder,
793 name_, 826 name_,
794 holder_obj); 827 interceptor_holder);
795 828
796 __ CallExternalReference( 829 __ CallExternalReference(
797 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall)), 830 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
798 5); 831 5);
799 832
800 // Restore the name_ register. 833 // Restore the name_ register.
801 __ pop(name_); 834 __ pop(name_);
802 __ LeaveInternalFrame(); 835 __ LeaveInternalFrame();
803 } 836 }
804 837
(...skipping 1554 matching lines...) Expand 10 before | Expand all | Expand 10 after
2359 // Return the generated code. 2392 // Return the generated code.
2360 return GetCode(); 2393 return GetCode();
2361 } 2394 }
2362 2395
2363 2396
2364 #undef __ 2397 #undef __
2365 2398
2366 } } // namespace v8::internal 2399 } } // namespace v8::internal
2367 2400
2368 #endif // V8_TARGET_ARCH_X64 2401 #endif // V8_TARGET_ARCH_X64
OLDNEW
« src/arm/stub-cache-arm.cc ('K') | « src/ia32/stub-cache-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698