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

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

Issue 6170001: Direct call api functions (arm implementation) (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 11 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
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 553 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 GenerateFastApiCall.
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 bool GenerateFastApiDirectCall(MacroAssembler* masm,
596 static void GenerateFastApiCall(MacroAssembler* masm, 596 const CallOptimization& optimization,
597 const CallOptimization& optimization, 597 int argc,
598 int argc) { 598 Failure** failure) {
599 // ----------- S t a t e -------------
600 // -- sp[0] : holder (set by CheckPrototypes)
601 // -- sp[4] : callee js function
602 // -- sp[8] : call data
603 // -- sp[12] : last js argument
604 // -- ...
605 // -- sp[(argc + 3) * 4] : first js argument
606 // -- sp[(argc + 4) * 4] : receiver
607 // -----------------------------------
599 // Get the function and setup the context. 608 // Get the function and setup the context.
600 JSFunction* function = optimization.constant_function(); 609 JSFunction* function = optimization.constant_function();
601 __ mov(r5, Operand(Handle<JSFunction>(function))); 610 __ mov(r5, Operand(Handle<JSFunction>(function)));
602 __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); 611 __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset));
603 612
604 // Pass the additional arguments FastHandleApiCall expects. 613 // 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(); 614 Object* call_data = optimization.api_call_info()->data();
615 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info());
615 if (Heap::InNewSpace(call_data)) { 616 if (Heap::InNewSpace(call_data)) {
616 if (!info_loaded) { 617 __ Move(r0, api_call_info_handle);
617 __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info()));
618 }
619 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); 618 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset));
620 } else { 619 } else {
621 __ Move(r6, Handle<Object>(call_data)); 620 __ Move(r6, Handle<Object>(call_data));
622 } 621 }
622 __ stm(ib, sp, r5.bit() | r6.bit());
antonm 2011/01/21 17:56:36 Please, add a comment
Zaheer 2011/01/24 09:43:31 Done.
623 623
624 __ add(sp, sp, Operand(1 * kPointerSize)); 624 // r2 points to calldata as expected by Arguments class (refer layout above)
antonm 2011/01/21 17:56:36 nit: either call_data or call data, please
Zaheer 2011/01/24 09:43:31 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 =
653 masm->TryCallApiFunctionAndReturn(&fun);
654 if (result->IsFailure()) {
655 *failure = Failure::cast(result);
656 return false;
657 }
658 return true;
637 } 659 }
638 660
639
640 class CallInterceptorCompiler BASE_EMBEDDED { 661 class CallInterceptorCompiler BASE_EMBEDDED {
641 public: 662 public:
642 CallInterceptorCompiler(StubCompiler* stub_compiler, 663 CallInterceptorCompiler(StubCompiler* stub_compiler,
643 const ParameterCount& arguments, 664 const ParameterCount& arguments,
644 Register name) 665 Register name)
645 : stub_compiler_(stub_compiler), 666 : stub_compiler_(stub_compiler),
646 arguments_(arguments), 667 arguments_(arguments),
647 name_(name) {} 668 name_(name) {}
648 669
649 void Compile(MacroAssembler* masm, 670 bool Compile(MacroAssembler* masm,
650 JSObject* object, 671 JSObject* object,
651 JSObject* holder, 672 JSObject* holder,
652 String* name, 673 String* name,
653 LookupResult* lookup, 674 LookupResult* lookup,
654 Register receiver, 675 Register receiver,
655 Register scratch1, 676 Register scratch1,
656 Register scratch2, 677 Register scratch2,
657 Register scratch3, 678 Register scratch3,
658 Label* miss) { 679 Label* miss,
680 Failure **failure) {
659 ASSERT(holder->HasNamedInterceptor()); 681 ASSERT(holder->HasNamedInterceptor());
660 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 682 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
661 683
662 // Check that the receiver isn't a smi. 684 // Check that the receiver isn't a smi.
663 __ BranchOnSmi(receiver, miss); 685 __ BranchOnSmi(receiver, miss);
664 686
665 CallOptimization optimization(lookup); 687 CallOptimization optimization(lookup);
666 688
667 if (optimization.is_constant_call()) { 689 if (optimization.is_constant_call()) {
668 CompileCacheable(masm, 690 return CompileCacheable(masm,
669 object, 691 object,
670 receiver, 692 receiver,
671 scratch1, 693 scratch1,
672 scratch2, 694 scratch2,
673 scratch3, 695 scratch3,
674 holder, 696 holder,
675 lookup, 697 lookup,
676 name, 698 name,
677 optimization, 699 optimization,
678 miss); 700 miss,
701 failure);
679 } else { 702 } else {
680 CompileRegular(masm, 703 CompileRegular(masm,
681 object, 704 object,
682 receiver, 705 receiver,
683 scratch1, 706 scratch1,
684 scratch2, 707 scratch2,
685 scratch3, 708 scratch3,
686 name, 709 name,
687 holder, 710 holder,
688 miss); 711 miss);
712 return true;
689 } 713 }
690 } 714 }
691 715
692 private: 716 private:
693 void CompileCacheable(MacroAssembler* masm, 717 bool CompileCacheable(MacroAssembler* masm,
694 JSObject* object, 718 JSObject* object,
695 Register receiver, 719 Register receiver,
696 Register scratch1, 720 Register scratch1,
697 Register scratch2, 721 Register scratch2,
698 Register scratch3, 722 Register scratch3,
699 JSObject* interceptor_holder, 723 JSObject* interceptor_holder,
700 LookupResult* lookup, 724 LookupResult* lookup,
701 String* name, 725 String* name,
702 const CallOptimization& optimization, 726 const CallOptimization& optimization,
703 Label* miss_label) { 727 Label* miss_label,
728 Failure **failure) {
704 ASSERT(optimization.is_constant_call()); 729 ASSERT(optimization.is_constant_call());
705 ASSERT(!lookup->holder()->IsGlobalObject()); 730 ASSERT(!lookup->holder()->IsGlobalObject());
706 731
707 int depth1 = kInvalidProtoDepth; 732 int depth1 = kInvalidProtoDepth;
708 int depth2 = kInvalidProtoDepth; 733 int depth2 = kInvalidProtoDepth;
709 bool can_do_fast_api_call = false; 734 bool can_do_fast_api_call = false;
710 if (optimization.is_simple_api_call() && 735 if (optimization.is_simple_api_call() &&
711 !lookup->holder()->IsGlobalObject()) { 736 !lookup->holder()->IsGlobalObject()) {
712 depth1 = 737 depth1 =
713 optimization.GetPrototypeDepthOfExpectedType(object, 738 optimization.GetPrototypeDepthOfExpectedType(object,
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 } else { 782 } else {
758 // CheckPrototypes has a side effect of fetching a 'holder' 783 // CheckPrototypes has a side effect of fetching a 'holder'
759 // for API (object which is instanceof for the signature). It's 784 // for API (object which is instanceof for the signature). It's
760 // safe to omit it here, as if present, it should be fetched 785 // safe to omit it here, as if present, it should be fetched
761 // by the previous CheckPrototypes. 786 // by the previous CheckPrototypes.
762 ASSERT(depth2 == kInvalidProtoDepth); 787 ASSERT(depth2 == kInvalidProtoDepth);
763 } 788 }
764 789
765 // Invoke function. 790 // Invoke function.
766 if (can_do_fast_api_call) { 791 if (can_do_fast_api_call) {
767 GenerateFastApiCall(masm, optimization, arguments_.immediate()); 792 bool success = GenerateFastApiDirectCall(masm,
793 optimization,
794 arguments_.immediate(),
795 failure);
796 if (!success) {
797 return false;
798 }
768 } else { 799 } else {
769 __ InvokeFunction(optimization.constant_function(), arguments_, 800 __ InvokeFunction(optimization.constant_function(), arguments_,
770 JUMP_FUNCTION); 801 JUMP_FUNCTION);
771 } 802 }
772 803
773 // Deferred code for fast API call case---clean preallocated space. 804 // Deferred code for fast API call case---clean preallocated space.
774 if (can_do_fast_api_call) { 805 if (can_do_fast_api_call) {
775 __ bind(&miss_cleanup); 806 __ bind(&miss_cleanup);
776 FreeSpaceForFastApiCall(masm); 807 FreeSpaceForFastApiCall(masm);
777 __ b(miss_label); 808 __ b(miss_label);
778 } 809 }
779 810
780 // Invoke a regular function. 811 // Invoke a regular function.
781 __ bind(&regular_invoke); 812 __ bind(&regular_invoke);
782 if (can_do_fast_api_call) { 813 if (can_do_fast_api_call) {
783 FreeSpaceForFastApiCall(masm); 814 FreeSpaceForFastApiCall(masm);
784 } 815 }
816
817 return true;
785 } 818 }
786 819
787 void CompileRegular(MacroAssembler* masm, 820 void CompileRegular(MacroAssembler* masm,
788 JSObject* object, 821 JSObject* object,
789 Register receiver, 822 Register receiver,
790 Register scratch1, 823 Register scratch1,
791 Register scratch2, 824 Register scratch2,
792 Register scratch3, 825 Register scratch3,
793 String* name, 826 String* name,
794 JSObject* interceptor_holder, 827 JSObject* interceptor_holder,
(...skipping 1436 matching lines...) Expand 10 before | Expand all | Expand 10 after
2231 r1, r4, name, &miss); 2264 r1, r4, name, &miss);
2232 } 2265 }
2233 break; 2266 break;
2234 } 2267 }
2235 2268
2236 default: 2269 default:
2237 UNREACHABLE(); 2270 UNREACHABLE();
2238 } 2271 }
2239 2272
2240 if (depth != kInvalidProtoDepth) { 2273 if (depth != kInvalidProtoDepth) {
2241 GenerateFastApiCall(masm(), optimization, argc); 2274 Failure* failure;
2275 bool success = GenerateFastApiDirectCall(masm(),
2276 optimization,
2277 argc,
2278 &failure);
2279 if (!success) {
2280 return failure;
2281 }
2242 } else { 2282 } else {
2243 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 2283 __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
2244 } 2284 }
2245 2285
2246 // Handle call cache miss. 2286 // Handle call cache miss.
2247 __ bind(&miss); 2287 __ bind(&miss);
2248 if (depth != kInvalidProtoDepth) { 2288 if (depth != kInvalidProtoDepth) {
2249 FreeSpaceForFastApiCall(masm()); 2289 FreeSpaceForFastApiCall(masm());
2250 } 2290 }
2251 2291
(...skipping 23 matching lines...) Expand all
2275 // Get the number of arguments. 2315 // Get the number of arguments.
2276 const int argc = arguments().immediate(); 2316 const int argc = arguments().immediate();
2277 2317
2278 LookupResult lookup; 2318 LookupResult lookup;
2279 LookupPostInterceptor(holder, name, &lookup); 2319 LookupPostInterceptor(holder, name, &lookup);
2280 2320
2281 // Get the receiver from the stack. 2321 // Get the receiver from the stack.
2282 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 2322 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
2283 2323
2284 CallInterceptorCompiler compiler(this, arguments(), r2); 2324 CallInterceptorCompiler compiler(this, arguments(), r2);
2285 compiler.Compile(masm(), 2325 Failure *failure;
2326 bool success = compiler.Compile(masm(),
2286 object, 2327 object,
2287 holder, 2328 holder,
2288 name, 2329 name,
2289 &lookup, 2330 &lookup,
2290 r1, 2331 r1,
2291 r3, 2332 r3,
2292 r4, 2333 r4,
2293 r0, 2334 r0,
2294 &miss); 2335 &miss,
2336 &failure);
2337 if (!success) {
2338 return false;
2339 }
2295 2340
2296 // Move returned value, the function to call, to r1. 2341 // Move returned value, the function to call, to r1.
2297 __ mov(r1, r0); 2342 __ mov(r1, r0);
2298 // Restore receiver. 2343 // Restore receiver.
2299 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 2344 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
2300 2345
2301 GenerateCallFunction(masm(), object, arguments(), &miss); 2346 GenerateCallFunction(masm(), object, arguments(), &miss);
2302 2347
2303 // Handle call cache miss. 2348 // Handle call cache miss.
2304 __ bind(&miss); 2349 __ bind(&miss);
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after
3200 // Return the generated code. 3245 // Return the generated code.
3201 return GetCode(); 3246 return GetCode();
3202 } 3247 }
3203 3248
3204 3249
3205 #undef __ 3250 #undef __
3206 3251
3207 } } // namespace v8::internal 3252 } } // namespace v8::internal
3208 3253
3209 #endif // V8_TARGET_ARCH_ARM 3254 #endif // V8_TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698