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