Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |