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

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

Issue 604054: Simplify compilation of CallIC interceptor stub. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | 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 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 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 401 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
402 402
403 // Jump to the cached code (tail call). 403 // Jump to the cached code (tail call).
404 Handle<Code> code(function->code()); 404 Handle<Code> code(function->code());
405 ParameterCount expected(function->shared()->formal_parameter_count()); 405 ParameterCount expected(function->shared()->formal_parameter_count());
406 __ InvokeCode(code, expected, arguments, 406 __ InvokeCode(code, expected, arguments,
407 RelocInfo::CODE_TARGET, JUMP_FUNCTION); 407 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
408 } 408 }
409 409
410 410
411 template <class Compiler>
412 static void CompileLoadInterceptor(Compiler* compiler,
413 StubCompiler* stub_compiler,
414 MacroAssembler* masm,
415 JSObject* object,
416 JSObject* holder,
417 String* name,
418 LookupResult* lookup,
419 Register receiver,
420 Register scratch1,
421 Register scratch2,
422 Label* miss) {
423 ASSERT(holder->HasNamedInterceptor());
424 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
425
426 // Check that the receiver isn't a smi.
427 __ BranchOnSmi(receiver, miss);
428
429 // Check that the maps haven't changed.
430 Register reg =
431 stub_compiler->CheckPrototypes(object, receiver, holder,
432 scratch1, scratch2, name, miss);
433
434 if (lookup->IsValid() && lookup->IsCacheable()) {
435 compiler->CompileCacheable(masm,
436 stub_compiler,
437 receiver,
438 reg,
439 scratch1,
440 scratch2,
441 holder,
442 lookup,
443 name,
444 miss);
445 } else {
446 compiler->CompileRegular(masm,
447 receiver,
448 reg,
449 scratch2,
450 holder,
451 miss);
452 }
453 }
454
455
456 static void PushInterceptorArguments(MacroAssembler* masm, 411 static void PushInterceptorArguments(MacroAssembler* masm,
457 Register receiver, 412 Register receiver,
458 Register holder, 413 Register holder,
459 Register name, 414 Register name,
460 JSObject* holder_obj) { 415 JSObject* holder_obj) {
461 __ push(receiver); 416 __ push(receiver);
462 __ push(holder); 417 __ push(holder);
463 __ push(name); 418 __ push(name);
464 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); 419 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
465 ASSERT(!Heap::InNewSpace(interceptor)); 420 ASSERT(!Heap::InNewSpace(interceptor));
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 ExternalReference ref = ExternalReference( 567 ExternalReference ref = ExternalReference(
613 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); 568 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
614 __ TailCallRuntime(ref, 5, 1); 569 __ TailCallRuntime(ref, 5, 1);
615 } 570 }
616 571
617 private: 572 private:
618 Register name_; 573 Register name_;
619 }; 574 };
620 575
621 576
622 class CallInterceptorCompiler BASE_EMBEDDED { 577 static void CompileLoadInterceptor(LoadInterceptorCompiler* compiler,
623 public: 578 StubCompiler* stub_compiler,
624 CallInterceptorCompiler(const ParameterCount& arguments, Register name) 579 MacroAssembler* masm,
625 : arguments_(arguments), argc_(arguments.immediate()), name_(name) {} 580 JSObject* object,
581 JSObject* holder,
582 String* name,
583 LookupResult* lookup,
584 Register receiver,
585 Register scratch1,
586 Register scratch2,
587 Label* miss) {
588 ASSERT(holder->HasNamedInterceptor());
589 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
626 590
627 void CompileCacheable(MacroAssembler* masm, 591 // Check that the receiver isn't a smi.
628 StubCompiler* stub_compiler, 592 __ BranchOnSmi(receiver, miss);
629 Register receiver,
630 Register holder,
631 Register scratch1,
632 Register scratch2,
633 JSObject* holder_obj,
634 LookupResult* lookup,
635 String* name,
636 Label* miss_label) {
637 JSFunction* function = 0;
638 bool optimize = false;
639 // So far the most popular case for failed interceptor is
640 // CONSTANT_FUNCTION sitting below.
641 if (lookup->type() == CONSTANT_FUNCTION) {
642 function = lookup->GetConstantFunction();
643 // JSArray holder is a special case for call constant function
644 // (see the corresponding code).
645 if (function->is_compiled() && !holder_obj->IsJSArray()) {
646 optimize = true;
647 }
648 }
649 593
650 if (!optimize) { 594 // Check that the maps haven't changed.
651 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); 595 Register reg =
652 return; 596 stub_compiler->CheckPrototypes(object, receiver, holder,
653 } 597 scratch1, scratch2, name, miss);
654 598
655 // Constant functions cannot sit on global object. 599 if (lookup->IsValid() && lookup->IsCacheable()) {
656 ASSERT(!lookup->holder()->IsGlobalObject()); 600 compiler->CompileCacheable(masm,
657 601 stub_compiler,
658 __ EnterInternalFrame(); 602 receiver,
659 __ push(holder); // Save the holder. 603 reg,
660 __ push(name_); // Save the name. 604 scratch1,
661 605 scratch2,
662 CompileCallLoadPropertyWithInterceptor(masm, 606 holder,
663 receiver, 607 lookup,
664 holder, 608 name,
665 name_, 609 miss);
666 holder_obj); 610 } else {
667 611 compiler->CompileRegular(masm,
668 ASSERT(!r0.is(name_)); 612 receiver,
669 ASSERT(!r0.is(scratch1)); 613 reg,
670 __ pop(name_); // Restore the name. 614 scratch2,
671 __ pop(scratch1); // Restore the holder. 615 holder,
672 __ LeaveInternalFrame(); 616 miss);
673
674 // Compare with no_interceptor_result_sentinel.
675 __ LoadRoot(scratch2, Heap::kNoInterceptorResultSentinelRootIndex);
676 __ cmp(r0, scratch2);
677 Label invoke;
678 __ b(ne, &invoke);
679
680 stub_compiler->CheckPrototypes(holder_obj, scratch1,
681 lookup->holder(), scratch1,
682 scratch2,
683 name,
684 miss_label);
685 GenerateCallConstFunction(masm, function, arguments_);
686
687 __ bind(&invoke);
688 } 617 }
689 618 }
690 void CompileRegular(MacroAssembler* masm,
691 Register receiver,
692 Register holder,
693 Register scratch,
694 JSObject* holder_obj,
695 Label* miss_label) {
696 __ EnterInternalFrame();
697 // Save the name_ register across the call.
698 __ push(name_);
699
700 PushInterceptorArguments(masm,
701 receiver,
702 holder,
703 name_,
704 holder_obj);
705
706 ExternalReference ref = ExternalReference(
707 IC_Utility(IC::kLoadPropertyWithInterceptorForCall));
708 __ mov(r0, Operand(5));
709 __ mov(r1, Operand(ref));
710
711 CEntryStub stub(1);
712 __ CallStub(&stub);
713
714 // Restore the name_ register.
715 __ pop(name_);
716 __ LeaveInternalFrame();
717 }
718
719 private:
720 const ParameterCount& arguments_;
721 int argc_;
722 Register name_;
723 };
724 619
725 620
726 #undef __ 621 #undef __
727 #define __ ACCESS_MASM(masm()) 622 #define __ ACCESS_MASM(masm())
728 623
729 624
730 Register StubCompiler::CheckPrototypes(JSObject* object, 625 Register StubCompiler::CheckPrototypes(JSObject* object,
731 Register object_reg, 626 Register object_reg,
732 JSObject* holder, 627 JSObject* holder,
733 Register holder_reg, 628 Register holder_reg,
(...skipping 23 matching lines...) Expand all
757 __ mov(scratch, Operand(Handle<Object>(cell))); 652 __ mov(scratch, Operand(Handle<Object>(cell)));
758 __ ldr(scratch, 653 __ ldr(scratch,
759 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); 654 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
760 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 655 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
761 __ cmp(scratch, ip); 656 __ cmp(scratch, ip);
762 __ b(ne, miss); 657 __ b(ne, miss);
763 } 658 }
764 object = JSObject::cast(object->GetPrototype()); 659 object = JSObject::cast(object->GetPrototype());
765 } 660 }
766 661
767 // Return the register containin the holder. 662 // Return the register containing the holder.
768 return result; 663 return result;
769 } 664 }
770 665
771 666
772 void StubCompiler::GenerateLoadField(JSObject* object, 667 void StubCompiler::GenerateLoadField(JSObject* object,
773 JSObject* holder, 668 JSObject* holder,
774 Register receiver, 669 Register receiver,
775 Register scratch1, 670 Register scratch1,
776 Register scratch2, 671 Register scratch2,
777 int index, 672 int index,
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
1068 return GetCode(CONSTANT_FUNCTION, function_name); 963 return GetCode(CONSTANT_FUNCTION, function_name);
1069 } 964 }
1070 965
1071 966
1072 Object* CallStubCompiler::CompileCallInterceptor(Object* object, 967 Object* CallStubCompiler::CompileCallInterceptor(Object* object,
1073 JSObject* holder, 968 JSObject* holder,
1074 String* name) { 969 String* name) {
1075 // ----------- S t a t e ------------- 970 // ----------- S t a t e -------------
1076 // -- lr: return address 971 // -- lr: return address
1077 // ----------------------------------- 972 // -----------------------------------
973 ASSERT(holder->HasNamedInterceptor());
974 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
1078 Label miss; 975 Label miss;
1079 976
977 const Register receiver = r0;
978 const Register name_reg = r1;
979 const Register holder_reg = r2;
980 const Register scratch = r3;
981
1080 // Get the number of arguments. 982 // Get the number of arguments.
1081 const int argc = arguments().immediate(); 983 const int argc = arguments().immediate();
1082 984
1083 LookupResult lookup; 985 LookupResult lookup;
1084 LookupPostInterceptor(holder, name, &lookup); 986 LookupPostInterceptor(holder, name, &lookup);
1085 987
1086 // Get the receiver from the stack into r0. 988 // Load the receiver from the stack.
1087 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 989 __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
1088 // Load the name from the stack into r1. 990 // Load the name from the stack.
1089 __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize)); 991 __ ldr(name_reg, MemOperand(sp, (argc + 1) * kPointerSize));
1090 992
1091 CallInterceptorCompiler compiler(arguments(), r1); 993 // Check that the receiver isn't a smi.
1092 CompileLoadInterceptor(&compiler, 994 __ BranchOnSmi(receiver, &miss);
1093 this, 995
1094 masm(), 996 // Check that the maps haven't changed.
1095 JSObject::cast(object), 997 Register reg =
1096 holder, 998 CheckPrototypes(JSObject::cast(object), receiver, holder,
1097 name, 999 holder_reg, scratch, name, &miss);
1098 &lookup, 1000 if (!reg.is(holder_reg)) {
1099 r0, 1001 __ mov(holder_reg, reg);
1100 r2, 1002 }
1101 r3, 1003
1102 &miss); 1004 // If we call a constant function when the interceptor returns
1005 // the no-result sentinel, generate code that optimizes this case.
1006 if (lookup.IsValid() &&
1007 lookup.IsCacheable() &&
1008 lookup.type() == CONSTANT_FUNCTION &&
1009 lookup.GetConstantFunction()->is_compiled() &&
1010 !holder->IsJSArray()) {
1011 // Constant functions cannot sit on global object.
1012 ASSERT(!lookup.holder()->IsGlobalObject());
1013
1014 // Call the interceptor.
1015 __ EnterInternalFrame();
1016 __ push(holder_reg);
1017 __ push(name_reg);
1018 CompileCallLoadPropertyWithInterceptor(masm(),
1019 receiver,
1020 holder_reg,
1021 name_reg,
1022 holder);
1023 __ pop(name_reg);
1024 __ pop(holder_reg);
1025 __ LeaveInternalFrame();
1026 // r0 no longer contains the receiver.
1027
1028 // If interceptor returns no-result sentinal, call the constant function.
1029 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
1030 __ cmp(r0, scratch);
1031 Label invoke;
1032 __ b(ne, &invoke);
1033 // Check the prototypes between the interceptor's holder and the
1034 // constant function's holder.
1035 CheckPrototypes(holder, holder_reg,
1036 lookup.holder(), r0,
1037 scratch,
1038 name,
1039 &miss);
1040 GenerateCallConstFunction(masm(),
1041 lookup.GetConstantFunction(),
1042 arguments());
1043 __ bind(&invoke);
1044
1045 } else {
1046 // Call a runtime function to load the interceptor property.
1047 __ EnterInternalFrame();
1048 __ push(name_reg);
1049
1050 PushInterceptorArguments(masm(), receiver, holder_reg, name_reg, holder);
1051
1052 ExternalReference ref = ExternalReference(
1053 IC_Utility(IC::kLoadPropertyWithInterceptorForCall));
1054 __ mov(r0, Operand(5));
1055 __ mov(r1, Operand(ref));
1056
1057 CEntryStub stub(1);
1058 __ CallStub(&stub);
1059
1060 __ pop(name_reg);
1061 __ LeaveInternalFrame();
1062 }
1063
1103 1064
1104 // Move returned value, the function to call, to r1. 1065 // Move returned value, the function to call, to r1.
1066 // Neither receiver nor name contain their original value at this point.
1105 __ mov(r1, r0); 1067 __ mov(r1, r0);
1106 // Restore receiver. 1068 // Restore receiver.
1107 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 1069 __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
1108 1070
1109 GenerateCallFunction(masm(), object, arguments(), &miss); 1071 GenerateCallFunction(masm(), object, arguments(), &miss);
1110 1072
1111 // Handle call cache miss. 1073 // Handle call cache miss.
1112 __ bind(&miss); 1074 __ bind(&miss);
1113 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); 1075 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
1114 __ Jump(ic, RelocInfo::CODE_TARGET); 1076 __ Jump(ic, RelocInfo::CODE_TARGET);
1115 1077
1116 // Return the generated code. 1078 // Return the generated code.
1117 return GetCode(INTERCEPTOR, name); 1079 return GetCode(INTERCEPTOR, name);
(...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after
1860 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); 1822 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
1861 1823
1862 // Return the generated code. 1824 // Return the generated code.
1863 return GetCode(); 1825 return GetCode();
1864 } 1826 }
1865 1827
1866 1828
1867 #undef __ 1829 #undef __
1868 1830
1869 } } // namespace v8::internal 1831 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698