OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |