| 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 |