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

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 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
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(&regular_invoke); 804 __ bind(&regular_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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698