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

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

Issue 5108003: API call code refactoring (x64). (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 482 matching lines...) Expand 10 before | Expand all | Expand 10 after
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. 500 // Number of pointers to be reserved on stack for fast API call.
501 static const int kFastApiCallArguments = 3; 501 static const int kFastApiCallArguments = 3;
502 502
503 // Reserves space for the extra arguments to FastHandleApiCall in the 503 // Reserves space for the extra arguments to API function in the
504 // caller's frame. 504 // caller's frame.
505 // 505 //
506 // These arguments are set by CheckPrototypes and GenerateFastApiCall. 506 // These arguments are set by CheckPrototypes and GenerateFastApiCall.
507 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 507 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
508 // ----------- S t a t e ------------- 508 // ----------- S t a t e -------------
509 // -- rsp[0] : return address 509 // -- rsp[0] : return address
510 // -- rsp[8] : last argument in the internal frame of the caller 510 // -- rsp[8] : last argument in the internal frame of the caller
511 // ----------------------------------- 511 // -----------------------------------
512 __ movq(scratch, Operand(rsp, 0)); 512 __ movq(scratch, Operand(rsp, 0));
513 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); 513 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
(...skipping 14 matching lines...) Expand all
528 // -- rsp[kFastApiCallArguments * 8] : first fast api call extra argument. 528 // -- rsp[kFastApiCallArguments * 8] : first fast api call extra argument.
529 // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal 529 // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal
530 // frame. 530 // frame.
531 // ----------------------------------- 531 // -----------------------------------
532 __ movq(scratch, Operand(rsp, 0)); 532 __ movq(scratch, Operand(rsp, 0));
533 __ movq(Operand(rsp, kFastApiCallArguments * kPointerSize), scratch); 533 __ movq(Operand(rsp, kFastApiCallArguments * kPointerSize), scratch);
534 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments)); 534 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments));
535 } 535 }
536 536
537 537
538 // Generates call to FastHandleApiCall builtin. 538 // Generates call to API function.
539 static bool GenerateFastApiCall(MacroAssembler* masm, 539 static bool GenerateFastApiCall(MacroAssembler* masm,
540 const CallOptimization& optimization, 540 const CallOptimization& optimization,
541 int argc, 541 int argc,
542 Failure** failure) { 542 Failure** failure) {
543 // ----------- S t a t e ------------- 543 // ----------- S t a t e -------------
544 // -- rsp[0] : return address 544 // -- rsp[0] : return address
545 // -- rsp[8] : object passing the type check 545 // -- rsp[8] : object passing the type check
546 // (last fast api call extra argument, 546 // (last fast api call extra argument,
547 // set by CheckPrototypes) 547 // set by CheckPrototypes)
548 // -- rsp[16] : api function 548 // -- rsp[16] : api function
549 // (first fast api call extra argument) 549 // (first fast api call extra argument)
550 // -- rsp[24] : api call data 550 // -- rsp[24] : api call data
551 // -- rsp[32] : last argument 551 // -- rsp[32] : last argument
552 // -- ... 552 // -- ...
553 // -- rsp[(argc + 3) * 8] : first argument 553 // -- rsp[(argc + 3) * 8] : first argument
554 // -- rsp[(argc + 4) * 8] : receiver 554 // -- rsp[(argc + 4) * 8] : receiver
555 // ----------------------------------- 555 // -----------------------------------
556 556
557 // Get the function and setup the context. 557 // Get the function and setup the context.
558 JSFunction* function = optimization.constant_function(); 558 JSFunction* function = optimization.constant_function();
559 __ Move(rdi, Handle<JSFunction>(function)); 559 __ Move(rdi, Handle<JSFunction>(function));
560 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 560 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
561 561
562 // Pass the additional arguments FastHandleApiCall expects. 562 // Pass the additional arguments.
563 __ movq(Operand(rsp, 2 * kPointerSize), rdi); 563 __ movq(Operand(rsp, 2 * kPointerSize), rdi);
564 Object* call_data = optimization.api_call_info()->data(); 564 Object* call_data = optimization.api_call_info()->data();
565 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); 565 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info());
566 if (Heap::InNewSpace(call_data)) { 566 if (Heap::InNewSpace(call_data)) {
567 __ Move(rcx, api_call_info_handle); 567 __ Move(rcx, api_call_info_handle);
568 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); 568 __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
569 __ movq(Operand(rsp, 3 * kPointerSize), rbx); 569 __ movq(Operand(rsp, 3 * kPointerSize), rbx);
570 } else { 570 } else {
571 __ Move(Operand(rsp, 3 * kPointerSize), Handle<Object>(call_data)); 571 __ Move(Operand(rsp, 3 * kPointerSize), Handle<Object>(call_data));
572 } 572 }
573 573
574 // Prepare arguments. 574 // Prepare arguments.
575 __ lea(rbx, Operand(rsp, 3 * kPointerSize)); 575 __ lea(rbx, Operand(rsp, 3 * kPointerSize));
576 576
577 Object* callback = optimization.api_call_info()->callback(); 577 Object* callback = optimization.api_call_info()->callback();
578 Address api_function_address = v8::ToCData<Address>(callback); 578 Address api_function_address = v8::ToCData<Address>(callback);
579 ApiFunction fun(api_function_address); 579 ApiFunction fun(api_function_address);
580 580
581 #ifdef _WIN64 581 #ifdef _WIN64
582 // Win64 uses first register--rcx--for returned value. 582 // Win64 uses first register--rcx--for returned value.
583 Register arguments_arg = rdx; 583 Register arguments_arg = rdx;
584 #else 584 #else
585 Register arguments_arg = rdi; 585 Register arguments_arg = rdi;
586 #endif 586 #endif
587 587
588 // Allocate the v8::Arguments structure in the arguments' space since 588 // Allocate the v8::Arguments structure in the arguments' space since
589 // it's not controlled by GC. 589 // it's not controlled by GC.
590 const int kApiStackSpace = 4; 590 const int kApiStackSpace = 4;
591 591
592 __ PrepareCallApiFunction(argc + kFastApiCallArguments + 1, kApiStackSpace); 592 __ PrepareCallApiFunction(kApiStackSpace);
593 593
594 __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_. 594 __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_.
595 __ addq(rbx, Immediate(argc * kPointerSize)); 595 __ addq(rbx, Immediate(argc * kPointerSize));
596 __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_. 596 __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_.
597 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_. 597 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_.
598 // v8::Arguments::is_construct_call_. 598 // v8::Arguments::is_construct_call_.
599 __ Set(StackSpaceOperand(3), 0); 599 __ Set(StackSpaceOperand(3), 0);
600 600
601 // v8::InvocationCallback's argument. 601 // v8::InvocationCallback's argument.
602 __ lea(arguments_arg, StackSpaceOperand(0)); 602 __ lea(arguments_arg, StackSpaceOperand(0));
603 // Emitting a stub call may try to allocate (if the code is not 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 604 // already generated). Do not allow the assembler to perform a
605 // garbage collection but instead return the allocation failure 605 // garbage collection but instead return the allocation failure
606 // object. 606 // object.
607 MaybeObject* result = 607 MaybeObject* result =
608 masm->TryCallApiFunctionAndReturn(&fun); 608 masm->TryCallApiFunctionAndReturn(&fun, argc + kFastApiCallArguments + 1);
609 if (result->IsFailure()) { 609 if (result->IsFailure()) {
610 *failure = Failure::cast(result); 610 *failure = Failure::cast(result);
611 return false; 611 return false;
612 } 612 }
613 return true; 613 return true;
614 } 614 }
615 615
616 616
617 class CallInterceptorCompiler BASE_EMBEDDED { 617 class CallInterceptorCompiler BASE_EMBEDDED {
618 public: 618 public:
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 case RECEIVER_MAP_CHECK: 985 case RECEIVER_MAP_CHECK:
986 __ IncrementCounter(&Counters::call_const, 1); 986 __ IncrementCounter(&Counters::call_const, 1);
987 987
988 if (optimization.is_simple_api_call() && !object->IsGlobalObject()) { 988 if (optimization.is_simple_api_call() && !object->IsGlobalObject()) {
989 depth = optimization.GetPrototypeDepthOfExpectedType( 989 depth = optimization.GetPrototypeDepthOfExpectedType(
990 JSObject::cast(object), holder); 990 JSObject::cast(object), holder);
991 } 991 }
992 992
993 if (depth != kInvalidProtoDepth) { 993 if (depth != kInvalidProtoDepth) {
994 __ IncrementCounter(&Counters::call_const_fast_api, 1); 994 __ IncrementCounter(&Counters::call_const_fast_api, 1);
995 ReserveSpaceForFastApiCall(masm(), rax); 995 // Allocate space for v8::Arguments implicit values. Must be initialized
996 // before to call any runtime function.
997 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
996 } 998 }
997 999
998 // Check that the maps haven't changed. 1000 // Check that the maps haven't changed.
999 CheckPrototypes(JSObject::cast(object), rdx, holder, 1001 CheckPrototypes(JSObject::cast(object), rdx, holder,
1000 rbx, rax, rdi, name, depth, &miss); 1002 rbx, rax, rdi, name, depth, &miss);
1001 1003
1002 // Patch the receiver on the stack with the global proxy if 1004 // Patch the receiver on the stack with the global proxy if
1003 // necessary. 1005 // necessary.
1004 if (object->IsGlobalObject()) { 1006 if (object->IsGlobalObject()) {
1005 ASSERT(depth == kInvalidProtoDepth); 1007 ASSERT(depth == kInvalidProtoDepth);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1064 } 1066 }
1065 break; 1067 break;
1066 } 1068 }
1067 1069
1068 default: 1070 default:
1069 UNREACHABLE(); 1071 UNREACHABLE();
1070 } 1072 }
1071 1073
1072 if (depth != kInvalidProtoDepth) { 1074 if (depth != kInvalidProtoDepth) {
1073 Failure* failure; 1075 Failure* failure;
1076 // Move the return address on top of the stack.
1077 __ movq(rax, Operand(rsp, 3 * kPointerSize));
1078 __ movq(Operand(rsp, 0 * kPointerSize), rax);
1079
1080 // rsp[2 * kPointerSize] is uninitialized, rsp[3 * kPointerSize] contains
1081 // duplicate of return address and will be overwritten.
1074 bool success = GenerateFastApiCall(masm(), optimization, argc, &failure); 1082 bool success = GenerateFastApiCall(masm(), optimization, argc, &failure);
1075 if (!success) { 1083 if (!success) {
1076 return failure; 1084 return failure;
1077 } 1085 }
1078 } else { 1086 } else {
1079 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 1087 __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
1080 } 1088 }
1081 1089
1082 // Handle call cache miss. 1090 // Handle call cache miss.
1083 __ bind(&miss); 1091 __ bind(&miss);
1084 if (depth != kInvalidProtoDepth) { 1092 if (depth != kInvalidProtoDepth) {
1085 FreeSpaceForFastApiCall(masm(), rax); 1093 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
1086 } 1094 }
1087 1095
1088 // Handle call cache miss. 1096 // Handle call cache miss.
1089 __ bind(&miss_in_smi_check); 1097 __ bind(&miss_in_smi_check);
1090 Object* obj; 1098 Object* obj;
1091 { MaybeObject* maybe_obj = GenerateMissBranch(); 1099 { MaybeObject* maybe_obj = GenerateMissBranch();
1092 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 1100 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1093 } 1101 }
1094 1102
1095 // Return the generated code. 1103 // Return the generated code.
(...skipping 1530 matching lines...) Expand 10 before | Expand all | Expand 10 after
2626 CheckPrototypes(object, receiver, holder, scratch1, 2634 CheckPrototypes(object, receiver, holder, scratch1,
2627 scratch2, scratch3, name, miss); 2635 scratch2, scratch3, name, miss);
2628 2636
2629 Handle<AccessorInfo> callback_handle(callback); 2637 Handle<AccessorInfo> callback_handle(callback);
2630 2638
2631 // Insert additional parameters into the stack frame above return address. 2639 // Insert additional parameters into the stack frame above return address.
2632 ASSERT(!scratch2.is(reg)); 2640 ASSERT(!scratch2.is(reg));
2633 __ pop(scratch2); // Get return address to place it below. 2641 __ pop(scratch2); // Get return address to place it below.
2634 2642
2635 __ push(receiver); // receiver 2643 __ push(receiver); // receiver
2636 ASSERT(!scratch3.is(reg));
2637 __ movq(scratch3, rsp);
2638 __ push(reg); // holder 2644 __ push(reg); // holder
2639 if (Heap::InNewSpace(callback_handle->data())) { 2645 if (Heap::InNewSpace(callback_handle->data())) {
2640 __ Move(scratch1, callback_handle); 2646 __ Move(scratch1, callback_handle);
2641 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); // data 2647 __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); // data
2642 } else { 2648 } else {
2643 __ Push(Handle<Object>(callback_handle->data())); 2649 __ Push(Handle<Object>(callback_handle->data()));
2644 } 2650 }
2645 __ push(scratch3);
2646 __ push(name_reg); // name 2651 __ push(name_reg); // name
2647 // Save a pointer to where we pushed the arguments pointer. 2652 // Save a pointer to where we pushed the arguments pointer.
2648 // This will be passed as the const AccessorInfo& to the C++ callback. 2653 // This will be passed as the const AccessorInfo& to the C++ callback.
2649 2654
2650 #ifdef _WIN64 2655 #ifdef _WIN64
2651 // Win64 uses first register--rcx--for returned value. 2656 // Win64 uses first register--rcx--for returned value.
2652 Register accessor_info_arg = r8; 2657 Register accessor_info_arg = r8;
2653 Register name_arg = rdx; 2658 Register name_arg = rdx;
2654 #else 2659 #else
2655 Register accessor_info_arg = rsi; 2660 Register accessor_info_arg = rsi;
2656 Register name_arg = rdi; 2661 Register name_arg = rdi;
2657 #endif 2662 #endif
2658 2663
2659 ASSERT(!name_arg.is(scratch2)); 2664 ASSERT(!name_arg.is(scratch2));
2660 __ movq(name_arg, rsp); 2665 __ movq(name_arg, rsp);
2661 __ push(scratch2); // Restore return address. 2666 __ push(scratch2); // Restore return address.
2662 2667
2663 // Do call through the api. 2668 // Do call through the api.
2664 Address getter_address = v8::ToCData<Address>(callback->getter()); 2669 Address getter_address = v8::ToCData<Address>(callback->getter());
2665 ApiFunction fun(getter_address); 2670 ApiFunction fun(getter_address);
2666 2671
2667 // 3 elements array for v8::Agruments::values_, handler for name and pointer 2672 // 3 elements array for v8::Agruments::values_ and handler for name.
2668 // to the values (it considered as smi in GC). 2673 const int kStackSpace = 4;
2669 const int kStackSpace = 5;
2670 const int kApiArgc = 2;
2671 2674
2672 __ PrepareCallApiFunction(kStackSpace, kApiArgc); 2675 // Allocate v8::AccessorInfo in non-GCed stack space.
2676 const int kArgStackSpace = 1;
2677
2678 __ PrepareCallApiFunction(kArgStackSpace);
2679 __ lea(rax, Operand(name_arg, 3 * kPointerSize));
2680
2681 // v8::AccessorInfo::args_.
2682 __ movq(StackSpaceOperand(0), rax);
2673 2683
2674 // The context register (rsi) has been saved in PrepareCallApiFunction and 2684 // The context register (rsi) has been saved in PrepareCallApiFunction and
2675 // could be used to pass arguments. 2685 // could be used to pass arguments.
2676 __ lea(accessor_info_arg, Operand(name_arg, 1 * kPointerSize)); 2686 __ lea(accessor_info_arg, StackSpaceOperand(0));
2677 2687
2678 // Emitting a stub call may try to allocate (if the code is not 2688 // Emitting a stub call may try to allocate (if the code is not
2679 // already generated). Do not allow the assembler to perform a 2689 // already generated). Do not allow the assembler to perform a
2680 // garbage collection but instead return the allocation failure 2690 // garbage collection but instead return the allocation failure
2681 // object. 2691 // object.
2682 MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun); 2692 MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace);
2683 if (result->IsFailure()) { 2693 if (result->IsFailure()) {
2684 *failure = Failure::cast(result); 2694 *failure = Failure::cast(result);
2685 return false; 2695 return false;
2686 } 2696 }
2687 return true; 2697 return true;
2688 } 2698 }
2689 2699
2690 2700
2691 Register StubCompiler::CheckPrototypes(JSObject* object, 2701 Register StubCompiler::CheckPrototypes(JSObject* object,
2692 Register object_reg, 2702 Register object_reg,
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
3006 // Return the generated code. 3016 // Return the generated code.
3007 return GetCode(); 3017 return GetCode();
3008 } 3018 }
3009 3019
3010 3020
3011 #undef __ 3021 #undef __
3012 3022
3013 } } // namespace v8::internal 3023 } } // namespace v8::internal
3014 3024
3015 #endif // V8_TARGET_ARCH_X64 3025 #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