| 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 1408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1608 ASSERT(ToRegister(instr->left()).is(eax)); | 1618 ASSERT(ToRegister(instr->left()).is(eax)); |
| 1609 ASSERT(ToRegister(instr->result()).is(edx)); | 1619 ASSERT(ToRegister(instr->result()).is(edx)); |
| 1610 Register scratch = ToRegister(instr->temp()); | 1620 Register scratch = ToRegister(instr->temp()); |
| 1611 | 1621 |
| 1612 // Find b which: 2^b < divisor_abs < 2^(b+1). | 1622 // Find b which: 2^b < divisor_abs < 2^(b+1). |
| 1613 unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs); | 1623 unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs); |
| 1614 unsigned shift = 32 + b; // Precision +1bit (effectively). | 1624 unsigned shift = 32 + b; // Precision +1bit (effectively). |
| 1615 double multiplier_f = | 1625 double multiplier_f = |
| 1616 static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs; | 1626 static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs; |
| 1617 int64_t multiplier; | 1627 int64_t multiplier; |
| 1618 if (multiplier_f - floor(multiplier_f) < 0.5) { | 1628 if (multiplier_f - std::floor(multiplier_f) < 0.5) { |
| 1619 multiplier = static_cast<int64_t>(floor(multiplier_f)); | 1629 multiplier = static_cast<int64_t>(std::floor(multiplier_f)); |
| 1620 } else { | 1630 } else { |
| 1621 multiplier = static_cast<int64_t>(floor(multiplier_f)) + 1; | 1631 multiplier = static_cast<int64_t>(std::floor(multiplier_f)) + 1; |
| 1622 } | 1632 } |
| 1623 // The multiplier is a uint32. | 1633 // The multiplier is a uint32. |
| 1624 ASSERT(multiplier > 0 && | 1634 ASSERT(multiplier > 0 && |
| 1625 multiplier < (static_cast<int64_t>(1) << 32)); | 1635 multiplier < (static_cast<int64_t>(1) << 32)); |
| 1626 __ mov(scratch, dividend); | 1636 __ mov(scratch, dividend); |
| 1627 if (divisor < 0 && | 1637 if (divisor < 0 && |
| 1628 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1638 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1629 __ test(dividend, dividend); | 1639 __ test(dividend, dividend); |
| 1630 DeoptimizeIf(zero, instr->environment()); | 1640 DeoptimizeIf(zero, instr->environment()); |
| 1631 } | 1641 } |
| (...skipping 1525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3157 } | 3167 } |
| 3158 } | 3168 } |
| 3159 | 3169 |
| 3160 | 3170 |
| 3161 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { | 3171 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { |
| 3162 ASSERT(ToRegister(instr->context()).is(esi)); | 3172 ASSERT(ToRegister(instr->context()).is(esi)); |
| 3163 ASSERT(ToRegister(instr->global_object()).is(edx)); | 3173 ASSERT(ToRegister(instr->global_object()).is(edx)); |
| 3164 ASSERT(ToRegister(instr->result()).is(eax)); | 3174 ASSERT(ToRegister(instr->result()).is(eax)); |
| 3165 | 3175 |
| 3166 __ mov(ecx, instr->name()); | 3176 __ mov(ecx, instr->name()); |
| 3167 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : | 3177 ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL; |
| 3168 RelocInfo::CODE_TARGET_CONTEXT; | 3178 Handle<Code> ic = LoadIC::initialize_stub(isolate(), mode); |
| 3169 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 3179 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3170 CallCode(ic, mode, instr); | |
| 3171 } | 3180 } |
| 3172 | 3181 |
| 3173 | 3182 |
| 3174 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 3183 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
| 3175 Register value = ToRegister(instr->value()); | 3184 Register value = ToRegister(instr->value()); |
| 3176 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle(); | 3185 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle(); |
| 3177 | 3186 |
| 3178 // If the cell we are storing to contains the hole it could have | 3187 // If the cell we are storing to contains the hole it could have |
| 3179 // been deleted from the property dictionary. In that case, we need | 3188 // been deleted from the property dictionary. In that case, we need |
| 3180 // to update the property details in the property dictionary to mark | 3189 // to update the property details in the property dictionary to mark |
| 3181 // it as no longer deleted. We deoptimize in that case. | 3190 // it as no longer deleted. We deoptimize in that case. |
| 3182 if (instr->hydrogen()->RequiresHoleCheck()) { | 3191 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3183 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value()); | 3192 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value()); |
| 3184 DeoptimizeIf(equal, instr->environment()); | 3193 DeoptimizeIf(equal, instr->environment()); |
| 3185 } | 3194 } |
| 3186 | 3195 |
| 3187 // Store the value. | 3196 // Store the value. |
| 3188 __ mov(Operand::ForCell(cell_handle), value); | 3197 __ mov(Operand::ForCell(cell_handle), value); |
| 3189 // Cells are always rescanned, so no write barrier here. | 3198 // Cells are always rescanned, so no write barrier here. |
| 3190 } | 3199 } |
| 3191 | 3200 |
| 3192 | 3201 |
| 3193 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { | 3202 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { |
| 3194 ASSERT(ToRegister(instr->context()).is(esi)); | 3203 ASSERT(ToRegister(instr->context()).is(esi)); |
| 3195 ASSERT(ToRegister(instr->global_object()).is(edx)); | 3204 ASSERT(ToRegister(instr->global_object()).is(edx)); |
| 3196 ASSERT(ToRegister(instr->value()).is(eax)); | 3205 ASSERT(ToRegister(instr->value()).is(eax)); |
| 3197 | 3206 |
| 3198 __ mov(ecx, instr->name()); | 3207 __ mov(ecx, instr->name()); |
| 3199 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 3208 Handle<Code> ic = StoreIC::initialize_stub(isolate(), |
| 3200 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3209 instr->strict_mode_flag(), |
| 3201 : isolate()->builtins()->StoreIC_Initialize(); | 3210 CONTEXTUAL); |
| 3202 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); | 3211 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3203 } | 3212 } |
| 3204 | 3213 |
| 3205 | 3214 |
| 3206 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 3215 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
| 3207 Register context = ToRegister(instr->context()); | 3216 Register context = ToRegister(instr->context()); |
| 3208 Register result = ToRegister(instr->result()); | 3217 Register result = ToRegister(instr->result()); |
| 3209 __ mov(result, ContextOperand(context, instr->slot_index())); | 3218 __ mov(result, ContextOperand(context, instr->slot_index())); |
| 3210 | 3219 |
| 3211 if (instr->hydrogen()->RequiresHoleCheck()) { | 3220 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3212 __ cmp(result, factory()->the_hole_value()); | 3221 __ cmp(result, factory()->the_hole_value()); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3311 } | 3320 } |
| 3312 } | 3321 } |
| 3313 | 3322 |
| 3314 | 3323 |
| 3315 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 3324 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 3316 ASSERT(ToRegister(instr->context()).is(esi)); | 3325 ASSERT(ToRegister(instr->context()).is(esi)); |
| 3317 ASSERT(ToRegister(instr->object()).is(edx)); | 3326 ASSERT(ToRegister(instr->object()).is(edx)); |
| 3318 ASSERT(ToRegister(instr->result()).is(eax)); | 3327 ASSERT(ToRegister(instr->result()).is(eax)); |
| 3319 | 3328 |
| 3320 __ mov(ecx, instr->name()); | 3329 __ mov(ecx, instr->name()); |
| 3321 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 3330 Handle<Code> ic = LoadIC::initialize_stub(isolate(), NOT_CONTEXTUAL); |
| 3322 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3331 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3323 } | 3332 } |
| 3324 | 3333 |
| 3325 | 3334 |
| 3326 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 3335 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
| 3327 Register function = ToRegister(instr->function()); | 3336 Register function = ToRegister(instr->function()); |
| 3328 Register temp = ToRegister(instr->temp()); | 3337 Register temp = ToRegister(instr->temp()); |
| 3329 Register result = ToRegister(instr->result()); | 3338 Register result = ToRegister(instr->result()); |
| 3330 | 3339 |
| 3331 // Check that the function really is a function. | 3340 // Check that the function really is a function. |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3635 | 3644 |
| 3636 | 3645 |
| 3637 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { | 3646 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { |
| 3638 Register receiver = ToRegister(instr->receiver()); | 3647 Register receiver = ToRegister(instr->receiver()); |
| 3639 Register function = ToRegister(instr->function()); | 3648 Register function = ToRegister(instr->function()); |
| 3640 Register scratch = ToRegister(instr->temp()); | 3649 Register scratch = ToRegister(instr->temp()); |
| 3641 | 3650 |
| 3642 // 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 |
| 3643 // object as a receiver to normal functions. Values have to be | 3652 // object as a receiver to normal functions. Values have to be |
| 3644 // passed unchanged to builtins and strict-mode functions. | 3653 // passed unchanged to builtins and strict-mode functions. |
| 3645 Label global_object, receiver_ok; | 3654 Label receiver_ok, global_object; |
| 3646 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; | 3655 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
| 3647 | 3656 |
| 3648 // Do not transform the receiver to object for strict mode | 3657 // Do not transform the receiver to object for strict mode |
| 3649 // functions. | 3658 // functions. |
| 3650 __ mov(scratch, | 3659 __ mov(scratch, |
| 3651 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 3660 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
| 3652 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset), | 3661 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset), |
| 3653 1 << SharedFunctionInfo::kStrictModeBitWithinByte); | 3662 1 << SharedFunctionInfo::kStrictModeBitWithinByte); |
| 3654 __ j(not_equal, &receiver_ok, dist); | 3663 __ j(not_equal, &receiver_ok, dist); |
| 3655 | 3664 |
| 3656 // Do not transform the receiver to object for builtins. | 3665 // Do not transform the receiver to object for builtins. |
| 3657 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset), | 3666 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset), |
| 3658 1 << SharedFunctionInfo::kNativeBitWithinByte); | 3667 1 << SharedFunctionInfo::kNativeBitWithinByte); |
| 3659 __ j(not_equal, &receiver_ok, dist); | 3668 __ j(not_equal, &receiver_ok, dist); |
| 3660 | 3669 |
| 3661 // Normal function. Replace undefined or null with global receiver. | 3670 // Normal function. Replace undefined or null with global receiver. |
| 3662 __ cmp(receiver, factory()->null_value()); | 3671 __ cmp(receiver, factory()->null_value()); |
| 3663 __ j(equal, &global_object, Label::kNear); | 3672 __ j(equal, &global_object, Label::kNear); |
| 3664 __ cmp(receiver, factory()->undefined_value()); | 3673 __ cmp(receiver, factory()->undefined_value()); |
| 3665 __ j(equal, &global_object, Label::kNear); | 3674 __ j(equal, &global_object, Label::kNear); |
| 3666 | 3675 |
| 3667 // The receiver should be a JS object. | 3676 // The receiver should be a JS object. |
| 3668 __ test(receiver, Immediate(kSmiTagMask)); | 3677 __ test(receiver, Immediate(kSmiTagMask)); |
| 3669 DeoptimizeIf(equal, instr->environment()); | 3678 DeoptimizeIf(equal, instr->environment()); |
| 3670 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); | 3679 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); |
| 3671 DeoptimizeIf(below, instr->environment()); | 3680 DeoptimizeIf(below, instr->environment()); |
| 3672 __ jmp(&receiver_ok, Label::kNear); | 3681 __ jmp(&receiver_ok, Label::kNear); |
| 3673 | 3682 |
| 3674 __ bind(&global_object); | 3683 __ bind(&global_object); |
| 3675 // TODO(kmillikin): We have a hydrogen value for the global object. See | 3684 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); |
| 3676 // if it's better to use it than to explicitly fetch it from the context | |
| 3677 // here. | |
| 3678 __ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
| 3679 __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_OBJECT_INDEX)); | |
| 3680 __ mov(receiver, | 3685 __ mov(receiver, |
| 3681 FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset)); | 3686 Operand(receiver, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 3687 __ mov(receiver, FieldOperand(receiver, GlobalObject::kGlobalReceiverOffset)); |
| 3688 |
| 3682 __ bind(&receiver_ok); | 3689 __ bind(&receiver_ok); |
| 3683 } | 3690 } |
| 3684 | 3691 |
| 3685 | 3692 |
| 3686 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 3693 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
| 3687 Register receiver = ToRegister(instr->receiver()); | 3694 Register receiver = ToRegister(instr->receiver()); |
| 3688 Register function = ToRegister(instr->function()); | 3695 Register function = ToRegister(instr->function()); |
| 3689 Register length = ToRegister(instr->length()); | 3696 Register length = ToRegister(instr->length()); |
| 3690 Register elements = ToRegister(instr->elements()); | 3697 Register elements = ToRegister(instr->elements()); |
| 3691 ASSERT(receiver.is(eax)); // Used for parameter count. | 3698 ASSERT(receiver.is(eax)); // Used for parameter count. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3713 __ j(not_zero, &loop); | 3720 __ j(not_zero, &loop); |
| 3714 | 3721 |
| 3715 // Invoke the function. | 3722 // Invoke the function. |
| 3716 __ bind(&invoke); | 3723 __ bind(&invoke); |
| 3717 ASSERT(instr->HasPointerMap()); | 3724 ASSERT(instr->HasPointerMap()); |
| 3718 LPointerMap* pointers = instr->pointer_map(); | 3725 LPointerMap* pointers = instr->pointer_map(); |
| 3719 SafepointGenerator safepoint_generator( | 3726 SafepointGenerator safepoint_generator( |
| 3720 this, pointers, Safepoint::kLazyDeopt); | 3727 this, pointers, Safepoint::kLazyDeopt); |
| 3721 ParameterCount actual(eax); | 3728 ParameterCount actual(eax); |
| 3722 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3729 __ InvokeFunction(function, actual, CALL_FUNCTION, |
| 3723 safepoint_generator, CALL_AS_METHOD); | 3730 safepoint_generator, CALL_AS_FUNCTION); |
| 3724 } | 3731 } |
| 3725 | 3732 |
| 3726 | 3733 |
| 3727 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { | 3734 void LCodeGen::DoDebugBreak(LDebugBreak* instr) { |
| 3728 __ int3(); | 3735 __ int3(); |
| 3729 } | 3736 } |
| 3730 | 3737 |
| 3731 | 3738 |
| 3732 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3739 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| 3733 LOperand* argument = instr->value(); | 3740 LOperand* argument = instr->value(); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3834 } | 3841 } |
| 3835 } | 3842 } |
| 3836 | 3843 |
| 3837 | 3844 |
| 3838 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 3845 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| 3839 ASSERT(ToRegister(instr->result()).is(eax)); | 3846 ASSERT(ToRegister(instr->result()).is(eax)); |
| 3840 CallKnownFunction(instr->hydrogen()->function(), | 3847 CallKnownFunction(instr->hydrogen()->function(), |
| 3841 instr->hydrogen()->formal_parameter_count(), | 3848 instr->hydrogen()->formal_parameter_count(), |
| 3842 instr->arity(), | 3849 instr->arity(), |
| 3843 instr, | 3850 instr, |
| 3844 CALL_AS_METHOD, | 3851 CALL_AS_FUNCTION, |
| 3845 EDI_UNINITIALIZED); | 3852 EDI_UNINITIALIZED); |
| 3846 } | 3853 } |
| 3847 | 3854 |
| 3848 | 3855 |
| 3849 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3856 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3850 Register input_reg = ToRegister(instr->value()); | 3857 Register input_reg = ToRegister(instr->value()); |
| 3851 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 3858 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3852 factory()->heap_number_map()); | 3859 factory()->heap_number_map()); |
| 3853 DeoptimizeIf(not_equal, instr->environment()); | 3860 DeoptimizeIf(not_equal, instr->environment()); |
| 3854 | 3861 |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4195 ASSERT(ToRegister(instr->context()).is(esi)); | 4202 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4196 ASSERT(ToRegister(instr->function()).is(edi)); | 4203 ASSERT(ToRegister(instr->function()).is(edi)); |
| 4197 ASSERT(instr->HasPointerMap()); | 4204 ASSERT(instr->HasPointerMap()); |
| 4198 | 4205 |
| 4199 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 4206 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 4200 if (known_function.is_null()) { | 4207 if (known_function.is_null()) { |
| 4201 LPointerMap* pointers = instr->pointer_map(); | 4208 LPointerMap* pointers = instr->pointer_map(); |
| 4202 SafepointGenerator generator( | 4209 SafepointGenerator generator( |
| 4203 this, pointers, Safepoint::kLazyDeopt); | 4210 this, pointers, Safepoint::kLazyDeopt); |
| 4204 ParameterCount count(instr->arity()); | 4211 ParameterCount count(instr->arity()); |
| 4205 __ InvokeFunction(edi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 4212 __ InvokeFunction(edi, count, CALL_FUNCTION, generator, CALL_AS_FUNCTION); |
| 4206 } else { | 4213 } else { |
| 4207 CallKnownFunction(known_function, | 4214 CallKnownFunction(known_function, |
| 4208 instr->hydrogen()->formal_parameter_count(), | 4215 instr->hydrogen()->formal_parameter_count(), |
| 4209 instr->arity(), | 4216 instr->arity(), |
| 4210 instr, | 4217 instr, |
| 4211 CALL_AS_METHOD, | 4218 CALL_AS_FUNCTION, |
| 4212 EDI_CONTAINS_TARGET); | 4219 EDI_CONTAINS_TARGET); |
| 4213 } | 4220 } |
| 4214 } | 4221 } |
| 4215 | 4222 |
| 4216 | 4223 |
| 4217 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 4224 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
| 4218 ASSERT(ToRegister(instr->context()).is(esi)); | 4225 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4219 ASSERT(ToRegister(instr->key()).is(ecx)); | 4226 ASSERT(ToRegister(instr->key()).is(ecx)); |
| 4220 ASSERT(ToRegister(instr->result()).is(eax)); | 4227 ASSERT(ToRegister(instr->result()).is(eax)); |
| 4221 | 4228 |
| 4222 int arity = instr->arity(); | 4229 int arity = instr->arity(); |
| 4223 Handle<Code> ic = | 4230 Handle<Code> ic = |
| 4224 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); | 4231 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); |
| 4225 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4232 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4226 } | 4233 } |
| 4227 | 4234 |
| 4228 | 4235 |
| 4229 void LCodeGen::DoCallNamed(LCallNamed* instr) { | 4236 void LCodeGen::DoCallNamed(LCallNamed* instr) { |
| 4230 ASSERT(ToRegister(instr->context()).is(esi)); | 4237 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4231 ASSERT(ToRegister(instr->result()).is(eax)); | 4238 ASSERT(ToRegister(instr->result()).is(eax)); |
| 4232 | 4239 |
| 4233 int arity = instr->arity(); | 4240 int arity = instr->arity(); |
| 4234 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | |
| 4235 Handle<Code> ic = | 4241 Handle<Code> ic = |
| 4236 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 4242 isolate()->stub_cache()->ComputeCallInitialize(arity, NOT_CONTEXTUAL); |
| 4237 __ mov(ecx, instr->name()); | 4243 __ mov(ecx, instr->name()); |
| 4238 CallCode(ic, mode, instr); | 4244 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4239 } | 4245 } |
| 4240 | 4246 |
| 4241 | 4247 |
| 4242 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 4248 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 4243 ASSERT(ToRegister(instr->context()).is(esi)); | 4249 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4244 ASSERT(ToRegister(instr->function()).is(edi)); | 4250 ASSERT(ToRegister(instr->function()).is(edi)); |
| 4245 ASSERT(ToRegister(instr->result()).is(eax)); | 4251 ASSERT(ToRegister(instr->result()).is(eax)); |
| 4246 | 4252 |
| 4247 int arity = instr->arity(); | 4253 int arity = instr->arity(); |
| 4248 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 4254 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
| 4249 if (instr->hydrogen()->IsTailCall()) { | 4255 if (instr->hydrogen()->IsTailCall()) { |
| 4250 if (NeedsEagerFrame()) __ leave(); | 4256 if (NeedsEagerFrame()) __ leave(); |
| 4251 __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | 4257 __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); |
| 4252 } else { | 4258 } else { |
| 4253 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4259 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4254 } | 4260 } |
| 4255 } | 4261 } |
| 4256 | 4262 |
| 4257 | 4263 |
| 4258 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 4264 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
| 4259 ASSERT(ToRegister(instr->context()).is(esi)); | 4265 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4260 ASSERT(ToRegister(instr->result()).is(eax)); | 4266 ASSERT(ToRegister(instr->result()).is(eax)); |
| 4261 | 4267 |
| 4262 int arity = instr->arity(); | 4268 int arity = instr->arity(); |
| 4263 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; | |
| 4264 Handle<Code> ic = | 4269 Handle<Code> ic = |
| 4265 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 4270 isolate()->stub_cache()->ComputeCallInitialize(arity, CONTEXTUAL); |
| 4266 __ mov(ecx, instr->name()); | 4271 __ mov(ecx, instr->name()); |
| 4267 CallCode(ic, mode, instr); | 4272 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4268 } | 4273 } |
| 4269 | 4274 |
| 4270 | 4275 |
| 4271 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 4276 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
| 4272 ASSERT(ToRegister(instr->result()).is(eax)); | 4277 ASSERT(ToRegister(instr->result()).is(eax)); |
| 4273 CallKnownFunction(instr->hydrogen()->target(), | 4278 CallKnownFunction(instr->hydrogen()->target(), |
| 4274 instr->hydrogen()->formal_parameter_count(), | 4279 instr->hydrogen()->formal_parameter_count(), |
| 4275 instr->arity(), | 4280 instr->arity(), |
| 4276 instr, | 4281 instr, |
| 4277 CALL_AS_FUNCTION, | 4282 CALL_AS_FUNCTION, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4298 ASSERT(ToRegister(instr->constructor()).is(edi)); | 4303 ASSERT(ToRegister(instr->constructor()).is(edi)); |
| 4299 ASSERT(ToRegister(instr->result()).is(eax)); | 4304 ASSERT(ToRegister(instr->result()).is(eax)); |
| 4300 | 4305 |
| 4301 __ Set(eax, Immediate(instr->arity())); | 4306 __ Set(eax, Immediate(instr->arity())); |
| 4302 __ mov(ebx, instr->hydrogen()->property_cell()); | 4307 __ mov(ebx, instr->hydrogen()->property_cell()); |
| 4303 ElementsKind kind = instr->hydrogen()->elements_kind(); | 4308 ElementsKind kind = instr->hydrogen()->elements_kind(); |
| 4304 AllocationSiteOverrideMode override_mode = | 4309 AllocationSiteOverrideMode override_mode = |
| 4305 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) | 4310 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) |
| 4306 ? DISABLE_ALLOCATION_SITES | 4311 ? DISABLE_ALLOCATION_SITES |
| 4307 : DONT_OVERRIDE; | 4312 : DONT_OVERRIDE; |
| 4308 ContextCheckMode context_mode = CONTEXT_CHECK_NOT_REQUIRED; | |
| 4309 | 4313 |
| 4310 if (instr->arity() == 0) { | 4314 if (instr->arity() == 0) { |
| 4311 ArrayNoArgumentConstructorStub stub(kind, context_mode, override_mode); | 4315 ArrayNoArgumentConstructorStub stub(kind, override_mode); |
| 4312 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4316 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4313 } else if (instr->arity() == 1) { | 4317 } else if (instr->arity() == 1) { |
| 4314 Label done; | 4318 Label done; |
| 4315 if (IsFastPackedElementsKind(kind)) { | 4319 if (IsFastPackedElementsKind(kind)) { |
| 4316 Label packed_case; | 4320 Label packed_case; |
| 4317 // We might need a change here | 4321 // We might need a change here |
| 4318 // look at the first argument | 4322 // look at the first argument |
| 4319 __ mov(ecx, Operand(esp, 0)); | 4323 __ mov(ecx, Operand(esp, 0)); |
| 4320 __ test(ecx, ecx); | 4324 __ test(ecx, ecx); |
| 4321 __ j(zero, &packed_case, Label::kNear); | 4325 __ j(zero, &packed_case, Label::kNear); |
| 4322 | 4326 |
| 4323 ElementsKind holey_kind = GetHoleyElementsKind(kind); | 4327 ElementsKind holey_kind = GetHoleyElementsKind(kind); |
| 4324 ArraySingleArgumentConstructorStub stub(holey_kind, context_mode, | 4328 ArraySingleArgumentConstructorStub stub(holey_kind, override_mode); |
| 4325 override_mode); | |
| 4326 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4329 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4327 __ jmp(&done, Label::kNear); | 4330 __ jmp(&done, Label::kNear); |
| 4328 __ bind(&packed_case); | 4331 __ bind(&packed_case); |
| 4329 } | 4332 } |
| 4330 | 4333 |
| 4331 ArraySingleArgumentConstructorStub stub(kind, context_mode, override_mode); | 4334 ArraySingleArgumentConstructorStub stub(kind, override_mode); |
| 4332 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4335 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4333 __ bind(&done); | 4336 __ bind(&done); |
| 4334 } else { | 4337 } else { |
| 4335 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode); | 4338 ArrayNArgumentsConstructorStub stub(kind, override_mode); |
| 4336 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4339 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4337 } | 4340 } |
| 4338 } | 4341 } |
| 4339 | 4342 |
| 4340 | 4343 |
| 4341 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 4344 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 4342 ASSERT(ToRegister(instr->context()).is(esi)); | 4345 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4343 CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles()); | 4346 CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles()); |
| 4344 } | 4347 } |
| 4345 | 4348 |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4489 } | 4492 } |
| 4490 } | 4493 } |
| 4491 | 4494 |
| 4492 | 4495 |
| 4493 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 4496 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
| 4494 ASSERT(ToRegister(instr->context()).is(esi)); | 4497 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4495 ASSERT(ToRegister(instr->object()).is(edx)); | 4498 ASSERT(ToRegister(instr->object()).is(edx)); |
| 4496 ASSERT(ToRegister(instr->value()).is(eax)); | 4499 ASSERT(ToRegister(instr->value()).is(eax)); |
| 4497 | 4500 |
| 4498 __ mov(ecx, instr->name()); | 4501 __ mov(ecx, instr->name()); |
| 4499 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4502 Handle<Code> ic = StoreIC::initialize_stub(isolate(), |
| 4500 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 4503 instr->strict_mode_flag(), |
| 4501 : isolate()->builtins()->StoreIC_Initialize(); | 4504 NOT_CONTEXTUAL); |
| 4502 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4505 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4503 } | 4506 } |
| 4504 | 4507 |
| 4505 | 4508 |
| 4506 void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) { | 4509 void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) { |
| 4507 if (FLAG_debug_code && check->hydrogen()->skip_check()) { | 4510 if (FLAG_debug_code && check->hydrogen()->skip_check()) { |
| 4508 Label done; | 4511 Label done; |
| 4509 __ j(NegateCondition(cc), &done, Label::kNear); | 4512 __ j(NegateCondition(cc), &done, Label::kNear); |
| 4510 __ int3(); | 4513 __ int3(); |
| 4511 __ bind(&done); | 4514 __ bind(&done); |
| (...skipping 1851 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6363 FixedArray::kHeaderSize - kPointerSize)); | 6366 FixedArray::kHeaderSize - kPointerSize)); |
| 6364 __ bind(&done); | 6367 __ bind(&done); |
| 6365 } | 6368 } |
| 6366 | 6369 |
| 6367 | 6370 |
| 6368 #undef __ | 6371 #undef __ |
| 6369 | 6372 |
| 6370 } } // namespace v8::internal | 6373 } } // namespace v8::internal |
| 6371 | 6374 |
| 6372 #endif // V8_TARGET_ARCH_IA32 | 6375 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |