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

Side by Side Diff: src/codegen-ia32.cc

Issue 16409: Inline array loads in loops directly in the code instead of always... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 12 years 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-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 3760 matching lines...) Expand 10 before | Expand all | Expand 10 after
3771 SmiComparison(cc, right->AsLiteral()->handle(), strict); 3771 SmiComparison(cc, right->AsLiteral()->handle(), strict);
3772 return; 3772 return;
3773 } 3773 }
3774 3774
3775 Load(left); 3775 Load(left);
3776 Load(right); 3776 Load(right);
3777 Comparison(cc, strict); 3777 Comparison(cc, strict);
3778 } 3778 }
3779 3779
3780 3780
3781 class DeferredReferenceGetKeyedValue: public DeferredCode {
3782 public:
3783 DeferredReferenceGetKeyedValue(CodeGenerator* generator, bool is_global)
3784 : DeferredCode(generator), is_global_(is_global) {
3785 set_comment("[ DeferredReferenceGetKeyedValue");
3786 }
3787
3788 virtual void Generate() {
3789 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
3790 // Calculate the delta from the IC call instruction to the map
3791 // check cmp instruction in the inlined version. This delta is
3792 // stored in a test(eax, delta) instruction after the call so that
3793 // we can find it in the IC initialization code and patch the cmp
3794 // instruction. This means that we cannot allow test instructions
3795 // after calls to KeyedLoadIC stubs in other places.
3796 int delta_to_patch_site = __ SizeOfCodeGeneratedSince(patch_site());
3797 if (is_global_) {
3798 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
3799 } else {
3800 __ call(ic, RelocInfo::CODE_TARGET);
3801 }
3802 __ test(eax, Immediate(-delta_to_patch_site));
3803 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1);
3804 }
3805
3806 Label* patch_site() { return &patch_site_; }
3807
3808 private:
3809 Label patch_site_;
3810 bool is_global_;
3811 };
3812
3813
3814
3781 #undef __ 3815 #undef __
3782 #define __ masm-> 3816 #define __ masm->
3783 3817
3784 Handle<String> Reference::GetName() { 3818 Handle<String> Reference::GetName() {
3785 ASSERT(type_ == NAMED); 3819 ASSERT(type_ == NAMED);
3786 Property* property = expression_->AsProperty(); 3820 Property* property = expression_->AsProperty();
3787 if (property == NULL) { 3821 if (property == NULL) {
3788 // Global variable reference treated as a named property reference. 3822 // Global variable reference treated as a named property reference.
3789 VariableProxy* proxy = expression_->AsVariableProxy(); 3823 VariableProxy* proxy = expression_->AsVariableProxy();
3790 ASSERT(proxy->AsVariable() != NULL); 3824 ASSERT(proxy->AsVariable() != NULL);
(...skipping 15 matching lines...) Expand all
3806 switch (type_) { 3840 switch (type_) {
3807 case SLOT: { 3841 case SLOT: {
3808 Comment cmnt(masm, "[ Load from Slot"); 3842 Comment cmnt(masm, "[ Load from Slot");
3809 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 3843 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
3810 ASSERT(slot != NULL); 3844 ASSERT(slot != NULL);
3811 cgen_->LoadFromSlot(slot, typeof_state); 3845 cgen_->LoadFromSlot(slot, typeof_state);
3812 break; 3846 break;
3813 } 3847 }
3814 3848
3815 case NAMED: { 3849 case NAMED: {
3816 // TODO(1241834): Make sure that this it is safe to ignore the 3850 // TODO(1241834): Make sure that it is safe to ignore the
3817 // distinction between expressions in a typeof and not in a typeof. If 3851 // distinction between expressions in a typeof and not in a
3818 // there is a chance that reference errors can be thrown below, we 3852 // typeof. If there is a chance that reference errors can be
3819 // must distinguish between the two kinds of loads (typeof expression 3853 // thrown below, we must distinguish between the two kinds of
3820 // loads must not throw a reference error). 3854 // loads (typeof expression loads must not throw a reference
3855 // error).
3821 Comment cmnt(masm, "[ Load from named Property"); 3856 Comment cmnt(masm, "[ Load from named Property");
3822 Handle<String> name(GetName()); 3857 Handle<String> name(GetName());
3858 Variable* var = expression_->AsVariableProxy()->AsVariable();
3823 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 3859 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
3824 // Setup the name register. 3860 // Setup the name register.
3825 __ mov(ecx, name); 3861 __ mov(ecx, name);
3826
3827 Variable* var = expression_->AsVariableProxy()->AsVariable();
3828 if (var != NULL) { 3862 if (var != NULL) {
3829 ASSERT(var->is_global()); 3863 ASSERT(var->is_global());
3830 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 3864 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
3831 } else { 3865 } else {
3832 __ call(ic, RelocInfo::CODE_TARGET); 3866 __ call(ic, RelocInfo::CODE_TARGET);
3833 } 3867 }
3834 frame->Push(eax); // IC call leaves result in eax, push it out 3868 // Push the result.
3869 frame->Push(eax);
3835 break; 3870 break;
3836 } 3871 }
3837 3872
3838 case KEYED: { 3873 case KEYED: {
3839 // TODO(1241834): Make sure that this it is safe to ignore the 3874 // TODO(1241834): Make sure that it is safe to ignore the
3840 // distinction between expressions in a typeof and not in a typeof. 3875 // distinction between expressions in a typeof and not in a
3841 Comment cmnt(masm, "[ Load from keyed Property"); 3876 // typeof.
3842 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
3843
3844 Variable* var = expression_->AsVariableProxy()->AsVariable(); 3877 Variable* var = expression_->AsVariableProxy()->AsVariable();
3845 if (var != NULL) { 3878 // Inline array load code if inside of a loop. We do not know
3846 ASSERT(var->is_global()); 3879 // the receiver map yet, so we initially generate the code with
3847 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 3880 // a check against an invalid map. In the inline cache code, we
3881 // patch the map check if appropriate.
3882 if (cgen_->loop_nesting() > 0) {
3883 Comment cmnt(masm, "[ Inlined array index load");
3884 DeferredReferenceGetKeyedValue* deferred =
3885 new DeferredReferenceGetKeyedValue(cgen_, var != NULL);
3886 // Load receiver and check that it is not a smi (only needed
3887 // if not contextual) and that it has the expected map.
iposva 2008/12/22 18:59:16 I think it would improve the readability if was cl
3888 __ mov(edx, Operand(esp, kPointerSize));
3889 if (var == NULL) {
3890 __ test(edx, Immediate(kSmiTagMask));
3891 __ j(zero, deferred->enter(), not_taken);
3892 }
3893 // Initially, use an invalid map. The map is patched in the IC
3894 // initialization code.
3895 __ bind(deferred->patch_site());
3896 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
3897 Immediate(Factory::null_value()));
3898 __ j(not_equal, deferred->enter(), not_taken);
3899 // Load key and check that it is a smi.
3900 __ mov(eax, Operand(esp, 0));
3901 __ test(eax, Immediate(kSmiTagMask));
3902 __ j(not_zero, deferred->enter(), not_taken);
3903 // Shift to get actual index value.
3904 __ sar(eax, kSmiTagSize);
Kasper Lund 2008/12/22 09:52:13 Maybe we should consider keeping the FixedArray le
Mads Ager (chromium) 2008/12/22 12:59:11 That would be an interesting experiment. I'll try
3905 // Get the elements array from the receiver and check that it
3906 // is not a dictionary.
3907 __ mov(edx, FieldOperand(edx, JSObject::kElementsOffset));
3908 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
3909 Immediate(Factory::hash_table_map()));
3910 __ j(equal, deferred->enter(), not_taken);
3911 // Check that key is within bounds.
3912 __ cmp(eax, FieldOperand(edx, Array::kLengthOffset));
3913 __ j(above_equal, deferred->enter(), not_taken);
3914 // Load and check that the result is not the hole.
3915 __ mov(eax,
3916 Operand(edx, eax, times_4, Array::kHeaderSize - kHeapObjectTag));
3917 __ cmp(Operand(eax), Immediate(Factory::the_hole_value()));
3918 __ j(equal, deferred->enter(), not_taken);
3919 __ IncrementCounter(&Counters::keyed_load_inline, 1);
3920 __ bind(deferred->exit());
3848 } else { 3921 } else {
3849 __ call(ic, RelocInfo::CODE_TARGET); 3922 Comment cmnt(masm, "[ Load from keyed Property");
3923 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
3924 if (var != NULL) {
3925 ASSERT(var->is_global());
3926 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
3927 } else {
3928 __ call(ic, RelocInfo::CODE_TARGET);
3929 }
3930 // Make sure that we do not have a test instruction after the
3931 // call. A test instruction after the call is used to
3932 // indicate that we have generated an inline version of the
3933 // keyed load.
3934 __ nop();
Kasper Lund 2008/12/22 09:52:13 I guess here the nop is really needed because the
Mads Ager (chromium) 2008/12/22 12:59:11 Yes, exactly. I'll update the comment to make it
iposva 2008/12/22 18:59:16 Alternatively you could bind a label after the pus
3850 } 3935 }
3851 frame->Push(eax); // IC call leaves result in eax, push it out 3936 // Push the result.
3937 frame->Push(eax);
3852 break; 3938 break;
3853 } 3939 }
3854 3940
3855 default: 3941 default:
3856 UNREACHABLE(); 3942 UNREACHABLE();
3857 } 3943 }
3858 } 3944 }
3859 3945
3860 3946
3861 void Reference::SetValue(InitState init_state) { 3947 void Reference::SetValue(InitState init_state) {
(...skipping 1326 matching lines...) Expand 10 before | Expand all | Expand 10 after
5188 5274
5189 // Slow-case: Go through the JavaScript implementation. 5275 // Slow-case: Go through the JavaScript implementation.
5190 __ bind(&slow); 5276 __ bind(&slow);
5191 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5277 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5192 } 5278 }
5193 5279
5194 5280
5195 #undef __ 5281 #undef __
5196 5282
5197 } } // namespace v8::internal 5283 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698