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 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
564 | 564 |
565 ExternalReference ref = | 565 ExternalReference ref = |
566 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); | 566 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); |
567 __ mov(r0, Operand(5)); | 567 __ mov(r0, Operand(5)); |
568 __ mov(r1, Operand(ref)); | 568 __ mov(r1, Operand(ref)); |
569 | 569 |
570 CEntryStub stub(1); | 570 CEntryStub stub(1); |
571 __ CallStub(&stub); | 571 __ CallStub(&stub); |
572 } | 572 } |
573 | 573 |
574 static const int kFastApiCallArguments = 3; | |
574 | 575 |
575 // Reserves space for the extra arguments to FastHandleApiCall in the | 576 // Reserves space for the extra arguments to FastHandleApiCall in the |
576 // caller's frame. | 577 // caller's frame. |
577 // | 578 // |
578 // These arguments are set by CheckPrototypes and GenerateFastApiCall. | 579 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. |
579 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, | 580 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, |
580 Register scratch) { | 581 Register scratch) { |
581 __ mov(scratch, Operand(Smi::FromInt(0))); | 582 __ mov(scratch, Operand(Smi::FromInt(0))); |
582 __ push(scratch); | 583 for (int i = 0; i < kFastApiCallArguments; i++) { |
583 __ push(scratch); | 584 __ push(scratch); |
584 __ push(scratch); | 585 } |
585 __ push(scratch); | |
586 } | 586 } |
587 | 587 |
588 | 588 |
589 // Undoes the effects of ReserveSpaceForFastApiCall. | 589 // Undoes the effects of ReserveSpaceForFastApiCall. |
590 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { | 590 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { |
591 __ Drop(4); | 591 __ Drop(kFastApiCallArguments); |
592 } | 592 } |
593 | 593 |
594 | 594 |
595 // Generates call to FastHandleApiCall builtin. | 595 static MaybeObject* GenerateFastApiDirectCall(MacroAssembler* masm, |
596 static void GenerateFastApiCall(MacroAssembler* masm, | 596 const CallOptimization& optimization, |
597 const CallOptimization& optimization, | 597 int argc) { |
598 int argc) { | 598 // ----------- S t a t e ------------- |
599 // -- sp[0] : holder (set by CheckPrototypes) | |
600 // -- sp[4] : callee js function | |
601 // -- sp[8] : call data | |
602 // -- sp[12] : last js argument | |
603 // -- ... | |
604 // -- sp[(argc + 3) * 4] : first js argument | |
605 // -- sp[(argc + 4) * 4] : receiver | |
606 // ----------------------------------- | |
599 // Get the function and setup the context. | 607 // Get the function and setup the context. |
600 JSFunction* function = optimization.constant_function(); | 608 JSFunction* function = optimization.constant_function(); |
601 __ mov(r5, Operand(Handle<JSFunction>(function))); | 609 __ mov(r5, Operand(Handle<JSFunction>(function))); |
602 __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); | 610 __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); |
603 | 611 |
604 // Pass the additional arguments FastHandleApiCall expects. | 612 // Pass the additional arguments FastHandleApiCall expects. |
605 bool info_loaded = false; | |
606 Object* callback = optimization.api_call_info()->callback(); | |
607 if (Heap::InNewSpace(callback)) { | |
608 info_loaded = true; | |
609 __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info())); | |
610 __ ldr(r7, FieldMemOperand(r0, CallHandlerInfo::kCallbackOffset)); | |
611 } else { | |
612 __ Move(r7, Handle<Object>(callback)); | |
613 } | |
614 Object* call_data = optimization.api_call_info()->data(); | 613 Object* call_data = optimization.api_call_info()->data(); |
614 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); | |
615 if (Heap::InNewSpace(call_data)) { | 615 if (Heap::InNewSpace(call_data)) { |
616 if (!info_loaded) { | 616 __ Move(r0, api_call_info_handle); |
617 __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info())); | |
618 } | |
619 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); | 617 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); |
620 } else { | 618 } else { |
621 __ Move(r6, Handle<Object>(call_data)); | 619 __ Move(r6, Handle<Object>(call_data)); |
622 } | 620 } |
621 // Store js function and call data. | |
622 __ stm(ib, sp, r5.bit() | r6.bit()); | |
623 | 623 |
624 __ add(sp, sp, Operand(1 * kPointerSize)); | 624 // r2 points to call data as expected by Arguments class (refer layout above). |
antonm
2011/01/26 11:36:38
nit: refer <to> layout above?
Zaheer
2011/02/02 10:05:59
Done.
| |
625 __ stm(ia, sp, r5.bit() | r6.bit() | r7.bit()); | 625 __ add(r2, sp, Operand(2 * kPointerSize)); |
626 __ sub(sp, sp, Operand(1 * kPointerSize)); | |
627 | 626 |
628 // Set the number of arguments. | 627 Object* callback = optimization.api_call_info()->callback(); |
629 __ mov(r0, Operand(argc + 4)); | 628 Address api_function_address = v8::ToCData<Address>(callback); |
629 ApiFunction fun(api_function_address); | |
630 | 630 |
631 // Jump to the fast api call builtin (tail call). | 631 const int kApiStackSpace = 4; |
632 Handle<Code> code = Handle<Code>( | 632 __ PrepareCallApiFunction(kApiStackSpace, |
633 Builtins::builtin(Builtins::FastHandleApiCall)); | 633 argc + kFastApiCallArguments + 1); |
634 ParameterCount expected(0); | 634 // v8::Arguments::implicit_args = data |
635 __ InvokeCode(code, expected, expected, | 635 __ str(r2, MemOperand(sp)); |
636 RelocInfo::CODE_TARGET, JUMP_FUNCTION); | 636 // v8::Arguments::values = last argument |
637 __ add(ip, r2, Operand(argc * kPointerSize)); | |
638 __ str(ip, MemOperand(sp, 1 * kPointerSize)); | |
639 // v8::Arguments::length_ = argc | |
640 __ mov(ip, Operand(argc)); | |
641 __ str(ip, MemOperand(sp, 2 * kPointerSize)); | |
642 // v8::Arguments::is_construct_call = 0 | |
643 __ mov(ip, Operand(0)); | |
644 __ str(ip, MemOperand(sp, 3 * kPointerSize)); | |
645 // r0 = v8::Arguments& | |
646 __ mov(r0, sp); | |
647 | |
648 // Emitting a stub call may try to allocate (if the code is not | |
649 // already generated). Do not allow the assembler to perform a | |
650 // garbage collection but instead return the allocation failure | |
651 // object. | |
652 MaybeObject* result = masm->TryCallApiFunctionAndReturn(&fun); | |
653 if (result->IsFailure()) { | |
654 return result; | |
655 } | |
656 return Heap::undefined_value(); | |
637 } | 657 } |
638 | 658 |
639 | |
640 class CallInterceptorCompiler BASE_EMBEDDED { | 659 class CallInterceptorCompiler BASE_EMBEDDED { |
641 public: | 660 public: |
642 CallInterceptorCompiler(StubCompiler* stub_compiler, | 661 CallInterceptorCompiler(StubCompiler* stub_compiler, |
643 const ParameterCount& arguments, | 662 const ParameterCount& arguments, |
644 Register name) | 663 Register name) |
645 : stub_compiler_(stub_compiler), | 664 : stub_compiler_(stub_compiler), |
646 arguments_(arguments), | 665 arguments_(arguments), |
647 name_(name) {} | 666 name_(name) {} |
648 | 667 |
649 void Compile(MacroAssembler* masm, | 668 MaybeObject* Compile(MacroAssembler* masm, |
650 JSObject* object, | 669 JSObject* object, |
651 JSObject* holder, | 670 JSObject* holder, |
652 String* name, | 671 String* name, |
653 LookupResult* lookup, | 672 LookupResult* lookup, |
654 Register receiver, | 673 Register receiver, |
655 Register scratch1, | 674 Register scratch1, |
656 Register scratch2, | 675 Register scratch2, |
657 Register scratch3, | 676 Register scratch3, |
658 Label* miss) { | 677 Label* miss) { |
659 ASSERT(holder->HasNamedInterceptor()); | 678 ASSERT(holder->HasNamedInterceptor()); |
660 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 679 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
661 | 680 |
662 // Check that the receiver isn't a smi. | 681 // Check that the receiver isn't a smi. |
663 __ BranchOnSmi(receiver, miss); | 682 __ BranchOnSmi(receiver, miss); |
664 | 683 |
665 CallOptimization optimization(lookup); | 684 CallOptimization optimization(lookup); |
666 | 685 |
667 if (optimization.is_constant_call()) { | 686 if (optimization.is_constant_call()) { |
668 CompileCacheable(masm, | 687 return CompileCacheable(masm, |
669 object, | 688 object, |
670 receiver, | 689 receiver, |
671 scratch1, | 690 scratch1, |
672 scratch2, | 691 scratch2, |
673 scratch3, | 692 scratch3, |
674 holder, | 693 holder, |
675 lookup, | 694 lookup, |
676 name, | 695 name, |
677 optimization, | 696 optimization, |
678 miss); | 697 miss); |
679 } else { | 698 } else { |
680 CompileRegular(masm, | 699 CompileRegular(masm, |
681 object, | 700 object, |
682 receiver, | 701 receiver, |
683 scratch1, | 702 scratch1, |
684 scratch2, | 703 scratch2, |
685 scratch3, | 704 scratch3, |
686 name, | 705 name, |
687 holder, | 706 holder, |
688 miss); | 707 miss); |
708 return Heap::undefined_value(); | |
689 } | 709 } |
690 } | 710 } |
691 | 711 |
692 private: | 712 private: |
693 void CompileCacheable(MacroAssembler* masm, | 713 MaybeObject* CompileCacheable(MacroAssembler* masm, |
694 JSObject* object, | 714 JSObject* object, |
695 Register receiver, | 715 Register receiver, |
696 Register scratch1, | 716 Register scratch1, |
697 Register scratch2, | 717 Register scratch2, |
698 Register scratch3, | 718 Register scratch3, |
699 JSObject* interceptor_holder, | 719 JSObject* interceptor_holder, |
700 LookupResult* lookup, | 720 LookupResult* lookup, |
701 String* name, | 721 String* name, |
702 const CallOptimization& optimization, | 722 const CallOptimization& optimization, |
703 Label* miss_label) { | 723 Label* miss_label) { |
704 ASSERT(optimization.is_constant_call()); | 724 ASSERT(optimization.is_constant_call()); |
705 ASSERT(!lookup->holder()->IsGlobalObject()); | 725 ASSERT(!lookup->holder()->IsGlobalObject()); |
706 | 726 |
707 int depth1 = kInvalidProtoDepth; | 727 int depth1 = kInvalidProtoDepth; |
708 int depth2 = kInvalidProtoDepth; | 728 int depth2 = kInvalidProtoDepth; |
709 bool can_do_fast_api_call = false; | 729 bool can_do_fast_api_call = false; |
710 if (optimization.is_simple_api_call() && | 730 if (optimization.is_simple_api_call() && |
711 !lookup->holder()->IsGlobalObject()) { | 731 !lookup->holder()->IsGlobalObject()) { |
712 depth1 = | 732 depth1 = |
713 optimization.GetPrototypeDepthOfExpectedType(object, | 733 optimization.GetPrototypeDepthOfExpectedType(object, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
757 } else { | 777 } else { |
758 // CheckPrototypes has a side effect of fetching a 'holder' | 778 // CheckPrototypes has a side effect of fetching a 'holder' |
759 // for API (object which is instanceof for the signature). It's | 779 // for API (object which is instanceof for the signature). It's |
760 // safe to omit it here, as if present, it should be fetched | 780 // safe to omit it here, as if present, it should be fetched |
761 // by the previous CheckPrototypes. | 781 // by the previous CheckPrototypes. |
762 ASSERT(depth2 == kInvalidProtoDepth); | 782 ASSERT(depth2 == kInvalidProtoDepth); |
763 } | 783 } |
764 | 784 |
765 // Invoke function. | 785 // Invoke function. |
766 if (can_do_fast_api_call) { | 786 if (can_do_fast_api_call) { |
767 GenerateFastApiCall(masm, optimization, arguments_.immediate()); | 787 MaybeObject* result = GenerateFastApiDirectCall(masm, |
788 optimization, | |
789 arguments_.immediate()); | |
790 if (result->IsFailure()) return result; | |
768 } else { | 791 } else { |
769 __ InvokeFunction(optimization.constant_function(), arguments_, | 792 __ InvokeFunction(optimization.constant_function(), arguments_, |
770 JUMP_FUNCTION); | 793 JUMP_FUNCTION); |
771 } | 794 } |
772 | 795 |
773 // Deferred code for fast API call case---clean preallocated space. | 796 // Deferred code for fast API call case---clean preallocated space. |
774 if (can_do_fast_api_call) { | 797 if (can_do_fast_api_call) { |
775 __ bind(&miss_cleanup); | 798 __ bind(&miss_cleanup); |
776 FreeSpaceForFastApiCall(masm); | 799 FreeSpaceForFastApiCall(masm); |
777 __ b(miss_label); | 800 __ b(miss_label); |
778 } | 801 } |
779 | 802 |
780 // Invoke a regular function. | 803 // Invoke a regular function. |
781 __ bind(®ular_invoke); | 804 __ bind(®ular_invoke); |
782 if (can_do_fast_api_call) { | 805 if (can_do_fast_api_call) { |
783 FreeSpaceForFastApiCall(masm); | 806 FreeSpaceForFastApiCall(masm); |
784 } | 807 } |
808 | |
809 return Heap::undefined_value(); | |
785 } | 810 } |
786 | 811 |
787 void CompileRegular(MacroAssembler* masm, | 812 void CompileRegular(MacroAssembler* masm, |
788 JSObject* object, | 813 JSObject* object, |
789 Register receiver, | 814 Register receiver, |
790 Register scratch1, | 815 Register scratch1, |
791 Register scratch2, | 816 Register scratch2, |
792 Register scratch3, | 817 Register scratch3, |
793 String* name, | 818 String* name, |
794 JSObject* interceptor_holder, | 819 JSObject* interceptor_holder, |
(...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2231 r1, r4, name, &miss); | 2256 r1, r4, name, &miss); |
2232 } | 2257 } |
2233 break; | 2258 break; |
2234 } | 2259 } |
2235 | 2260 |
2236 default: | 2261 default: |
2237 UNREACHABLE(); | 2262 UNREACHABLE(); |
2238 } | 2263 } |
2239 | 2264 |
2240 if (depth != kInvalidProtoDepth) { | 2265 if (depth != kInvalidProtoDepth) { |
2241 GenerateFastApiCall(masm(), optimization, argc); | 2266 MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc); |
2267 if (result->IsFailure()) return result; | |
2242 } else { | 2268 } else { |
2243 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 2269 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
2244 } | 2270 } |
2245 | 2271 |
2246 // Handle call cache miss. | 2272 // Handle call cache miss. |
2247 __ bind(&miss); | 2273 __ bind(&miss); |
2248 if (depth != kInvalidProtoDepth) { | 2274 if (depth != kInvalidProtoDepth) { |
2249 FreeSpaceForFastApiCall(masm()); | 2275 FreeSpaceForFastApiCall(masm()); |
2250 } | 2276 } |
2251 | 2277 |
(...skipping 23 matching lines...) Expand all Loading... | |
2275 // Get the number of arguments. | 2301 // Get the number of arguments. |
2276 const int argc = arguments().immediate(); | 2302 const int argc = arguments().immediate(); |
2277 | 2303 |
2278 LookupResult lookup; | 2304 LookupResult lookup; |
2279 LookupPostInterceptor(holder, name, &lookup); | 2305 LookupPostInterceptor(holder, name, &lookup); |
2280 | 2306 |
2281 // Get the receiver from the stack. | 2307 // Get the receiver from the stack. |
2282 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2308 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
2283 | 2309 |
2284 CallInterceptorCompiler compiler(this, arguments(), r2); | 2310 CallInterceptorCompiler compiler(this, arguments(), r2); |
2285 compiler.Compile(masm(), | 2311 MaybeObject* result = compiler.Compile(masm(), |
2286 object, | 2312 object, |
2287 holder, | 2313 holder, |
2288 name, | 2314 name, |
2289 &lookup, | 2315 &lookup, |
2290 r1, | 2316 r1, |
2291 r3, | 2317 r3, |
2292 r4, | 2318 r4, |
2293 r0, | 2319 r0, |
2294 &miss); | 2320 &miss); |
2321 if (result->IsFailure()) { | |
2322 return result; | |
2323 } | |
2295 | 2324 |
2296 // Move returned value, the function to call, to r1. | 2325 // Move returned value, the function to call, to r1. |
2297 __ mov(r1, r0); | 2326 __ mov(r1, r0); |
2298 // Restore receiver. | 2327 // Restore receiver. |
2299 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 2328 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
2300 | 2329 |
2301 GenerateCallFunction(masm(), object, arguments(), &miss); | 2330 GenerateCallFunction(masm(), object, arguments(), &miss); |
2302 | 2331 |
2303 // Handle call cache miss. | 2332 // Handle call cache miss. |
2304 __ bind(&miss); | 2333 __ bind(&miss); |
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3200 // Return the generated code. | 3229 // Return the generated code. |
3201 return GetCode(); | 3230 return GetCode(); |
3202 } | 3231 } |
3203 | 3232 |
3204 | 3233 |
3205 #undef __ | 3234 #undef __ |
3206 | 3235 |
3207 } } // namespace v8::internal | 3236 } } // namespace v8::internal |
3208 | 3237 |
3209 #endif // V8_TARGET_ARCH_ARM | 3238 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |