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 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
568 | 568 |
569 ExternalReference ref = | 569 ExternalReference ref = |
570 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); | 570 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); |
571 __ mov(r0, Operand(5)); | 571 __ mov(r0, Operand(5)); |
572 __ mov(r1, Operand(ref)); | 572 __ mov(r1, Operand(ref)); |
573 | 573 |
574 CEntryStub stub(1); | 574 CEntryStub stub(1); |
575 __ CallStub(&stub); | 575 __ CallStub(&stub); |
576 } | 576 } |
577 | 577 |
| 578 static const int kFastApiCallArguments = 3; |
578 | 579 |
579 // Reserves space for the extra arguments to FastHandleApiCall in the | 580 // Reserves space for the extra arguments to FastHandleApiCall in the |
580 // caller's frame. | 581 // caller's frame. |
581 // | 582 // |
582 // These arguments are set by CheckPrototypes and GenerateFastApiCall. | 583 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. |
583 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, | 584 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, |
584 Register scratch) { | 585 Register scratch) { |
585 __ mov(scratch, Operand(Smi::FromInt(0))); | 586 __ mov(scratch, Operand(Smi::FromInt(0))); |
586 __ push(scratch); | 587 for (int i = 0; i < kFastApiCallArguments; i++) { |
587 __ push(scratch); | 588 __ push(scratch); |
588 __ push(scratch); | 589 } |
589 __ push(scratch); | |
590 } | 590 } |
591 | 591 |
592 | 592 |
593 // Undoes the effects of ReserveSpaceForFastApiCall. | 593 // Undoes the effects of ReserveSpaceForFastApiCall. |
594 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { | 594 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { |
595 __ Drop(4); | 595 __ Drop(kFastApiCallArguments); |
596 } | 596 } |
597 | 597 |
598 | 598 |
599 // Generates call to FastHandleApiCall builtin. | 599 static MaybeObject* GenerateFastApiDirectCall(MacroAssembler* masm, |
600 static void GenerateFastApiCall(MacroAssembler* masm, | 600 const CallOptimization& optimization, |
601 const CallOptimization& optimization, | 601 int argc) { |
602 int argc) { | 602 // ----------- S t a t e ------------- |
| 603 // -- sp[0] : holder (set by CheckPrototypes) |
| 604 // -- sp[4] : callee js function |
| 605 // -- sp[8] : call data |
| 606 // -- sp[12] : last js argument |
| 607 // -- ... |
| 608 // -- sp[(argc + 3) * 4] : first js argument |
| 609 // -- sp[(argc + 4) * 4] : receiver |
| 610 // ----------------------------------- |
603 // Get the function and setup the context. | 611 // Get the function and setup the context. |
604 JSFunction* function = optimization.constant_function(); | 612 JSFunction* function = optimization.constant_function(); |
605 __ mov(r5, Operand(Handle<JSFunction>(function))); | 613 __ mov(r5, Operand(Handle<JSFunction>(function))); |
606 __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); | 614 __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); |
607 | 615 |
608 // Pass the additional arguments FastHandleApiCall expects. | 616 // Pass the additional arguments FastHandleApiCall expects. |
609 bool info_loaded = false; | |
610 Object* callback = optimization.api_call_info()->callback(); | |
611 if (Heap::InNewSpace(callback)) { | |
612 info_loaded = true; | |
613 __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info())); | |
614 __ ldr(r7, FieldMemOperand(r0, CallHandlerInfo::kCallbackOffset)); | |
615 } else { | |
616 __ Move(r7, Handle<Object>(callback)); | |
617 } | |
618 Object* call_data = optimization.api_call_info()->data(); | 617 Object* call_data = optimization.api_call_info()->data(); |
| 618 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); |
619 if (Heap::InNewSpace(call_data)) { | 619 if (Heap::InNewSpace(call_data)) { |
620 if (!info_loaded) { | 620 __ Move(r0, api_call_info_handle); |
621 __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info())); | |
622 } | |
623 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); | 621 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); |
624 } else { | 622 } else { |
625 __ Move(r6, Handle<Object>(call_data)); | 623 __ Move(r6, Handle<Object>(call_data)); |
626 } | 624 } |
| 625 // Store js function and call data. |
| 626 __ stm(ib, sp, r5.bit() | r6.bit()); |
627 | 627 |
628 __ add(sp, sp, Operand(1 * kPointerSize)); | 628 // r2 points to call data as expected by Arguments |
629 __ stm(ia, sp, r5.bit() | r6.bit() | r7.bit()); | 629 // (refer to layout above). |
630 __ sub(sp, sp, Operand(1 * kPointerSize)); | 630 __ add(r2, sp, Operand(2 * kPointerSize)); |
631 | 631 |
632 // Set the number of arguments. | 632 Object* callback = optimization.api_call_info()->callback(); |
633 __ mov(r0, Operand(argc + 4)); | 633 Address api_function_address = v8::ToCData<Address>(callback); |
| 634 ApiFunction fun(api_function_address); |
634 | 635 |
635 // Jump to the fast api call builtin (tail call). | 636 const int kApiStackSpace = 4; |
636 Handle<Code> code = Handle<Code>( | 637 __ EnterExitFrame(false, kApiStackSpace); |
637 Builtins::builtin(Builtins::FastHandleApiCall)); | 638 |
638 ParameterCount expected(0); | 639 // r0 = v8::Arguments& |
639 __ InvokeCode(code, expected, expected, | 640 // Arguments is after the return address. |
640 RelocInfo::CODE_TARGET, JUMP_FUNCTION); | 641 __ add(r0, sp, Operand(1 * kPointerSize)); |
| 642 // v8::Arguments::implicit_args = data |
| 643 __ str(r2, MemOperand(r0, 0 * kPointerSize)); |
| 644 // v8::Arguments::values = last argument |
| 645 __ add(ip, r2, Operand(argc * kPointerSize)); |
| 646 __ str(ip, MemOperand(r0, 1 * kPointerSize)); |
| 647 // v8::Arguments::length_ = argc |
| 648 __ mov(ip, Operand(argc)); |
| 649 __ str(ip, MemOperand(r0, 2 * kPointerSize)); |
| 650 // v8::Arguments::is_construct_call = 0 |
| 651 __ mov(ip, Operand(0)); |
| 652 __ str(ip, MemOperand(r0, 3 * kPointerSize)); |
| 653 |
| 654 // Emitting a stub call may try to allocate (if the code is not |
| 655 // already generated). Do not allow the assembler to perform a |
| 656 // garbage collection but instead return the allocation failure |
| 657 // object. |
| 658 MaybeObject* result = masm->TryCallApiFunctionAndReturn( |
| 659 &fun, argc + kFastApiCallArguments + 1); |
| 660 if (result->IsFailure()) { |
| 661 return result; |
| 662 } |
| 663 return Heap::undefined_value(); |
641 } | 664 } |
642 | 665 |
643 | |
644 class CallInterceptorCompiler BASE_EMBEDDED { | 666 class CallInterceptorCompiler BASE_EMBEDDED { |
645 public: | 667 public: |
646 CallInterceptorCompiler(StubCompiler* stub_compiler, | 668 CallInterceptorCompiler(StubCompiler* stub_compiler, |
647 const ParameterCount& arguments, | 669 const ParameterCount& arguments, |
648 Register name) | 670 Register name) |
649 : stub_compiler_(stub_compiler), | 671 : stub_compiler_(stub_compiler), |
650 arguments_(arguments), | 672 arguments_(arguments), |
651 name_(name) {} | 673 name_(name) {} |
652 | 674 |
653 void Compile(MacroAssembler* masm, | 675 MaybeObject* Compile(MacroAssembler* masm, |
654 JSObject* object, | 676 JSObject* object, |
655 JSObject* holder, | 677 JSObject* holder, |
656 String* name, | 678 String* name, |
657 LookupResult* lookup, | 679 LookupResult* lookup, |
658 Register receiver, | 680 Register receiver, |
659 Register scratch1, | 681 Register scratch1, |
660 Register scratch2, | 682 Register scratch2, |
661 Register scratch3, | 683 Register scratch3, |
662 Label* miss) { | 684 Label* miss) { |
663 ASSERT(holder->HasNamedInterceptor()); | 685 ASSERT(holder->HasNamedInterceptor()); |
664 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 686 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
665 | 687 |
666 // Check that the receiver isn't a smi. | 688 // Check that the receiver isn't a smi. |
667 __ JumpIfSmi(receiver, miss); | 689 __ JumpIfSmi(receiver, miss); |
668 | 690 |
669 CallOptimization optimization(lookup); | 691 CallOptimization optimization(lookup); |
670 | 692 |
671 if (optimization.is_constant_call()) { | 693 if (optimization.is_constant_call()) { |
672 CompileCacheable(masm, | 694 return CompileCacheable(masm, |
673 object, | 695 object, |
674 receiver, | 696 receiver, |
675 scratch1, | 697 scratch1, |
676 scratch2, | 698 scratch2, |
677 scratch3, | 699 scratch3, |
678 holder, | 700 holder, |
679 lookup, | 701 lookup, |
680 name, | 702 name, |
681 optimization, | 703 optimization, |
682 miss); | 704 miss); |
683 } else { | 705 } else { |
684 CompileRegular(masm, | 706 CompileRegular(masm, |
685 object, | 707 object, |
686 receiver, | 708 receiver, |
687 scratch1, | 709 scratch1, |
688 scratch2, | 710 scratch2, |
689 scratch3, | 711 scratch3, |
690 name, | 712 name, |
691 holder, | 713 holder, |
692 miss); | 714 miss); |
| 715 return Heap::undefined_value(); |
693 } | 716 } |
694 } | 717 } |
695 | 718 |
696 private: | 719 private: |
697 void CompileCacheable(MacroAssembler* masm, | 720 MaybeObject* CompileCacheable(MacroAssembler* masm, |
698 JSObject* object, | 721 JSObject* object, |
699 Register receiver, | 722 Register receiver, |
700 Register scratch1, | 723 Register scratch1, |
701 Register scratch2, | 724 Register scratch2, |
702 Register scratch3, | 725 Register scratch3, |
703 JSObject* interceptor_holder, | 726 JSObject* interceptor_holder, |
704 LookupResult* lookup, | 727 LookupResult* lookup, |
705 String* name, | 728 String* name, |
706 const CallOptimization& optimization, | 729 const CallOptimization& optimization, |
707 Label* miss_label) { | 730 Label* miss_label) { |
708 ASSERT(optimization.is_constant_call()); | 731 ASSERT(optimization.is_constant_call()); |
709 ASSERT(!lookup->holder()->IsGlobalObject()); | 732 ASSERT(!lookup->holder()->IsGlobalObject()); |
710 | 733 |
711 int depth1 = kInvalidProtoDepth; | 734 int depth1 = kInvalidProtoDepth; |
712 int depth2 = kInvalidProtoDepth; | 735 int depth2 = kInvalidProtoDepth; |
713 bool can_do_fast_api_call = false; | 736 bool can_do_fast_api_call = false; |
714 if (optimization.is_simple_api_call() && | 737 if (optimization.is_simple_api_call() && |
715 !lookup->holder()->IsGlobalObject()) { | 738 !lookup->holder()->IsGlobalObject()) { |
716 depth1 = | 739 depth1 = |
717 optimization.GetPrototypeDepthOfExpectedType(object, | 740 optimization.GetPrototypeDepthOfExpectedType(object, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 } else { | 784 } else { |
762 // CheckPrototypes has a side effect of fetching a 'holder' | 785 // CheckPrototypes has a side effect of fetching a 'holder' |
763 // for API (object which is instanceof for the signature). It's | 786 // for API (object which is instanceof for the signature). It's |
764 // safe to omit it here, as if present, it should be fetched | 787 // safe to omit it here, as if present, it should be fetched |
765 // by the previous CheckPrototypes. | 788 // by the previous CheckPrototypes. |
766 ASSERT(depth2 == kInvalidProtoDepth); | 789 ASSERT(depth2 == kInvalidProtoDepth); |
767 } | 790 } |
768 | 791 |
769 // Invoke function. | 792 // Invoke function. |
770 if (can_do_fast_api_call) { | 793 if (can_do_fast_api_call) { |
771 GenerateFastApiCall(masm, optimization, arguments_.immediate()); | 794 MaybeObject* result = GenerateFastApiDirectCall(masm, |
| 795 optimization, |
| 796 arguments_.immediate()); |
| 797 if (result->IsFailure()) return result; |
772 } else { | 798 } else { |
773 __ InvokeFunction(optimization.constant_function(), arguments_, | 799 __ InvokeFunction(optimization.constant_function(), arguments_, |
774 JUMP_FUNCTION); | 800 JUMP_FUNCTION); |
775 } | 801 } |
776 | 802 |
777 // Deferred code for fast API call case---clean preallocated space. | 803 // Deferred code for fast API call case---clean preallocated space. |
778 if (can_do_fast_api_call) { | 804 if (can_do_fast_api_call) { |
779 __ bind(&miss_cleanup); | 805 __ bind(&miss_cleanup); |
780 FreeSpaceForFastApiCall(masm); | 806 FreeSpaceForFastApiCall(masm); |
781 __ b(miss_label); | 807 __ b(miss_label); |
782 } | 808 } |
783 | 809 |
784 // Invoke a regular function. | 810 // Invoke a regular function. |
785 __ bind(®ular_invoke); | 811 __ bind(®ular_invoke); |
786 if (can_do_fast_api_call) { | 812 if (can_do_fast_api_call) { |
787 FreeSpaceForFastApiCall(masm); | 813 FreeSpaceForFastApiCall(masm); |
788 } | 814 } |
| 815 |
| 816 return Heap::undefined_value(); |
789 } | 817 } |
790 | 818 |
791 void CompileRegular(MacroAssembler* masm, | 819 void CompileRegular(MacroAssembler* masm, |
792 JSObject* object, | 820 JSObject* object, |
793 Register receiver, | 821 Register receiver, |
794 Register scratch1, | 822 Register scratch1, |
795 Register scratch2, | 823 Register scratch2, |
796 Register scratch3, | 824 Register scratch3, |
797 String* name, | 825 String* name, |
798 JSObject* interceptor_holder, | 826 JSObject* interceptor_holder, |
(...skipping 1562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2361 r1, r4, name, &miss); | 2389 r1, r4, name, &miss); |
2362 } | 2390 } |
2363 break; | 2391 break; |
2364 } | 2392 } |
2365 | 2393 |
2366 default: | 2394 default: |
2367 UNREACHABLE(); | 2395 UNREACHABLE(); |
2368 } | 2396 } |
2369 | 2397 |
2370 if (depth != kInvalidProtoDepth) { | 2398 if (depth != kInvalidProtoDepth) { |
2371 GenerateFastApiCall(masm(), optimization, argc); | 2399 MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc); |
| 2400 if (result->IsFailure()) return result; |
2372 } else { | 2401 } else { |
2373 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 2402 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
2374 } | 2403 } |
2375 | 2404 |
2376 // Handle call cache miss. | 2405 // Handle call cache miss. |
2377 __ bind(&miss); | 2406 __ bind(&miss); |
2378 if (depth != kInvalidProtoDepth) { | 2407 if (depth != kInvalidProtoDepth) { |
2379 FreeSpaceForFastApiCall(masm()); | 2408 FreeSpaceForFastApiCall(masm()); |
2380 } | 2409 } |
2381 | 2410 |
(...skipping 23 matching lines...) Expand all Loading... |
2405 // Get the number of arguments. | 2434 // Get the number of arguments. |
2406 const int argc = arguments().immediate(); | 2435 const int argc = arguments().immediate(); |
2407 | 2436 |
2408 LookupResult lookup; | 2437 LookupResult lookup; |
2409 LookupPostInterceptor(holder, name, &lookup); | 2438 LookupPostInterceptor(holder, name, &lookup); |
2410 | 2439 |
2411 // Get the receiver from the stack. | 2440 // Get the receiver from the stack. |
2412 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2441 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
2413 | 2442 |
2414 CallInterceptorCompiler compiler(this, arguments(), r2); | 2443 CallInterceptorCompiler compiler(this, arguments(), r2); |
2415 compiler.Compile(masm(), | 2444 MaybeObject* result = compiler.Compile(masm(), |
2416 object, | 2445 object, |
2417 holder, | 2446 holder, |
2418 name, | 2447 name, |
2419 &lookup, | 2448 &lookup, |
2420 r1, | 2449 r1, |
2421 r3, | 2450 r3, |
2422 r4, | 2451 r4, |
2423 r0, | 2452 r0, |
2424 &miss); | 2453 &miss); |
| 2454 if (result->IsFailure()) { |
| 2455 return result; |
| 2456 } |
2425 | 2457 |
2426 // Move returned value, the function to call, to r1. | 2458 // Move returned value, the function to call, to r1. |
2427 __ mov(r1, r0); | 2459 __ mov(r1, r0); |
2428 // Restore receiver. | 2460 // Restore receiver. |
2429 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 2461 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
2430 | 2462 |
2431 GenerateCallFunction(masm(), object, arguments(), &miss); | 2463 GenerateCallFunction(masm(), object, arguments(), &miss); |
2432 | 2464 |
2433 // Handle call cache miss. | 2465 // Handle call cache miss. |
2434 __ bind(&miss); | 2466 __ bind(&miss); |
(...skipping 1499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3934 | 3966 |
3935 return GetCode(flags); | 3967 return GetCode(flags); |
3936 } | 3968 } |
3937 | 3969 |
3938 | 3970 |
3939 #undef __ | 3971 #undef __ |
3940 | 3972 |
3941 } } // namespace v8::internal | 3973 } } // namespace v8::internal |
3942 | 3974 |
3943 #endif // V8_TARGET_ARCH_ARM | 3975 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |