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

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, 10 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 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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(&regular_invoke); 811 __ bind(&regular_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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698