OLD | NEW |
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 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 void CompileCacheable(MacroAssembler* masm, | 428 void CompileCacheable(MacroAssembler* masm, |
429 StubCompiler* stub_compiler, | 429 StubCompiler* stub_compiler, |
430 Register receiver, | 430 Register receiver, |
431 Register holder, | 431 Register holder, |
432 Register scratch1, | 432 Register scratch1, |
433 Register scratch2, | 433 Register scratch2, |
434 JSObject* holder_obj, | 434 JSObject* holder_obj, |
435 LookupResult* lookup, | 435 LookupResult* lookup, |
436 String* name, | 436 String* name, |
437 Label* miss_label) { | 437 Label* miss_label) { |
438 AccessorInfo* callback = 0; | 438 AccessorInfo* callback = NULL; |
439 bool optimize = false; | 439 bool optimize = false; |
440 // So far the most popular follow ups for interceptor loads are FIELD | 440 // So far the most popular follow ups for interceptor loads are FIELD |
441 // and CALLBACKS, so inline only them, other cases may be added | 441 // and CALLBACKS, so inline only them, other cases may be added |
442 // later. | 442 // later. |
443 if (lookup->type() == FIELD) { | 443 if (lookup->type() == FIELD) { |
444 optimize = true; | 444 optimize = true; |
445 } else if (lookup->type() == CALLBACKS) { | 445 } else if (lookup->type() == CALLBACKS) { |
446 Object* callback_object = lookup->GetCallbackObject(); | 446 Object* callback_object = lookup->GetCallbackObject(); |
447 if (callback_object->IsAccessorInfo()) { | 447 if (callback_object->IsAccessorInfo()) { |
448 callback = AccessorInfo::cast(callback_object); | 448 callback = AccessorInfo::cast(callback_object); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
552 } | 552 } |
553 | 553 |
554 private: | 554 private: |
555 Register name_; | 555 Register name_; |
556 }; | 556 }; |
557 | 557 |
558 | 558 |
559 class CallInterceptorCompiler BASE_EMBEDDED { | 559 class CallInterceptorCompiler BASE_EMBEDDED { |
560 public: | 560 public: |
561 CallInterceptorCompiler(const ParameterCount& arguments, Register name) | 561 CallInterceptorCompiler(const ParameterCount& arguments, Register name) |
562 : arguments_(arguments), argc_(arguments.immediate()), name_(name) {} | 562 : arguments_(arguments), name_(name) {} |
563 | 563 |
564 void CompileCacheable(MacroAssembler* masm, | 564 void CompileCacheable(MacroAssembler* masm, |
565 StubCompiler* stub_compiler, | 565 StubCompiler* stub_compiler, |
566 Register receiver, | 566 Register receiver, |
567 Register holder, | 567 Register holder, |
568 Register scratch1, | 568 Register scratch1, |
569 Register scratch2, | 569 Register scratch2, |
570 JSObject* holder_obj, | 570 JSObject* holder_obj, |
571 LookupResult* lookup, | 571 LookupResult* lookup, |
572 String* name, | 572 String* name, |
573 Label* miss_label) { | 573 Label* miss_label) { |
574 JSFunction* function = 0; | 574 JSFunction* function = 0; |
575 bool optimize = false; | 575 bool optimize = false; |
576 // So far the most popular case for failed interceptor is | 576 // So far the most popular case for failed interceptor is |
577 // CONSTANT_FUNCTION sitting below. | 577 // CONSTANT_FUNCTION sitting below. |
578 if (lookup->type() == CONSTANT_FUNCTION) { | 578 if (lookup->type() == CONSTANT_FUNCTION) { |
579 function = lookup->GetConstantFunction(); | 579 function = lookup->GetConstantFunction(); |
580 // JSArray holder is a special case for call constant function | 580 // JSArray holder is a special case for call constant function |
581 // (see the corresponding code). | 581 // (see the corresponding code). |
582 if (function->is_compiled() && !holder_obj->IsJSArray()) { | 582 if (function->is_compiled() && !holder_obj->IsJSArray()) { |
583 optimize = true; | 583 optimize = true; |
584 } | 584 } |
585 } | 585 } |
586 | 586 |
587 if (!optimize) { | 587 if (!optimize) { |
588 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); | 588 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); |
589 return; | 589 return; |
590 } | 590 } |
591 | 591 |
| 592 ASSERT(!lookup->holder()->IsGlobalObject()); |
| 593 |
592 __ EnterInternalFrame(); | 594 __ EnterInternalFrame(); |
593 __ push(holder); // Save the holder. | 595 __ push(holder); // Save the holder. |
594 __ push(name_); // Save the name. | 596 __ push(name_); // Save the name. |
595 | 597 |
596 CompileCallLoadPropertyWithInterceptor(masm, | 598 CompileCallLoadPropertyWithInterceptor(masm, |
597 receiver, | 599 receiver, |
598 holder, | 600 holder, |
599 name_, | 601 name_, |
600 holder_obj); | 602 holder_obj); |
601 | 603 |
602 __ pop(name_); // Restore the name. | 604 __ pop(name_); // Restore the name. |
603 __ pop(receiver); // Restore the holder. | 605 __ pop(receiver); // Restore the holder. |
604 __ LeaveInternalFrame(); | 606 __ LeaveInternalFrame(); |
605 | 607 |
606 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); | 608 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); |
607 Label invoke; | 609 Label invoke; |
608 __ j(not_equal, &invoke); | 610 __ j(not_equal, &invoke); |
609 | 611 |
610 stub_compiler->CheckPrototypes(holder_obj, receiver, | 612 stub_compiler->CheckPrototypes(holder_obj, receiver, |
611 lookup->holder(), scratch1, | 613 lookup->holder(), scratch1, |
612 scratch2, | 614 scratch2, |
613 name, | 615 name, |
614 miss_label); | 616 miss_label); |
615 if (lookup->holder()->IsGlobalObject()) { | |
616 __ movq(rdx, Operand(rsp, (argc_ + 1) * kPointerSize)); | |
617 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | |
618 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdx); | |
619 } | |
620 | 617 |
621 ASSERT(function->is_compiled()); | 618 __ InvokeFunction(function, arguments_); |
622 // Get the function and setup the context. | |
623 __ Move(rdi, Handle<JSFunction>(function)); | |
624 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | |
625 | |
626 // Jump to the cached code (tail call). | |
627 Handle<Code> code(function->code()); | |
628 ParameterCount expected(function->shared()->formal_parameter_count()); | |
629 __ InvokeCode(code, expected, arguments_, | |
630 RelocInfo::CODE_TARGET, JUMP_FUNCTION); | |
631 | 619 |
632 __ bind(&invoke); | 620 __ bind(&invoke); |
633 } | 621 } |
634 | 622 |
635 void CompileRegular(MacroAssembler* masm, | 623 void CompileRegular(MacroAssembler* masm, |
636 Register receiver, | 624 Register receiver, |
637 Register holder, | 625 Register holder, |
638 Register scratch, | 626 Register scratch, |
639 JSObject* holder_obj, | 627 JSObject* holder_obj, |
640 Label* miss_label) { | 628 Label* miss_label) { |
641 __ EnterInternalFrame(); | 629 __ EnterInternalFrame(); |
642 // Save the name_ register across the call. | 630 // Save the name_ register across the call. |
643 __ push(name_); | 631 __ push(name_); |
644 | 632 |
645 PushInterceptorArguments(masm, | 633 PushInterceptorArguments(masm, |
646 receiver, | 634 receiver, |
647 holder, | 635 holder, |
648 name_, | 636 name_, |
649 holder_obj); | 637 holder_obj); |
650 | 638 |
651 ExternalReference ref = ExternalReference( | 639 __ CallExternalReference( |
652 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)); | 640 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall)), |
653 __ movq(rax, Immediate(5)); | 641 5); |
654 __ movq(rbx, ref); | |
655 | |
656 CEntryStub stub(1); | |
657 __ CallStub(&stub); | |
658 | 642 |
659 __ pop(name_); | 643 __ pop(name_); |
660 __ LeaveInternalFrame(); | 644 __ LeaveInternalFrame(); |
661 } | 645 } |
662 | 646 |
663 private: | 647 private: |
664 const ParameterCount& arguments_; | 648 const ParameterCount& arguments_; |
665 int argc_; | |
666 Register name_; | 649 Register name_; |
667 }; | 650 }; |
668 | 651 |
669 | 652 |
670 #undef __ | 653 #undef __ |
671 | 654 |
672 #define __ ACCESS_MASM((masm())) | 655 #define __ ACCESS_MASM((masm())) |
673 | 656 |
674 | 657 |
675 Object* CallStubCompiler::CompileCallConstant(Object* object, | 658 Object* CallStubCompiler::CompileCallConstant(Object* object, |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
785 // Check that the object is in fast mode (not dictionary). | 768 // Check that the object is in fast mode (not dictionary). |
786 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), | 769 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), |
787 Factory::fixed_array_map()); | 770 Factory::fixed_array_map()); |
788 __ j(not_equal, &miss); | 771 __ j(not_equal, &miss); |
789 break; | 772 break; |
790 | 773 |
791 default: | 774 default: |
792 UNREACHABLE(); | 775 UNREACHABLE(); |
793 } | 776 } |
794 | 777 |
795 // Get the function and setup the context. | 778 __ InvokeFunction(function, arguments()); |
796 __ Move(rdi, Handle<JSFunction>(function)); | |
797 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | |
798 | |
799 // Jump to the cached code (tail call). | |
800 ASSERT(function->is_compiled()); | |
801 Handle<Code> code(function->code()); | |
802 ParameterCount expected(function->shared()->formal_parameter_count()); | |
803 __ InvokeCode(code, expected, arguments(), | |
804 RelocInfo::CODE_TARGET, JUMP_FUNCTION); | |
805 | 779 |
806 // Handle call cache miss. | 780 // Handle call cache miss. |
807 __ bind(&miss); | 781 __ bind(&miss); |
808 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); | 782 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); |
809 __ Jump(ic, RelocInfo::CODE_TARGET); | 783 __ Jump(ic, RelocInfo::CODE_TARGET); |
810 | 784 |
811 // Return the generated code. | 785 // Return the generated code. |
812 String* function_name = NULL; | 786 String* function_name = NULL; |
813 if (function->shared()->name()->IsString()) { | 787 if (function->shared()->name()->IsString()) { |
814 function_name = String::cast(function->shared()->name()); | 788 function_name = String::cast(function->shared()->name()); |
(...skipping 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1882 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | 1856 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); |
1883 | 1857 |
1884 // Return the generated code. | 1858 // Return the generated code. |
1885 return GetCode(); | 1859 return GetCode(); |
1886 } | 1860 } |
1887 | 1861 |
1888 | 1862 |
1889 #undef __ | 1863 #undef __ |
1890 | 1864 |
1891 } } // namespace v8::internal | 1865 } } // namespace v8::internal |
OLD | NEW |