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

Side by Side Diff: src/arm/stub-cache-arm.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
« no previous file with comments | « no previous file | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 418 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 class LoadInterceptorCompiler BASE_EMBEDDED { 429 class LoadInterceptorCompiler BASE_EMBEDDED {
430 public: 430 public:
431 explicit LoadInterceptorCompiler(Register name) : name_(name) {} 431 explicit LoadInterceptorCompiler(Register name) : name_(name) {}
432 432
433 void CompileCacheable(MacroAssembler* masm, 433 void CompileCacheable(MacroAssembler* masm,
434 StubCompiler* stub_compiler, 434 StubCompiler* stub_compiler,
435 Register receiver, 435 Register receiver,
436 Register holder, 436 Register holder,
437 Register scratch1, 437 Register scratch1,
438 Register scratch2, 438 Register scratch2,
439 JSObject* holder_obj, 439 JSObject* interceptor_holder,
440 LookupResult* lookup, 440 LookupResult* lookup,
441 String* name, 441 String* name,
442 Label* miss_label) { 442 Label* miss_label) {
443 AccessorInfo* callback = NULL; 443 AccessorInfo* callback = NULL;
444 bool optimize = false; 444 bool optimize = false;
445 // So far the most popular follow ups for interceptor loads are FIELD 445 // So far the most popular follow ups for interceptor loads are FIELD
446 // and CALLBACKS, so inline only them, other cases may be added 446 // and CALLBACKS, so inline only them, other cases may be added
447 // later. 447 // later.
448 if (lookup->type() == FIELD) { 448 if (lookup->type() == FIELD) {
449 optimize = true; 449 optimize = true;
450 } else if (lookup->type() == CALLBACKS) { 450 } else if (lookup->type() == CALLBACKS) {
451 Object* callback_object = lookup->GetCallbackObject(); 451 Object* callback_object = lookup->GetCallbackObject();
452 if (callback_object->IsAccessorInfo()) { 452 if (callback_object->IsAccessorInfo()) {
453 callback = AccessorInfo::cast(callback_object); 453 callback = AccessorInfo::cast(callback_object);
454 optimize = callback->getter() != NULL; 454 optimize = callback->getter() != NULL;
455 } 455 }
456 } 456 }
457 457
458 if (!optimize) { 458 if (!optimize) {
459 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); 459 CompileRegular(masm, receiver, holder, scratch2, interceptor_holder,
460 miss_label);
460 return; 461 return;
461 } 462 }
462 463
463 // Note: starting a frame here makes GC aware of pointers pushed below. 464 // Note: starting a frame here makes GC aware of pointers pushed below.
464 __ EnterInternalFrame(); 465 __ EnterInternalFrame();
465 466
466 __ push(receiver); 467 __ push(receiver);
467 __ Push(holder, name_); 468 __ Push(holder, name_);
468 469
470 // Invoke an interceptor. Note: map checks from receiver to
471 // interceptor's holder has been compiled before (see a caller
472 // of this method.)
469 CompileCallLoadPropertyWithInterceptor(masm, 473 CompileCallLoadPropertyWithInterceptor(masm,
470 receiver, 474 receiver,
471 holder, 475 holder,
472 name_, 476 name_,
473 holder_obj); 477 interceptor_holder);
474 478
479 // Check if interceptor provided a value for property. If it's
480 // the case, return immediately.
475 Label interceptor_failed; 481 Label interceptor_failed;
476 // Compare with no_interceptor_result_sentinel.
477 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); 482 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex);
478 __ cmp(r0, scratch1); 483 __ cmp(r0, scratch1);
479 __ b(eq, &interceptor_failed); 484 __ b(eq, &interceptor_failed);
480 __ LeaveInternalFrame(); 485 __ LeaveInternalFrame();
481 __ Ret(); 486 __ Ret();
482 487
483 __ bind(&interceptor_failed); 488 __ bind(&interceptor_failed);
484 __ pop(name_); 489 __ pop(name_);
485 __ pop(holder); 490 __ pop(holder);
486 __ pop(receiver); 491 __ pop(receiver);
487 492
488 __ LeaveInternalFrame(); 493 __ LeaveInternalFrame();
489 494
490 if (lookup->type() == FIELD) { 495 if (lookup->type() == FIELD) {
491 holder = stub_compiler->CheckPrototypes(holder_obj, 496 // We found FIELD property in prototype chain of interceptor's holder.
497 // Check that the maps from interceptor's holder to field's holder
498 // haven't changed...
499 holder = stub_compiler->CheckPrototypes(interceptor_holder,
492 holder, 500 holder,
493 lookup->holder(), 501 lookup->holder(),
494 scratch1, 502 scratch1,
495 scratch2, 503 scratch2,
496 name, 504 name,
497 miss_label); 505 miss_label);
506 // ... and retrieve a field from field's holder.
498 stub_compiler->GenerateFastPropertyLoad(masm, 507 stub_compiler->GenerateFastPropertyLoad(masm,
499 r0, 508 r0,
500 holder, 509 holder,
501 lookup->holder(), 510 lookup->holder(),
502 lookup->GetFieldIndex()); 511 lookup->GetFieldIndex());
503 __ Ret(); 512 __ Ret();
504 } else { 513 } else {
514 // We found CALLBACKS property in prototype chain of interceptor's
515 // holder.
505 ASSERT(lookup->type() == CALLBACKS); 516 ASSERT(lookup->type() == CALLBACKS);
506 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); 517 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
507 ASSERT(callback != NULL); 518 ASSERT(callback != NULL);
508 ASSERT(callback->getter() != NULL); 519 ASSERT(callback->getter() != NULL);
509 520
521 // Prepare for tail call: push receiver to stack.
510 Label cleanup; 522 Label cleanup;
511 __ push(receiver); 523 __ push(receiver);
512 524
513 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,
514 lookup->holder(), scratch1, 528 lookup->holder(), scratch1,
515 scratch2, 529 scratch2,
516 name, 530 name,
517 &cleanup); 531 &cleanup);
518 532
533 // Continue tail call preparation: push remaining parameters.
519 __ push(holder); 534 __ push(holder);
520 __ Move(holder, Handle<AccessorInfo>(callback)); 535 __ Move(holder, Handle<AccessorInfo>(callback));
521 __ push(holder); 536 __ push(holder);
522 __ ldr(scratch1, FieldMemOperand(holder, AccessorInfo::kDataOffset)); 537 __ ldr(scratch1, FieldMemOperand(holder, AccessorInfo::kDataOffset));
523 __ Push(scratch1, name_); 538 __ Push(scratch1, name_);
524 539
540 // Tail call to runtime.
525 ExternalReference ref = 541 ExternalReference ref =
526 ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); 542 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
527 __ TailCallExternalReference(ref, 5, 1); 543 __ TailCallExternalReference(ref, 5, 1);
528 544
545 // Clean up code: we pushed receiver and need to remove it.
529 __ bind(&cleanup); 546 __ bind(&cleanup);
530 __ pop(scratch2); 547 __ pop(scratch2);
531 } 548 }
532 } 549 }
533 550
534 551
535 void CompileRegular(MacroAssembler* masm, 552 void CompileRegular(MacroAssembler* masm,
536 Register receiver, 553 Register receiver,
537 Register holder, 554 Register holder,
538 Register scratch, 555 Register scratch,
539 JSObject* holder_obj, 556 JSObject* interceptor_holder,
540 Label* miss_label) { 557 Label* miss_label) {
541 PushInterceptorArguments(masm, receiver, holder, name_, holder_obj); 558 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
542 559
543 ExternalReference ref = ExternalReference( 560 ExternalReference ref = ExternalReference(
544 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); 561 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
545 __ TailCallExternalReference(ref, 5, 1); 562 __ TailCallExternalReference(ref, 5, 1);
546 } 563 }
547 564
548 private: 565 private:
549 Register name_; 566 Register name_;
550 }; 567 };
551 568
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 miss); 724 miss);
708 } 725 }
709 } 726 }
710 727
711 private: 728 private:
712 void CompileCacheable(MacroAssembler* masm, 729 void CompileCacheable(MacroAssembler* masm,
713 JSObject* object, 730 JSObject* object,
714 Register receiver, 731 Register receiver,
715 Register scratch1, 732 Register scratch1,
716 Register scratch2, 733 Register scratch2,
717 JSObject* holder_obj, 734 JSObject* interceptor_holder,
718 LookupResult* lookup, 735 LookupResult* lookup,
719 String* name, 736 String* name,
720 const CallOptimization& optimization, 737 const CallOptimization& optimization,
721 Label* miss_label) { 738 Label* miss_label) {
722 ASSERT(optimization.is_constant_call()); 739 ASSERT(optimization.is_constant_call());
723 ASSERT(!lookup->holder()->IsGlobalObject()); 740 ASSERT(!lookup->holder()->IsGlobalObject());
724 741
725 int depth1 = kInvalidProtoDepth; 742 int depth1 = kInvalidProtoDepth;
726 int depth2 = kInvalidProtoDepth; 743 int depth2 = kInvalidProtoDepth;
727 bool can_do_fast_api_call = false; 744 bool can_do_fast_api_call = false;
728 if (optimization.is_simple_api_call() && 745 if (optimization.is_simple_api_call() &&
729 !lookup->holder()->IsGlobalObject()) { 746 !lookup->holder()->IsGlobalObject()) {
730 depth1 = optimization.GetPrototypeDepthOfExpectedType(object, holder_obj); 747 depth1 =
748 optimization.GetPrototypeDepthOfExpectedType(object,
749 interceptor_holder);
731 if (depth1 == kInvalidProtoDepth) { 750 if (depth1 == kInvalidProtoDepth) {
732 depth2 = optimization.GetPrototypeDepthOfExpectedType(holder_obj, 751 depth2 =
733 lookup->holder()); 752 optimization.GetPrototypeDepthOfExpectedType(interceptor_holder,
753 lookup->holder());
734 } 754 }
735 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || 755 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) ||
736 (depth2 != kInvalidProtoDepth); 756 (depth2 != kInvalidProtoDepth);
737 } 757 }
738 758
739 __ IncrementCounter(&Counters::call_const_interceptor, 1, 759 __ IncrementCounter(&Counters::call_const_interceptor, 1,
740 scratch1, scratch2); 760 scratch1, scratch2);
741 761
742 if (can_do_fast_api_call) { 762 if (can_do_fast_api_call) {
743 __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1, 763 __ IncrementCounter(&Counters::call_const_interceptor_fast_api, 1,
744 scratch1, scratch2); 764 scratch1, scratch2);
745 ReserveSpaceForFastApiCall(masm, scratch1); 765 ReserveSpaceForFastApiCall(masm, scratch1);
746 } 766 }
747 767
768 // Check that the maps from receiver to interceptor's holder
769 // haven't changed and thus we can invoke interceptor.
748 Label miss_cleanup; 770 Label miss_cleanup;
749 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; 771 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
750 Register holder = 772 Register holder =
751 stub_compiler_->CheckPrototypes(object, receiver, holder_obj, scratch1, 773 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
752 scratch2, name, depth1, miss); 774 scratch1, scratch2, name,
775 depth1, miss);
753 776
777 // Invoke an interceptor and if it provides a value,
778 // branch to |regular_invoke|.
754 Label regular_invoke; 779 Label regular_invoke;
755 LoadWithInterceptor(masm, receiver, holder, holder_obj, scratch2, 780 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2,
756 &regular_invoke); 781 &regular_invoke);
757 782
758 // Generate code for the failed interceptor case. 783 // Interceptor returned nothing for this property. Try to use cached
784 // constant function.
759 785
760 // Check the lookup is still valid. 786 // Check that the maps from interceptor's holder to constant function's
761 stub_compiler_->CheckPrototypes(holder_obj, receiver, 787 // holder haven't changed and thus we can use cached constant function.
Søren Thygesen Gjesse 2010/05/25 14:07:29 I am wondering whether this check can be skipped i
antonm 2010/05/25 14:15:10 That's a good point and it indeed could happen. L
788 stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
762 lookup->holder(), scratch1, 789 lookup->holder(), scratch1,
763 scratch2, name, depth2, miss); 790 scratch2, name, depth2, miss);
764 791
792 // Invoke function.
765 if (can_do_fast_api_call) { 793 if (can_do_fast_api_call) {
766 GenerateFastApiCall(masm, optimization, arguments_.immediate()); 794 GenerateFastApiCall(masm, optimization, arguments_.immediate());
767 } else { 795 } else {
768 __ InvokeFunction(optimization.constant_function(), arguments_, 796 __ InvokeFunction(optimization.constant_function(), arguments_,
769 JUMP_FUNCTION); 797 JUMP_FUNCTION);
770 } 798 }
771 799
800 // Deferred code for fast API call case---clean preallocated space.
772 if (can_do_fast_api_call) { 801 if (can_do_fast_api_call) {
773 __ bind(&miss_cleanup); 802 __ bind(&miss_cleanup);
774 FreeSpaceForFastApiCall(masm); 803 FreeSpaceForFastApiCall(masm);
775 __ b(miss_label); 804 __ b(miss_label);
776 } 805 }
777 806
807 // Invoke a regular function.
778 __ bind(&regular_invoke); 808 __ bind(&regular_invoke);
779 if (can_do_fast_api_call) { 809 if (can_do_fast_api_call) {
780 FreeSpaceForFastApiCall(masm); 810 FreeSpaceForFastApiCall(masm);
781 } 811 }
782 } 812 }
783 813
784 void CompileRegular(MacroAssembler* masm, 814 void CompileRegular(MacroAssembler* masm,
785 JSObject* object, 815 JSObject* object,
786 Register receiver, 816 Register receiver,
787 Register scratch1, 817 Register scratch1,
788 Register scratch2, 818 Register scratch2,
789 String* name, 819 String* name,
790 JSObject* holder_obj, 820 JSObject* interceptor_holder,
791 Label* miss_label) { 821 Label* miss_label) {
792 Register holder = 822 Register holder =
793 stub_compiler_->CheckPrototypes(object, receiver, holder_obj, 823 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
794 scratch1, scratch2, name, 824 scratch1, scratch2, name,
795 miss_label); 825 miss_label);
796 826
797 // Call a runtime function to load the interceptor property. 827 // Call a runtime function to load the interceptor property.
798 __ EnterInternalFrame(); 828 __ EnterInternalFrame();
799 // Save the name_ register across the call. 829 // Save the name_ register across the call.
800 __ push(name_); 830 __ push(name_);
801 831
802 PushInterceptorArguments(masm, 832 PushInterceptorArguments(masm,
803 receiver, 833 receiver,
804 holder, 834 holder,
805 name_, 835 name_,
806 holder_obj); 836 interceptor_holder);
807 837
808 __ CallExternalReference( 838 __ CallExternalReference(
809 ExternalReference( 839 ExternalReference(
810 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)), 840 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)),
811 5); 841 5);
812 842
813 // Restore the name_ register. 843 // Restore the name_ register.
814 __ pop(name_); 844 __ pop(name_);
815 __ LeaveInternalFrame(); 845 __ LeaveInternalFrame();
816 } 846 }
(...skipping 1317 matching lines...) Expand 10 before | Expand all | Expand 10 after
2134 // Return the generated code. 2164 // Return the generated code.
2135 return GetCode(); 2165 return GetCode();
2136 } 2166 }
2137 2167
2138 2168
2139 #undef __ 2169 #undef __
2140 2170
2141 } } // namespace v8::internal 2171 } } // namespace v8::internal
2142 2172
2143 #endif // V8_TARGET_ARCH_ARM 2173 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698