| OLD | NEW | 
|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 3602 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3613   __ PushReturnAddressFrom(rcx); | 3613   __ PushReturnAddressFrom(rcx); | 
| 3614   GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8); | 3614   GenerateCompareFlatAsciiStrings(masm, rdx, rax, rcx, rbx, rdi, r8); | 
| 3615 | 3615 | 
| 3616   // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 3616   // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 
| 3617   // tagged as a small integer. | 3617   // tagged as a small integer. | 
| 3618   __ bind(&runtime); | 3618   __ bind(&runtime); | 
| 3619   __ TailCallRuntime(Runtime::kHiddenStringCompare, 2, 1); | 3619   __ TailCallRuntime(Runtime::kHiddenStringCompare, 2, 1); | 
| 3620 } | 3620 } | 
| 3621 | 3621 | 
| 3622 | 3622 | 
| 3623 void ArrayPushStub::Generate(MacroAssembler* masm) { |  | 
| 3624   int argc = arguments_count(); |  | 
| 3625 |  | 
| 3626   StackArgumentsAccessor args(rsp, argc); |  | 
| 3627   if (argc == 0) { |  | 
| 3628     // Noop, return the length. |  | 
| 3629     __ movp(rax, FieldOperand(rdx, JSArray::kLengthOffset)); |  | 
| 3630     __ ret((argc + 1) * kPointerSize); |  | 
| 3631     return; |  | 
| 3632   } |  | 
| 3633 |  | 
| 3634   Isolate* isolate = masm->isolate(); |  | 
| 3635 |  | 
| 3636   if (argc != 1) { |  | 
| 3637     __ TailCallExternalReference( |  | 
| 3638         ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); |  | 
| 3639     return; |  | 
| 3640   } |  | 
| 3641 |  | 
| 3642   Label call_builtin, attempt_to_grow_elements, with_write_barrier; |  | 
| 3643 |  | 
| 3644   // Get the elements array of the object. |  | 
| 3645   __ movp(rdi, FieldOperand(rdx, JSArray::kElementsOffset)); |  | 
| 3646 |  | 
| 3647   if (IsFastSmiOrObjectElementsKind(elements_kind())) { |  | 
| 3648     // Check that the elements are in fast mode and writable. |  | 
| 3649     __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset), |  | 
| 3650            isolate->factory()->fixed_array_map()); |  | 
| 3651     __ j(not_equal, &call_builtin); |  | 
| 3652   } |  | 
| 3653 |  | 
| 3654   // Get the array's length into rax and calculate new length. |  | 
| 3655   __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset)); |  | 
| 3656   STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); |  | 
| 3657   __ addl(rax, Immediate(argc)); |  | 
| 3658 |  | 
| 3659   // Get the elements' length into rcx. |  | 
| 3660   __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); |  | 
| 3661 |  | 
| 3662   // Check if we could survive without allocation. |  | 
| 3663   __ cmpl(rax, rcx); |  | 
| 3664 |  | 
| 3665   if (IsFastSmiOrObjectElementsKind(elements_kind())) { |  | 
| 3666     __ j(greater, &attempt_to_grow_elements); |  | 
| 3667 |  | 
| 3668     // Check if value is a smi. |  | 
| 3669     __ movp(rcx, args.GetArgumentOperand(1)); |  | 
| 3670     __ JumpIfNotSmi(rcx, &with_write_barrier); |  | 
| 3671 |  | 
| 3672     // Store the value. |  | 
| 3673     __ movp(FieldOperand(rdi, |  | 
| 3674                          rax, |  | 
| 3675                          times_pointer_size, |  | 
| 3676                          FixedArray::kHeaderSize - argc * kPointerSize), |  | 
| 3677             rcx); |  | 
| 3678   } else { |  | 
| 3679     __ j(greater, &call_builtin); |  | 
| 3680 |  | 
| 3681     __ movp(rcx, args.GetArgumentOperand(1)); |  | 
| 3682     __ StoreNumberToDoubleElements( |  | 
| 3683         rcx, rdi, rax, xmm0, &call_builtin, argc * kDoubleSize); |  | 
| 3684   } |  | 
| 3685 |  | 
| 3686   // Save new length. |  | 
| 3687   __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); |  | 
| 3688 |  | 
| 3689   __ Integer32ToSmi(rax, rax);  // Return new length as smi. |  | 
| 3690   __ ret((argc + 1) * kPointerSize); |  | 
| 3691 |  | 
| 3692   if (IsFastDoubleElementsKind(elements_kind())) { |  | 
| 3693     __ bind(&call_builtin); |  | 
| 3694     __ TailCallExternalReference( |  | 
| 3695         ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); |  | 
| 3696     return; |  | 
| 3697   } |  | 
| 3698 |  | 
| 3699   __ bind(&with_write_barrier); |  | 
| 3700 |  | 
| 3701   if (IsFastSmiElementsKind(elements_kind())) { |  | 
| 3702     if (FLAG_trace_elements_transitions) __ jmp(&call_builtin); |  | 
| 3703 |  | 
| 3704     __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), |  | 
| 3705            isolate->factory()->heap_number_map()); |  | 
| 3706     __ j(equal, &call_builtin); |  | 
| 3707 |  | 
| 3708     ElementsKind target_kind = IsHoleyElementsKind(elements_kind()) |  | 
| 3709         ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; |  | 
| 3710     __ movp(rbx, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX)); |  | 
| 3711     __ movp(rbx, FieldOperand(rbx, GlobalObject::kNativeContextOffset)); |  | 
| 3712     __ movp(rbx, ContextOperand(rbx, Context::JS_ARRAY_MAPS_INDEX)); |  | 
| 3713     const int header_size = FixedArrayBase::kHeaderSize; |  | 
| 3714     // Verify that the object can be transitioned in place. |  | 
| 3715     const int origin_offset = header_size + elements_kind() * kPointerSize; |  | 
| 3716     __ movp(rdi, FieldOperand(rbx, origin_offset)); |  | 
| 3717     __ cmpp(rdi, FieldOperand(rdx, HeapObject::kMapOffset)); |  | 
| 3718     __ j(not_equal, &call_builtin); |  | 
| 3719 |  | 
| 3720     const int target_offset = header_size + target_kind * kPointerSize; |  | 
| 3721     __ movp(rbx, FieldOperand(rbx, target_offset)); |  | 
| 3722     ElementsTransitionGenerator::GenerateMapChangeElementsTransition( |  | 
| 3723         masm, DONT_TRACK_ALLOCATION_SITE, NULL); |  | 
| 3724     __ movp(rdi, FieldOperand(rdx, JSArray::kElementsOffset)); |  | 
| 3725   } |  | 
| 3726 |  | 
| 3727   // Save new length. |  | 
| 3728   __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); |  | 
| 3729 |  | 
| 3730   // Store the value. |  | 
| 3731   __ leap(rdx, FieldOperand(rdi, |  | 
| 3732                            rax, times_pointer_size, |  | 
| 3733                            FixedArray::kHeaderSize - argc * kPointerSize)); |  | 
| 3734   __ movp(Operand(rdx, 0), rcx); |  | 
| 3735 |  | 
| 3736   __ RecordWrite(rdi, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, |  | 
| 3737                  OMIT_SMI_CHECK); |  | 
| 3738 |  | 
| 3739   __ Integer32ToSmi(rax, rax);  // Return new length as smi. |  | 
| 3740   __ ret((argc + 1) * kPointerSize); |  | 
| 3741 |  | 
| 3742   __ bind(&attempt_to_grow_elements); |  | 
| 3743   if (!FLAG_inline_new) { |  | 
| 3744     __ bind(&call_builtin); |  | 
| 3745     __ TailCallExternalReference( |  | 
| 3746         ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); |  | 
| 3747     return; |  | 
| 3748   } |  | 
| 3749 |  | 
| 3750   __ movp(rbx, args.GetArgumentOperand(1)); |  | 
| 3751   // Growing elements that are SMI-only requires special handling in case the |  | 
| 3752   // new element is non-Smi. For now, delegate to the builtin. |  | 
| 3753   Label no_fast_elements_check; |  | 
| 3754   __ JumpIfSmi(rbx, &no_fast_elements_check); |  | 
| 3755   __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); |  | 
| 3756   __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar); |  | 
| 3757   __ bind(&no_fast_elements_check); |  | 
| 3758 |  | 
| 3759   ExternalReference new_space_allocation_top = |  | 
| 3760       ExternalReference::new_space_allocation_top_address(isolate); |  | 
| 3761   ExternalReference new_space_allocation_limit = |  | 
| 3762       ExternalReference::new_space_allocation_limit_address(isolate); |  | 
| 3763 |  | 
| 3764   const int kAllocationDelta = 4; |  | 
| 3765   ASSERT(kAllocationDelta >= argc); |  | 
| 3766   // Load top. |  | 
| 3767   __ Load(rcx, new_space_allocation_top); |  | 
| 3768 |  | 
| 3769   // Check if it's the end of elements. |  | 
| 3770   __ leap(rdx, FieldOperand(rdi, |  | 
| 3771                            rax, times_pointer_size, |  | 
| 3772                            FixedArray::kHeaderSize - argc * kPointerSize)); |  | 
| 3773   __ cmpp(rdx, rcx); |  | 
| 3774   __ j(not_equal, &call_builtin); |  | 
| 3775   __ addp(rcx, Immediate(kAllocationDelta * kPointerSize)); |  | 
| 3776   Operand limit_operand = masm->ExternalOperand(new_space_allocation_limit); |  | 
| 3777   __ cmpp(rcx, limit_operand); |  | 
| 3778   __ j(above, &call_builtin); |  | 
| 3779 |  | 
| 3780   // We fit and could grow elements. |  | 
| 3781   __ Store(new_space_allocation_top, rcx); |  | 
| 3782 |  | 
| 3783   // Push the argument... |  | 
| 3784   __ movp(Operand(rdx, 0), rbx); |  | 
| 3785   // ... and fill the rest with holes. |  | 
| 3786   __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); |  | 
| 3787   for (int i = 1; i < kAllocationDelta; i++) { |  | 
| 3788     __ movp(Operand(rdx, i * kPointerSize), kScratchRegister); |  | 
| 3789   } |  | 
| 3790 |  | 
| 3791   if (IsFastObjectElementsKind(elements_kind())) { |  | 
| 3792     // We know the elements array is in new space so we don't need the |  | 
| 3793     // remembered set, but we just pushed a value onto it so we may have to tell |  | 
| 3794     // the incremental marker to rescan the object that we just grew.  We don't |  | 
| 3795     // need to worry about the holes because they are in old space and already |  | 
| 3796     // marked black. |  | 
| 3797     __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); |  | 
| 3798   } |  | 
| 3799 |  | 
| 3800   // Restore receiver to rdx as finish sequence assumes it's here. |  | 
| 3801   __ movp(rdx, args.GetReceiverOperand()); |  | 
| 3802 |  | 
| 3803   // Increment element's and array's sizes. |  | 
| 3804   __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset), |  | 
| 3805                     Smi::FromInt(kAllocationDelta)); |  | 
| 3806 |  | 
| 3807   // Make new length a smi before returning it. |  | 
| 3808   __ Integer32ToSmi(rax, rax); |  | 
| 3809   __ movp(FieldOperand(rdx, JSArray::kLengthOffset), rax); |  | 
| 3810 |  | 
| 3811   __ ret((argc + 1) * kPointerSize); |  | 
| 3812 |  | 
| 3813   __ bind(&call_builtin); |  | 
| 3814   __ TailCallExternalReference( |  | 
| 3815       ExternalReference(Builtins::c_ArrayPush, isolate), argc + 1, 1); |  | 
| 3816 } |  | 
| 3817 |  | 
| 3818 |  | 
| 3819 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 3623 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) { | 
| 3820   // ----------- S t a t e ------------- | 3624   // ----------- S t a t e ------------- | 
| 3821   //  -- rdx    : left | 3625   //  -- rdx    : left | 
| 3822   //  -- rax    : right | 3626   //  -- rax    : right | 
| 3823   //  -- rsp[0] : return address | 3627   //  -- rsp[0] : return address | 
| 3824   // ----------------------------------- | 3628   // ----------------------------------- | 
| 3825   Isolate* isolate = masm->isolate(); | 3629   Isolate* isolate = masm->isolate(); | 
| 3826 | 3630 | 
| 3827   // Load rcx with the allocation site.  We stick an undefined dummy value here | 3631   // Load rcx with the allocation site.  We stick an undefined dummy value here | 
| 3828   // and replace it with the real allocation site later when we instantiate this | 3632   // and replace it with the real allocation site later when we instantiate this | 
| (...skipping 1395 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5224                               return_value_operand, | 5028                               return_value_operand, | 
| 5225                               NULL); | 5029                               NULL); | 
| 5226 } | 5030 } | 
| 5227 | 5031 | 
| 5228 | 5032 | 
| 5229 #undef __ | 5033 #undef __ | 
| 5230 | 5034 | 
| 5231 } }  // namespace v8::internal | 5035 } }  // namespace v8::internal | 
| 5232 | 5036 | 
| 5233 #endif  // V8_TARGET_ARCH_X64 | 5037 #endif  // V8_TARGET_ARCH_X64 | 
| OLD | NEW | 
|---|