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

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

Issue 5004004: Port direct API function call to x64 (ia32 CL is http://codereview.chromium.o... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 1 month 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
« no previous file with comments | « src/x64/macro-assembler-x64.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, 490 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
491 Register receiver, 491 Register receiver,
492 Register result, 492 Register result,
493 Register scratch, 493 Register scratch,
494 Label* miss_label) { 494 Label* miss_label) {
495 __ TryGetFunctionPrototype(receiver, result, miss_label); 495 __ TryGetFunctionPrototype(receiver, result, miss_label);
496 if (!result.is(rax)) __ movq(rax, result); 496 if (!result.is(rax)) __ movq(rax, result);
497 __ ret(0); 497 __ ret(0);
498 } 498 }
499 499
500 // Number of pointers to be reserved on stack for fast API call.
501 static const int kFastApiCallArguments = 3;
500 502
501 // Reserves space for the extra arguments to FastHandleApiCall in the 503 // Reserves space for the extra arguments to FastHandleApiCall in the
502 // caller's frame. 504 // caller's frame.
503 // 505 //
504 // These arguments are set by CheckPrototypes and GenerateFastApiCall. 506 // These arguments are set by CheckPrototypes and GenerateFastApiCall.
505 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 507 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
506 // ----------- S t a t e ------------- 508 // ----------- S t a t e -------------
507 // -- rsp[0] : return address 509 // -- rsp[0] : return address
508 // -- rsp[8] : last argument in the internal frame of the caller 510 // -- rsp[8] : last argument in the internal frame of the caller
509 // ----------------------------------- 511 // -----------------------------------
510 __ movq(scratch, Operand(rsp, 0)); 512 __ movq(scratch, Operand(rsp, 0));
511 __ subq(rsp, Immediate(4 * kPointerSize)); 513 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
512 __ movq(Operand(rsp, 0), scratch); 514 __ movq(Operand(rsp, 0), scratch);
513 __ Move(scratch, Smi::FromInt(0)); 515 __ Move(scratch, Smi::FromInt(0));
514 __ movq(Operand(rsp, 1 * kPointerSize), scratch); 516 for (int i = 1; i <= kFastApiCallArguments; i++) {
515 __ movq(Operand(rsp, 2 * kPointerSize), scratch); 517 __ movq(Operand(rsp, i * kPointerSize), scratch);
516 __ movq(Operand(rsp, 3 * kPointerSize), scratch); 518 }
517 __ movq(Operand(rsp, 4 * kPointerSize), scratch);
518 } 519 }
519 520
520 521
521 // Undoes the effects of ReserveSpaceForFastApiCall. 522 // Undoes the effects of ReserveSpaceForFastApiCall.
522 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 523 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
523 // ----------- S t a t e ------------- 524 // ----------- S t a t e -------------
524 // -- rsp[0] : return address 525 // -- rsp[0] : return address.
525 // -- rsp[8] : last fast api call extra argument 526 // -- rsp[8] : last fast api call extra argument.
526 // -- ... 527 // -- ...
527 // -- rsp[32] : first fast api call extra argument 528 // -- rsp[kFastApiCallArguments * 8] : first fast api call extra argument.
528 // -- rsp[40] : last argument in the internal frame 529 // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal
530 // frame.
529 // ----------------------------------- 531 // -----------------------------------
530 __ movq(scratch, Operand(rsp, 0)); 532 __ movq(scratch, Operand(rsp, 0));
531 __ movq(Operand(rsp, 4 * kPointerSize), scratch); 533 __ movq(Operand(rsp, kFastApiCallArguments * kPointerSize), scratch);
532 __ addq(rsp, Immediate(kPointerSize * 4)); 534 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments));
533 } 535 }
534 536
535 537
536 // Generates call to FastHandleApiCall builtin. 538 // Generates call to FastHandleApiCall builtin.
537 static void GenerateFastApiCall(MacroAssembler* masm, 539 static bool GenerateFastApiCall(MacroAssembler* masm,
538 const CallOptimization& optimization, 540 const CallOptimization& optimization,
539 int argc) { 541 int argc,
542 Failure** failure) {
540 // ----------- S t a t e ------------- 543 // ----------- S t a t e -------------
541 // -- rsp[0] : return address 544 // -- rsp[0] : return address
542 // -- rsp[8] : object passing the type check 545 // -- rsp[8] : object passing the type check
543 // (last fast api call extra argument, 546 // (last fast api call extra argument,
544 // set by CheckPrototypes) 547 // set by CheckPrototypes)
545 // -- rsp[16] : api call data 548 // -- rsp[16] : api function
546 // -- rsp[24] : api callback
547 // -- rsp[32] : api function
548 // (first fast api call extra argument) 549 // (first fast api call extra argument)
549 // -- rsp[40] : last argument 550 // -- rsp[24] : api call data
551 // -- rsp[32] : last argument
550 // -- ... 552 // -- ...
551 // -- rsp[(argc + 5) * 8] : first argument 553 // -- rsp[(argc + 3) * 8] : first argument
552 // -- rsp[(argc + 6) * 8] : receiver 554 // -- rsp[(argc + 4) * 8] : receiver
553 // ----------------------------------- 555 // -----------------------------------
554 556
555 // Get the function and setup the context. 557 // Get the function and setup the context.
556 JSFunction* function = optimization.constant_function(); 558 JSFunction* function = optimization.constant_function();
557 __ Move(rdi, Handle<JSFunction>(function)); 559 __ Move(rdi, Handle<JSFunction>(function));
558 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 560 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
559 561
560 // Pass the additional arguments FastHandleApiCall expects. 562 // Pass the additional arguments FastHandleApiCall expects.
561 __ movq(Operand(rsp, 4 * kPointerSize), rdi); 563 __ movq(Operand(rsp, 2 * kPointerSize), rdi);
562 bool info_loaded = false; 564 Object* call_data = optimization.api_call_info()->data();
563 Object* callback = optimization.api_call_info()->callback(); 565 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info());
564 if (Heap::InNewSpace(callback)) { 566 if (Heap::InNewSpace(call_data)) {
565 info_loaded = true; 567 __ Move(rcx, api_call_info_handle);
566 __ Move(rcx, Handle<CallHandlerInfo>(optimization.api_call_info())); 568 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
567 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kCallbackOffset));
568 __ movq(Operand(rsp, 3 * kPointerSize), rbx); 569 __ movq(Operand(rsp, 3 * kPointerSize), rbx);
569 } else { 570 } else {
570 __ Move(Operand(rsp, 3 * kPointerSize), Handle<Object>(callback)); 571 __ Move(Operand(rsp, 3 * kPointerSize), Handle<Object>(call_data));
571 }
572 Object* call_data = optimization.api_call_info()->data();
573 if (Heap::InNewSpace(call_data)) {
574 if (!info_loaded) {
575 __ Move(rcx, Handle<CallHandlerInfo>(optimization.api_call_info()));
576 }
577 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
578 __ movq(Operand(rsp, 2 * kPointerSize), rbx);
579 } else {
580 __ Move(Operand(rsp, 2 * kPointerSize), Handle<Object>(call_data));
581 } 572 }
582 573
583 // Set the number of arguments. 574 // Prepare arguments.
584 __ movq(rax, Immediate(argc + 4)); 575 __ lea(rbx, Operand(rsp, 3 * kPointerSize));
585 576
586 // Jump to the fast api call builtin (tail call). 577 Object* callback = optimization.api_call_info()->callback();
587 Handle<Code> code = Handle<Code>( 578 Address api_function_address = v8::ToCData<Address>(callback);
588 Builtins::builtin(Builtins::FastHandleApiCall)); 579 ApiFunction fun(api_function_address);
589 ParameterCount expected(0); 580
590 __ InvokeCode(code, expected, expected, 581 #ifdef _WIN64
591 RelocInfo::CODE_TARGET, JUMP_FUNCTION); 582 // Win64 uses first register--rcx--for returned value.
583 Register arguments_arg = rdx;
584 #else
585 Register arguments_arg = rdi;
586 #endif
587
588 // Allocate the v8::Arguments structure in the arguments' space since
589 // it's not controlled by GC.
590 const int kApiStackSpace = 4;
591
592 __ PrepareCallApiFunction(argc + kFastApiCallArguments + 1, kApiStackSpace);
593
594 __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_.
595 __ addq(rbx, Immediate(argc * kPointerSize));
596 __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_.
597 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_.
598 // v8::Arguments::is_construct_call_.
599 __ Set(StackSpaceOperand(3), 0);
600
601 // v8::InvocationCallback's argument.
602 __ lea(arguments_arg, StackSpaceOperand(0));
603 // Emitting a stub call may try to allocate (if the code is not
604 // already generated). Do not allow the assembler to perform a
605 // garbage collection but instead return the allocation failure
606 // object.
607 MaybeObject* result =
608 masm->TryCallApiFunctionAndReturn(&fun);
609 if (result->IsFailure()) {
610 *failure = Failure::cast(result);
611 return false;
612 }
613 return true;
592 } 614 }
593 615
594 616
595 class CallInterceptorCompiler BASE_EMBEDDED { 617 class CallInterceptorCompiler BASE_EMBEDDED {
596 public: 618 public:
597 CallInterceptorCompiler(StubCompiler* stub_compiler, 619 CallInterceptorCompiler(StubCompiler* stub_compiler,
598 const ParameterCount& arguments, 620 const ParameterCount& arguments,
599 Register name) 621 Register name)
600 : stub_compiler_(stub_compiler), 622 : stub_compiler_(stub_compiler),
601 arguments_(arguments), 623 arguments_(arguments),
602 name_(name) {} 624 name_(name) {}
603 625
604 void Compile(MacroAssembler* masm, 626 bool Compile(MacroAssembler* masm,
605 JSObject* object, 627 JSObject* object,
606 JSObject* holder, 628 JSObject* holder,
607 String* name, 629 String* name,
608 LookupResult* lookup, 630 LookupResult* lookup,
609 Register receiver, 631 Register receiver,
610 Register scratch1, 632 Register scratch1,
611 Register scratch2, 633 Register scratch2,
612 Register scratch3, 634 Register scratch3,
613 Label* miss) { 635 Label* miss,
636 Failure** failure) {
614 ASSERT(holder->HasNamedInterceptor()); 637 ASSERT(holder->HasNamedInterceptor());
615 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 638 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
616 639
617 // Check that the receiver isn't a smi. 640 // Check that the receiver isn't a smi.
618 __ JumpIfSmi(receiver, miss); 641 __ JumpIfSmi(receiver, miss);
619 642
620 CallOptimization optimization(lookup); 643 CallOptimization optimization(lookup);
621 644
622 if (optimization.is_constant_call()) { 645 if (optimization.is_constant_call()) {
623 CompileCacheable(masm, 646 return CompileCacheable(masm,
624 object, 647 object,
625 receiver, 648 receiver,
626 scratch1, 649 scratch1,
627 scratch2, 650 scratch2,
628 scratch3, 651 scratch3,
629 holder, 652 holder,
630 lookup, 653 lookup,
631 name, 654 name,
632 optimization, 655 optimization,
633 miss); 656 miss,
657 failure);
634 } else { 658 } else {
635 CompileRegular(masm, 659 CompileRegular(masm,
636 object, 660 object,
637 receiver, 661 receiver,
638 scratch1, 662 scratch1,
639 scratch2, 663 scratch2,
640 scratch3, 664 scratch3,
641 name, 665 name,
642 holder, 666 holder,
643 miss); 667 miss);
668 return true;
644 } 669 }
645 } 670 }
646 671
647 private: 672 private:
648 void CompileCacheable(MacroAssembler* masm, 673 bool CompileCacheable(MacroAssembler* masm,
649 JSObject* object, 674 JSObject* object,
650 Register receiver, 675 Register receiver,
651 Register scratch1, 676 Register scratch1,
652 Register scratch2, 677 Register scratch2,
653 Register scratch3, 678 Register scratch3,
654 JSObject* interceptor_holder, 679 JSObject* interceptor_holder,
655 LookupResult* lookup, 680 LookupResult* lookup,
656 String* name, 681 String* name,
657 const CallOptimization& optimization, 682 const CallOptimization& optimization,
658 Label* miss_label) { 683 Label* miss_label,
684 Failure** failure) {
659 ASSERT(optimization.is_constant_call()); 685 ASSERT(optimization.is_constant_call());
660 ASSERT(!lookup->holder()->IsGlobalObject()); 686 ASSERT(!lookup->holder()->IsGlobalObject());
661 687
662 int depth1 = kInvalidProtoDepth; 688 int depth1 = kInvalidProtoDepth;
663 int depth2 = kInvalidProtoDepth; 689 int depth2 = kInvalidProtoDepth;
664 bool can_do_fast_api_call = false; 690 bool can_do_fast_api_call = false;
665 if (optimization.is_simple_api_call() && 691 if (optimization.is_simple_api_call() &&
666 !lookup->holder()->IsGlobalObject()) { 692 !lookup->holder()->IsGlobalObject()) {
667 depth1 = 693 depth1 =
668 optimization.GetPrototypeDepthOfExpectedType(object, 694 optimization.GetPrototypeDepthOfExpectedType(object,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 } else { 736 } else {
711 // CheckPrototypes has a side effect of fetching a 'holder' 737 // CheckPrototypes has a side effect of fetching a 'holder'
712 // for API (object which is instanceof for the signature). It's 738 // for API (object which is instanceof for the signature). It's
713 // safe to omit it here, as if present, it should be fetched 739 // safe to omit it here, as if present, it should be fetched
714 // by the previous CheckPrototypes. 740 // by the previous CheckPrototypes.
715 ASSERT(depth2 == kInvalidProtoDepth); 741 ASSERT(depth2 == kInvalidProtoDepth);
716 } 742 }
717 743
718 // Invoke function. 744 // Invoke function.
719 if (can_do_fast_api_call) { 745 if (can_do_fast_api_call) {
720 GenerateFastApiCall(masm, optimization, arguments_.immediate()); 746 bool success = GenerateFastApiCall(masm,
747 optimization,
748 arguments_.immediate(),
749 failure);
750 if (!success) {
751 return false;
752 }
721 } else { 753 } else {
722 __ InvokeFunction(optimization.constant_function(), arguments_, 754 __ InvokeFunction(optimization.constant_function(), arguments_,
723 JUMP_FUNCTION); 755 JUMP_FUNCTION);
724 } 756 }
725 757
726 // Deferred code for fast API call case---clean preallocated space. 758 // Deferred code for fast API call case---clean preallocated space.
727 if (can_do_fast_api_call) { 759 if (can_do_fast_api_call) {
728 __ bind(&miss_cleanup); 760 __ bind(&miss_cleanup);
729 FreeSpaceForFastApiCall(masm, scratch1); 761 FreeSpaceForFastApiCall(masm, scratch1);
730 __ jmp(miss_label); 762 __ jmp(miss_label);
731 } 763 }
732 764
733 // Invoke a regular function. 765 // Invoke a regular function.
734 __ bind(&regular_invoke); 766 __ bind(&regular_invoke);
735 if (can_do_fast_api_call) { 767 if (can_do_fast_api_call) {
736 FreeSpaceForFastApiCall(masm, scratch1); 768 FreeSpaceForFastApiCall(masm, scratch1);
737 } 769 }
770
771 return true;
738 } 772 }
739 773
740 void CompileRegular(MacroAssembler* masm, 774 void CompileRegular(MacroAssembler* masm,
741 JSObject* object, 775 JSObject* object,
742 Register receiver, 776 Register receiver,
743 Register scratch1, 777 Register scratch1,
744 Register scratch2, 778 Register scratch2,
745 Register scratch3, 779 Register scratch3,
746 String* name, 780 String* name,
747 JSObject* interceptor_holder, 781 JSObject* interceptor_holder,
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
1029 rbx, rdx, rdi, name, &miss); 1063 rbx, rdx, rdi, name, &miss);
1030 } 1064 }
1031 break; 1065 break;
1032 } 1066 }
1033 1067
1034 default: 1068 default:
1035 UNREACHABLE(); 1069 UNREACHABLE();
1036 } 1070 }
1037 1071
1038 if (depth != kInvalidProtoDepth) { 1072 if (depth != kInvalidProtoDepth) {
1039 GenerateFastApiCall(masm(), optimization, argc); 1073 Failure* failure;
1074 bool success = GenerateFastApiCall(masm(), optimization, argc, &failure);
1075 if (!success) {
1076 return failure;
1077 }
1040 } else { 1078 } else {
1041 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 1079 __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
1042 } 1080 }
1043 1081
1044 // Handle call cache miss. 1082 // Handle call cache miss.
1045 __ bind(&miss); 1083 __ bind(&miss);
1046 if (depth != kInvalidProtoDepth) { 1084 if (depth != kInvalidProtoDepth) {
1047 FreeSpaceForFastApiCall(masm(), rax); 1085 FreeSpaceForFastApiCall(masm(), rax);
1048 } 1086 }
1049 1087
(...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after
1716 // Get the number of arguments. 1754 // Get the number of arguments.
1717 const int argc = arguments().immediate(); 1755 const int argc = arguments().immediate();
1718 1756
1719 LookupResult lookup; 1757 LookupResult lookup;
1720 LookupPostInterceptor(holder, name, &lookup); 1758 LookupPostInterceptor(holder, name, &lookup);
1721 1759
1722 // Get the receiver from the stack. 1760 // Get the receiver from the stack.
1723 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1761 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1724 1762
1725 CallInterceptorCompiler compiler(this, arguments(), rcx); 1763 CallInterceptorCompiler compiler(this, arguments(), rcx);
1726 compiler.Compile(masm(), 1764 Failure* failure;
1727 object, 1765 bool success = compiler.Compile(masm(),
1728 holder, 1766 object,
1729 name, 1767 holder,
1730 &lookup, 1768 name,
1731 rdx, 1769 &lookup,
1732 rbx, 1770 rdx,
1733 rdi, 1771 rbx,
1734 rax, 1772 rdi,
1735 &miss); 1773 rax,
1774 &miss,
1775 &failure);
1776 if (!success) {
1777 return failure;
1778 }
1736 1779
1737 // Restore receiver. 1780 // Restore receiver.
1738 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1781 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1739 1782
1740 // Check that the function really is a function. 1783 // Check that the function really is a function.
1741 __ JumpIfSmi(rax, &miss); 1784 __ JumpIfSmi(rax, &miss);
1742 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 1785 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
1743 __ j(not_equal, &miss); 1786 __ j(not_equal, &miss);
1744 1787
1745 // Patch the receiver on the stack with the global proxy if 1788 // Patch the receiver on the stack with the global proxy if
(...skipping 1217 matching lines...) Expand 10 before | Expand all | Expand 10 after
2963 // Return the generated code. 3006 // Return the generated code.
2964 return GetCode(); 3007 return GetCode();
2965 } 3008 }
2966 3009
2967 3010
2968 #undef __ 3011 #undef __
2969 3012
2970 } } // namespace v8::internal 3013 } } // namespace v8::internal
2971 3014
2972 #endif // V8_TARGET_ARCH_X64 3015 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/macro-assembler-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698