OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 if (info()->IsOptimizing()) { | 168 if (info()->IsOptimizing()) { |
169 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 169 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
170 | 170 |
171 #ifdef DEBUG | 171 #ifdef DEBUG |
172 if (strlen(FLAG_stop_at) > 0 && | 172 if (strlen(FLAG_stop_at) > 0 && |
173 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 173 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
174 __ int3(); | 174 __ int3(); |
175 } | 175 } |
176 #endif | 176 #endif |
177 | 177 |
178 // Strict mode functions and builtins need to replace the receiver | 178 // Classic mode functions and builtins need to replace the receiver with the |
179 // with undefined when called as functions (without an explicit | 179 // global proxy when called as functions (without an explicit receiver |
180 // receiver object). ecx is zero for method calls and non-zero for | 180 // object). |
181 // function calls. | 181 if (info_->this_has_uses() && |
182 if (!info_->is_classic_mode() || info_->is_native()) { | 182 info_->is_classic_mode() && |
| 183 !info_->is_native()) { |
183 Label ok; | 184 Label ok; |
184 __ test(ecx, Operand(ecx)); | 185 __ test(ecx, ecx); |
185 __ j(zero, &ok, Label::kNear); | 186 __ j(zero, &ok, Label::kNear); |
| 187 |
186 // +1 for return address. | 188 // +1 for return address. |
187 int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; | 189 int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; |
188 __ mov(Operand(esp, receiver_offset), | 190 __ mov(ecx, Operand(esp, receiver_offset)); |
189 Immediate(isolate()->factory()->undefined_value())); | 191 |
| 192 __ cmp(ecx, isolate()->factory()->undefined_value()); |
| 193 __ j(not_equal, &ok, Label::kNear); |
| 194 |
| 195 __ mov(ecx, GlobalObjectOperand()); |
| 196 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset)); |
| 197 |
| 198 __ mov(Operand(esp, receiver_offset), ecx); |
| 199 |
190 __ bind(&ok); | 200 __ bind(&ok); |
191 } | 201 } |
192 | 202 |
193 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { | 203 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { |
194 // Move state of dynamic frame alignment into edx. | 204 // Move state of dynamic frame alignment into edx. |
195 __ Set(edx, Immediate(kNoAlignmentPadding)); | 205 __ Set(edx, Immediate(kNoAlignmentPadding)); |
196 | 206 |
197 Label do_not_pad, align_loop; | 207 Label do_not_pad, align_loop; |
198 STATIC_ASSERT(kDoubleSize == 2 * kPointerSize); | 208 STATIC_ASSERT(kDoubleSize == 2 * kPointerSize); |
199 // Align esp + 4 to a multiple of 2 * kPointerSize. | 209 // Align esp + 4 to a multiple of 2 * kPointerSize. |
(...skipping 3434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3634 | 3644 |
3635 | 3645 |
3636 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { | 3646 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { |
3637 Register receiver = ToRegister(instr->receiver()); | 3647 Register receiver = ToRegister(instr->receiver()); |
3638 Register function = ToRegister(instr->function()); | 3648 Register function = ToRegister(instr->function()); |
3639 Register scratch = ToRegister(instr->temp()); | 3649 Register scratch = ToRegister(instr->temp()); |
3640 | 3650 |
3641 // If the receiver is null or undefined, we have to pass the global | 3651 // If the receiver is null or undefined, we have to pass the global |
3642 // object as a receiver to normal functions. Values have to be | 3652 // object as a receiver to normal functions. Values have to be |
3643 // passed unchanged to builtins and strict-mode functions. | 3653 // passed unchanged to builtins and strict-mode functions. |
3644 Label global_object, receiver_ok; | 3654 Label receiver_ok, global_object; |
3645 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; | 3655 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
3646 | 3656 |
3647 // Do not transform the receiver to object for strict mode | 3657 // Do not transform the receiver to object for strict mode |
3648 // functions. | 3658 // functions. |
3649 __ mov(scratch, | 3659 __ mov(scratch, |
3650 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 3660 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
3651 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset), | 3661 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset), |
3652 1 << SharedFunctionInfo::kStrictModeBitWithinByte); | 3662 1 << SharedFunctionInfo::kStrictModeBitWithinByte); |
3653 __ j(not_equal, &receiver_ok, dist); | 3663 __ j(not_equal, &receiver_ok, dist); |
3654 | 3664 |
3655 // Do not transform the receiver to object for builtins. | 3665 // Do not transform the receiver to object for builtins. |
3656 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset), | 3666 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset), |
3657 1 << SharedFunctionInfo::kNativeBitWithinByte); | 3667 1 << SharedFunctionInfo::kNativeBitWithinByte); |
3658 __ j(not_equal, &receiver_ok, dist); | 3668 __ j(not_equal, &receiver_ok, dist); |
3659 | 3669 |
3660 // Normal function. Replace undefined or null with global receiver. | 3670 // Normal function. Replace undefined or null with global receiver. |
3661 __ cmp(receiver, factory()->null_value()); | 3671 __ cmp(receiver, factory()->null_value()); |
3662 __ j(equal, &global_object, Label::kNear); | 3672 __ j(equal, &global_object, Label::kNear); |
3663 __ cmp(receiver, factory()->undefined_value()); | 3673 __ cmp(receiver, factory()->undefined_value()); |
3664 __ j(equal, &global_object, Label::kNear); | 3674 __ j(equal, &global_object, Label::kNear); |
3665 | 3675 |
3666 // The receiver should be a JS object. | 3676 // The receiver should be a JS object. |
3667 __ test(receiver, Immediate(kSmiTagMask)); | 3677 __ test(receiver, Immediate(kSmiTagMask)); |
3668 DeoptimizeIf(equal, instr->environment()); | 3678 DeoptimizeIf(equal, instr->environment()); |
3669 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); | 3679 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); |
3670 DeoptimizeIf(below, instr->environment()); | 3680 DeoptimizeIf(below, instr->environment()); |
3671 __ jmp(&receiver_ok, Label::kNear); | 3681 __ jmp(&receiver_ok, Label::kNear); |
3672 | 3682 |
3673 __ bind(&global_object); | 3683 __ bind(&global_object); |
3674 // TODO(kmillikin): We have a hydrogen value for the global object. See | 3684 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); |
3675 // if it's better to use it than to explicitly fetch it from the context | 3685 __ mov(receiver, |
3676 // here. | 3686 Operand(receiver, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
3677 CallStubCompiler::FetchGlobalProxy(masm(), receiver, function); | 3687 __ mov(receiver, FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset)); |
| 3688 |
3678 __ bind(&receiver_ok); | 3689 __ bind(&receiver_ok); |
3679 } | 3690 } |
3680 | 3691 |
3681 | 3692 |
3682 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 3693 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
3683 Register receiver = ToRegister(instr->receiver()); | 3694 Register receiver = ToRegister(instr->receiver()); |
3684 Register function = ToRegister(instr->function()); | 3695 Register function = ToRegister(instr->function()); |
3685 Register length = ToRegister(instr->length()); | 3696 Register length = ToRegister(instr->length()); |
3686 Register elements = ToRegister(instr->elements()); | 3697 Register elements = ToRegister(instr->elements()); |
3687 ASSERT(receiver.is(eax)); // Used for parameter count. | 3698 ASSERT(receiver.is(eax)); // Used for parameter count. |
(...skipping 21 matching lines...) Expand all Loading... |
3709 __ j(not_zero, &loop); | 3720 __ j(not_zero, &loop); |
3710 | 3721 |
3711 // Invoke the function. | 3722 // Invoke the function. |
3712 __ bind(&invoke); | 3723 __ bind(&invoke); |
3713 ASSERT(instr->HasPointerMap()); | 3724 ASSERT(instr->HasPointerMap()); |
3714 LPointerMap* pointers = instr->pointer_map(); | 3725 LPointerMap* pointers = instr->pointer_map(); |
3715 SafepointGenerator safepoint_generator( | 3726 SafepointGenerator safepoint_generator( |
3716 this, pointers, Safepoint::kLazyDeopt); | 3727 this, pointers, Safepoint::kLazyDeopt); |
3717 ParameterCount actual(eax); | 3728 ParameterCount actual(eax); |
3718 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3729 __ InvokeFunction(function, actual, CALL_FUNCTION, |
3719 safepoint_generator, CALL_AS_METHOD); | 3730 safepoint_generator, CALL_AS_FUNCTION); |
3720 } | 3731 } |
3721 | 3732 |
3722 | 3733 |
3723 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 3734 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
3724 __ int3(); | 3735 __ int3(); |
3725 } | 3736 } |
3726 | 3737 |
3727 | 3738 |
3728 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3739 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
3729 LOperand* argument = instr->value(); | 3740 LOperand* argument = instr->value(); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3830 } | 3841 } |
3831 } | 3842 } |
3832 | 3843 |
3833 | 3844 |
3834 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 3845 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
3835 ASSERT(ToRegister(instr->result()).is(eax)); | 3846 ASSERT(ToRegister(instr->result()).is(eax)); |
3836 CallKnownFunction(instr->hydrogen()->function(), | 3847 CallKnownFunction(instr->hydrogen()->function(), |
3837 instr->hydrogen()->formal_parameter_count(), | 3848 instr->hydrogen()->formal_parameter_count(), |
3838 instr->arity(), | 3849 instr->arity(), |
3839 instr, | 3850 instr, |
3840 CALL_AS_METHOD, | 3851 CALL_AS_FUNCTION, |
3841 EDI_UNINITIALIZED); | 3852 EDI_UNINITIALIZED); |
3842 } | 3853 } |
3843 | 3854 |
3844 | 3855 |
3845 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3856 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
3846 Register input_reg = ToRegister(instr->value()); | 3857 Register input_reg = ToRegister(instr->value()); |
3847 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 3858 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
3848 factory()->heap_number_map()); | 3859 factory()->heap_number_map()); |
3849 DeoptimizeIf(not_equal, instr->environment()); | 3860 DeoptimizeIf(not_equal, instr->environment()); |
3850 | 3861 |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4191 ASSERT(ToRegister(instr->context()).is(esi)); | 4202 ASSERT(ToRegister(instr->context()).is(esi)); |
4192 ASSERT(ToRegister(instr->function()).is(edi)); | 4203 ASSERT(ToRegister(instr->function()).is(edi)); |
4193 ASSERT(instr->HasPointerMap()); | 4204 ASSERT(instr->HasPointerMap()); |
4194 | 4205 |
4195 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 4206 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
4196 if (known_function.is_null()) { | 4207 if (known_function.is_null()) { |
4197 LPointerMap* pointers = instr->pointer_map(); | 4208 LPointerMap* pointers = instr->pointer_map(); |
4198 SafepointGenerator generator( | 4209 SafepointGenerator generator( |
4199 this, pointers, Safepoint::kLazyDeopt); | 4210 this, pointers, Safepoint::kLazyDeopt); |
4200 ParameterCount count(instr->arity()); | 4211 ParameterCount count(instr->arity()); |
4201 __ InvokeFunction(edi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 4212 __ InvokeFunction(edi, count, CALL_FUNCTION, generator, CALL_AS_FUNCTION); |
4202 } else { | 4213 } else { |
4203 CallKnownFunction(known_function, | 4214 CallKnownFunction(known_function, |
4204 instr->hydrogen()->formal_parameter_count(), | 4215 instr->hydrogen()->formal_parameter_count(), |
4205 instr->arity(), | 4216 instr->arity(), |
4206 instr, | 4217 instr, |
4207 CALL_AS_METHOD, | 4218 CALL_AS_FUNCTION, |
4208 EDI_CONTAINS_TARGET); | 4219 EDI_CONTAINS_TARGET); |
4209 } | 4220 } |
4210 } | 4221 } |
4211 | 4222 |
4212 | 4223 |
4213 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 4224 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
4214 ASSERT(ToRegister(instr->context()).is(esi)); | 4225 ASSERT(ToRegister(instr->context()).is(esi)); |
4215 ASSERT(ToRegister(instr->key()).is(ecx)); | 4226 ASSERT(ToRegister(instr->key()).is(ecx)); |
4216 ASSERT(ToRegister(instr->result()).is(eax)); | 4227 ASSERT(ToRegister(instr->result()).is(eax)); |
4217 | 4228 |
(...skipping 15 matching lines...) Expand all Loading... |
4233 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4244 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
4234 } | 4245 } |
4235 | 4246 |
4236 | 4247 |
4237 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 4248 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
4238 ASSERT(ToRegister(instr->context()).is(esi)); | 4249 ASSERT(ToRegister(instr->context()).is(esi)); |
4239 ASSERT(ToRegister(instr->function()).is(edi)); | 4250 ASSERT(ToRegister(instr->function()).is(edi)); |
4240 ASSERT(ToRegister(instr->result()).is(eax)); | 4251 ASSERT(ToRegister(instr->result()).is(eax)); |
4241 | 4252 |
4242 int arity = instr->arity(); | 4253 int arity = instr->arity(); |
4243 CallFunctionFlags flags = | 4254 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
4244 instr->hydrogen()->IsContextualCall() ? | |
4245 RECEIVER_IS_IMPLICIT : NO_CALL_FUNCTION_FLAGS; | |
4246 CallFunctionStub stub(arity, flags); | |
4247 if (instr->hydrogen()->IsTailCall()) { | 4255 if (instr->hydrogen()->IsTailCall()) { |
4248 if (NeedsEagerFrame()) __ leave(); | 4256 if (NeedsEagerFrame()) __ leave(); |
4249 __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | 4257 __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
4250 } else { | 4258 } else { |
4251 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4259 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
4252 } | 4260 } |
4253 } | 4261 } |
4254 | 4262 |
4255 | 4263 |
4256 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 4264 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
(...skipping 2101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6358 FixedArray::kHeaderSize - kPointerSize)); | 6366 FixedArray::kHeaderSize - kPointerSize)); |
6359 __ bind(&done); | 6367 __ bind(&done); |
6360 } | 6368 } |
6361 | 6369 |
6362 | 6370 |
6363 #undef __ | 6371 #undef __ |
6364 | 6372 |
6365 } } // namespace v8::internal | 6373 } } // namespace v8::internal |
6366 | 6374 |
6367 #endif // V8_TARGET_ARCH_IA32 | 6375 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |