~ubuntu-branches/ubuntu/trusty/libv8/trusty

« back to all changes in this revision

Viewing changes to src/x64/ic-x64.cc

  • Committer: Package Import Robot
  • Author(s): Jérémy Lal
  • Date: 2012-02-20 14:08:17 UTC
  • mfrom: (15.1.24 sid)
  • Revision ID: package-import@ubuntu.com-20120220140817-bsvmeoa4sxsj5hbz
Tags: 3.7.12.22-3
Fix mipsel build, allow test debug-step-3 to fail (non-crucial)

Show diffs side-by-side

added added

removed removed

Lines of Context:
221
221
 
222
222
  // Update write barrier. Make sure not to clobber the value.
223
223
  __ movq(scratch0, value);
224
 
  __ RecordWrite(elements, scratch1, scratch0);
 
224
  __ RecordWrite(elements, scratch1, scratch0, kDontSaveFPRegs);
225
225
}
226
226
 
227
227
 
531
531
 
532
532
  Register receiver = rdx;
533
533
  Register index = rax;
534
 
  Register scratch1 = rbx;
535
 
  Register scratch2 = rcx;
 
534
  Register scratch = rcx;
536
535
  Register result = rax;
537
536
 
538
537
  StringCharAtGenerator char_at_generator(receiver,
539
538
                                          index,
540
 
                                          scratch1,
541
 
                                          scratch2,
 
539
                                          scratch,
542
540
                                          result,
543
541
                                          &miss,  // When not a string.
544
542
                                          &miss,  // When not a number.
606
604
  //  -- rdx     : receiver
607
605
  //  -- rsp[0]  : return address
608
606
  // -----------------------------------
609
 
  Label slow, slow_with_tagged_index, fast, array, extra;
 
607
  Label slow, slow_with_tagged_index, fast, array, extra, check_extra_double;
 
608
  Label fast_object_with_map_check, fast_object_without_map_check;
 
609
  Label fast_double_with_map_check, fast_double_without_map_check;
610
610
 
611
611
  // Check that the object isn't a smi.
612
612
  __ JumpIfSmi(rdx, &slow_with_tagged_index);
613
613
  // Get the map from the receiver.
614
 
  __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
 
614
  __ movq(r9, FieldOperand(rdx, HeapObject::kMapOffset));
615
615
  // Check that the receiver does not require access checks.  We need
616
616
  // to do this because this generic stub does not perform map checks.
617
 
  __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
 
617
  __ testb(FieldOperand(r9, Map::kBitFieldOffset),
618
618
           Immediate(1 << Map::kIsAccessCheckNeeded));
619
619
  __ j(not_zero, &slow_with_tagged_index);
620
620
  // Check that the key is a smi.
621
621
  __ JumpIfNotSmi(rcx, &slow_with_tagged_index);
622
622
  __ SmiToInteger32(rcx, rcx);
623
623
 
624
 
  __ CmpInstanceType(rbx, JS_ARRAY_TYPE);
 
624
  __ CmpInstanceType(r9, JS_ARRAY_TYPE);
625
625
  __ j(equal, &array);
626
626
  // Check that the object is some kind of JSObject.
627
 
  __ CmpInstanceType(rbx, FIRST_JS_RECEIVER_TYPE);
 
627
  __ CmpInstanceType(r9, FIRST_JS_OBJECT_TYPE);
628
628
  __ j(below, &slow);
629
 
  __ CmpInstanceType(rbx, JS_PROXY_TYPE);
630
 
  __ j(equal, &slow);
631
 
  __ CmpInstanceType(rbx, JS_FUNCTION_PROXY_TYPE);
632
 
  __ j(equal, &slow);
633
629
 
634
630
  // Object case: Check key against length in the elements array.
635
631
  // rax: value
636
632
  // rdx: JSObject
637
633
  // rcx: index
638
634
  __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
639
 
  // Check that the object is in fast mode and writable.
640
 
  __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
641
 
                 Heap::kFixedArrayMapRootIndex);
642
 
  __ j(not_equal, &slow);
 
635
  // Check array bounds.
643
636
  __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx);
644
637
  // rax: value
645
638
  // rbx: FixedArray
646
639
  // rcx: index
647
 
  __ j(above, &fast);
 
640
  __ j(above, &fast_object_with_map_check);
648
641
 
649
642
  // Slow case: call runtime.
650
643
  __ bind(&slow);
666
659
  __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), rcx);
667
660
  __ j(below_equal, &slow);
668
661
  // Increment index to get new length.
669
 
  __ leal(rdi, Operand(rcx, 1));
670
 
  __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi);
671
 
  __ jmp(&fast);
 
662
  __ movq(rdi, FieldOperand(rbx, HeapObject::kMapOffset));
 
663
  __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex);
 
664
  __ j(not_equal, &check_extra_double);
 
665
  __ leal(rdi, Operand(rcx, 1));
 
666
  __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi);
 
667
  __ jmp(&fast_object_without_map_check);
 
668
 
 
669
  __ bind(&check_extra_double);
 
670
  // rdi: elements array's map
 
671
  __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex);
 
672
  __ j(not_equal, &slow);
 
673
  __ leal(rdi, Operand(rcx, 1));
 
674
  __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rdi);
 
675
  __ jmp(&fast_double_without_map_check);
672
676
 
673
677
  // Array case: Get the length and the elements array from the JS
674
678
  // array. Check that the array is in fast mode (and writable); if it
678
682
  // rdx: receiver (a JSArray)
679
683
  // rcx: index
680
684
  __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
681
 
  __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
682
 
                 Heap::kFixedArrayMapRootIndex);
683
 
  __ j(not_equal, &slow);
684
685
 
685
686
  // Check the key against the length in the array, compute the
686
687
  // address to store into and fall through to fast case.
688
689
  __ j(below_equal, &extra);
689
690
 
690
691
  // Fast case: Do the store.
691
 
  __ bind(&fast);
 
692
  __ bind(&fast_object_with_map_check);
692
693
  // rax: value
693
694
  // rbx: receiver's elements array (a FixedArray)
694
695
  // rcx: index
 
696
  // rdx: receiver (a JSArray)
 
697
  __ movq(rdi, FieldOperand(rbx, HeapObject::kMapOffset));
 
698
  __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex);
 
699
  __ j(not_equal, &fast_double_with_map_check);
 
700
  __ bind(&fast_object_without_map_check);
 
701
  // Smi stores don't require further checks.
695
702
  Label non_smi_value;
 
703
  __ JumpIfNotSmi(rax, &non_smi_value);
 
704
  // It's irrelevant whether array is smi-only or not when writing a smi.
696
705
  __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize),
697
706
          rax);
698
 
  __ JumpIfNotSmi(rax, &non_smi_value, Label::kNear);
699
707
  __ ret(0);
 
708
 
700
709
  __ bind(&non_smi_value);
701
 
  // Slow case that needs to retain rcx for use by RecordWrite.
702
 
  // Update write barrier for the elements array address.
703
 
  __ movq(rdx, rax);
704
 
  __ RecordWriteNonSmi(rbx, 0, rdx, rcx);
 
710
  // Writing a non-smi, check whether array allows non-smi elements.
 
711
  // r9: receiver's map
 
712
  __ CheckFastObjectElements(r9, &slow, Label::kNear);
 
713
  __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize),
 
714
          rax);
 
715
  __ movq(rdx, rax);  // Preserve the value which is returned.
 
716
  __ RecordWriteArray(
 
717
      rbx, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
 
718
  __ ret(0);
 
719
 
 
720
  __ bind(&fast_double_with_map_check);
 
721
  // Check for fast double array case. If this fails, call through to the
 
722
  // runtime.
 
723
  // rdi: elements array's map
 
724
  __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex);
 
725
  __ j(not_equal, &slow);
 
726
  __ bind(&fast_double_without_map_check);
 
727
  // If the value is a number, store it as a double in the FastDoubleElements
 
728
  // array.
 
729
  __ StoreNumberToDoubleElements(rax, rbx, rcx, xmm0, &slow);
705
730
  __ ret(0);
706
731
}
707
732
 
708
733
 
709
734
// The generated code does not accept smi keys.
710
735
// The generated code falls through if both probes miss.
711
 
static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
712
 
                                          int argc,
713
 
                                          Code::Kind kind,
714
 
                                          Code::ExtraICState extra_ic_state) {
 
736
void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm,
 
737
                                               int argc,
 
738
                                               Code::Kind kind,
 
739
                                               Code::ExtraICState extra_state) {
715
740
  // ----------- S t a t e -------------
716
741
  // rcx                      : function name
717
742
  // rdx                      : receiver
721
746
  // Probe the stub cache.
722
747
  Code::Flags flags = Code::ComputeFlags(kind,
723
748
                                         MONOMORPHIC,
724
 
                                         extra_ic_state,
 
749
                                         extra_state,
725
750
                                         NORMAL,
726
751
                                         argc);
727
752
  Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx,
794
819
 
795
820
 
796
821
// The generated code falls through if the call should be handled by runtime.
797
 
static void GenerateCallNormal(MacroAssembler* masm, int argc) {
 
822
void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) {
798
823
  // ----------- S t a t e -------------
799
824
  // rcx                    : function name
800
825
  // rsp[0]                 : return address
821
846
}
822
847
 
823
848
 
824
 
static void GenerateCallMiss(MacroAssembler* masm,
825
 
                             int argc,
826
 
                             IC::UtilityId id,
827
 
                             Code::ExtraICState extra_ic_state) {
 
849
void CallICBase::GenerateMiss(MacroAssembler* masm,
 
850
                              int argc,
 
851
                              IC::UtilityId id,
 
852
                              Code::ExtraICState extra_state) {
828
853
  // ----------- S t a t e -------------
829
854
  // rcx                      : function name
830
855
  // rsp[0]                   : return address
846
871
  __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
847
872
 
848
873
  // Enter an internal frame.
849
 
  __ EnterInternalFrame();
850
 
 
851
 
  // Push the receiver and the name of the function.
852
 
  __ push(rdx);
853
 
  __ push(rcx);
854
 
 
855
 
  // Call the entry.
856
 
  CEntryStub stub(1);
857
 
  __ Set(rax, 2);
858
 
  __ LoadAddress(rbx, ExternalReference(IC_Utility(id), masm->isolate()));
859
 
  __ CallStub(&stub);
860
 
 
861
 
  // Move result to rdi and exit the internal frame.
862
 
  __ movq(rdi, rax);
863
 
  __ LeaveInternalFrame();
 
874
  {
 
875
    FrameScope scope(masm, StackFrame::INTERNAL);
 
876
 
 
877
    // Push the receiver and the name of the function.
 
878
    __ push(rdx);
 
879
    __ push(rcx);
 
880
 
 
881
    // Call the entry.
 
882
    CEntryStub stub(1);
 
883
    __ Set(rax, 2);
 
884
    __ LoadAddress(rbx, ExternalReference(IC_Utility(id), masm->isolate()));
 
885
    __ CallStub(&stub);
 
886
 
 
887
    // Move result to rdi and exit the internal frame.
 
888
    __ movq(rdi, rax);
 
889
  }
864
890
 
865
891
  // Check if the receiver is a global object of some sort.
866
892
  // This can happen only for regular CallIC but not KeyedCallIC.
881
907
  }
882
908
 
883
909
  // Invoke the function.
884
 
  CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
 
910
  CallKind call_kind = CallICBase::Contextual::decode(extra_state)
885
911
      ? CALL_AS_FUNCTION
886
912
      : CALL_AS_METHOD;
887
913
  ParameterCount actual(argc);
913
939
}
914
940
 
915
941
 
916
 
void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
917
 
  // ----------- S t a t e -------------
918
 
  // rcx                      : function name
919
 
  // rsp[0]                   : return address
920
 
  // rsp[8]                   : argument argc
921
 
  // rsp[16]                  : argument argc - 1
922
 
  // ...
923
 
  // rsp[argc * 8]            : argument 1
924
 
  // rsp[(argc + 1) * 8]      : argument 0 = receiver
925
 
  // -----------------------------------
926
 
 
927
 
  GenerateCallNormal(masm, argc);
928
 
  GenerateMiss(masm, argc, Code::kNoExtraICState);
929
 
}
930
 
 
931
 
 
932
 
void CallIC::GenerateMiss(MacroAssembler* masm,
933
 
                          int argc,
934
 
                          Code::ExtraICState extra_ic_state) {
935
 
  // ----------- S t a t e -------------
936
 
  // rcx                      : function name
937
 
  // rsp[0]                   : return address
938
 
  // rsp[8]                   : argument argc
939
 
  // rsp[16]                  : argument argc - 1
940
 
  // ...
941
 
  // rsp[argc * 8]            : argument 1
942
 
  // rsp[(argc + 1) * 8]      : argument 0 = receiver
943
 
  // -----------------------------------
944
 
 
945
 
  GenerateCallMiss(masm, argc, IC::kCallIC_Miss, extra_ic_state);
946
 
}
947
 
 
948
 
 
949
942
void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
950
943
  // ----------- S t a t e -------------
951
944
  // rcx                      : function name
1002
995
  // This branch is taken when calling KeyedCallIC_Miss is neither required
1003
996
  // nor beneficial.
1004
997
  __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1);
1005
 
  __ EnterInternalFrame();
1006
 
  __ push(rcx);  // save the key
1007
 
  __ push(rdx);  // pass the receiver
1008
 
  __ push(rcx);  // pass the key
1009
 
  __ CallRuntime(Runtime::kKeyedGetProperty, 2);
1010
 
  __ pop(rcx);  // restore the key
1011
 
  __ LeaveInternalFrame();
 
998
  {
 
999
    FrameScope scope(masm, StackFrame::INTERNAL);
 
1000
    __ push(rcx);  // save the key
 
1001
    __ push(rdx);  // pass the receiver
 
1002
    __ push(rcx);  // pass the key
 
1003
    __ CallRuntime(Runtime::kKeyedGetProperty, 2);
 
1004
    __ pop(rcx);  // restore the key
 
1005
  }
1012
1006
  __ movq(rdi, rax);
1013
1007
  __ jmp(&do_call);
1014
1008
 
1072
1066
  __ JumpIfSmi(rcx, &miss);
1073
1067
  Condition cond = masm->IsObjectStringType(rcx, rax, rax);
1074
1068
  __ j(NegateCondition(cond), &miss);
1075
 
  GenerateCallNormal(masm, argc);
 
1069
  CallICBase::GenerateNormal(masm, argc);
1076
1070
  __ bind(&miss);
1077
1071
  GenerateMiss(masm, argc);
1078
1072
}
1079
1073
 
1080
1074
 
1081
 
void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) {
1082
 
  // ----------- S t a t e -------------
1083
 
  // rcx                      : function name
1084
 
  // rsp[0]                   : return address
1085
 
  // rsp[8]                   : argument argc
1086
 
  // rsp[16]                  : argument argc - 1
1087
 
  // ...
1088
 
  // rsp[argc * 8]            : argument 1
1089
 
  // rsp[(argc + 1) * 8]      : argument 0 = receiver
1090
 
  // -----------------------------------
1091
 
 
1092
 
  GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss, Code::kNoExtraICState);
1093
 
}
1094
 
 
1095
 
 
1096
1075
static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm,
1097
1076
                                             Register object,
1098
1077
                                             Register key,
1212
1191
  __ movq(mapped_location, rax);
1213
1192
  __ lea(r9, mapped_location);
1214
1193
  __ movq(r8, rax);
1215
 
  __ RecordWrite(rbx, r9, r8);
 
1194
  __ RecordWrite(rbx,
 
1195
                 r9,
 
1196
                 r8,
 
1197
                 kDontSaveFPRegs,
 
1198
                 EMIT_REMEMBERED_SET,
 
1199
                 INLINE_SMI_CHECK);
1216
1200
  __ Ret();
1217
1201
  __ bind(&notin);
1218
1202
  // The unmapped lookup expects that the parameter map is in rbx.
1221
1205
  __ movq(unmapped_location, rax);
1222
1206
  __ lea(r9, unmapped_location);
1223
1207
  __ movq(r8, rax);
1224
 
  __ RecordWrite(rbx, r9, r8);
 
1208
  __ RecordWrite(rbx,
 
1209
                 r9,
 
1210
                 r8,
 
1211
                 kDontSaveFPRegs,
 
1212
                 EMIT_REMEMBERED_SET,
 
1213
                 INLINE_SMI_CHECK);
1225
1214
  __ Ret();
1226
1215
  __ bind(&slow);
1227
1216
  GenerateMiss(masm, false);
1562
1551
}
1563
1552
 
1564
1553
 
 
1554
void KeyedStoreIC::GenerateTransitionElementsSmiToDouble(MacroAssembler* masm) {
 
1555
  // ----------- S t a t e -------------
 
1556
  //  -- rbx     : target map
 
1557
  //  -- rdx     : receiver
 
1558
  //  -- rsp[0]  : return address
 
1559
  // -----------------------------------
 
1560
  // Must return the modified receiver in eax.
 
1561
  if (!FLAG_trace_elements_transitions) {
 
1562
    Label fail;
 
1563
    ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &fail);
 
1564
    __ movq(rax, rdx);
 
1565
    __ Ret();
 
1566
    __ bind(&fail);
 
1567
  }
 
1568
 
 
1569
  __ pop(rbx);
 
1570
  __ push(rdx);
 
1571
  __ push(rbx);  // return address
 
1572
  __ TailCallRuntime(Runtime::kTransitionElementsSmiToDouble, 1, 1);
 
1573
}
 
1574
 
 
1575
 
 
1576
void KeyedStoreIC::GenerateTransitionElementsDoubleToObject(
 
1577
    MacroAssembler* masm) {
 
1578
  // ----------- S t a t e -------------
 
1579
  //  -- rbx     : target map
 
1580
  //  -- rdx     : receiver
 
1581
  //  -- rsp[0]  : return address
 
1582
  // -----------------------------------
 
1583
  // Must return the modified receiver in eax.
 
1584
  if (!FLAG_trace_elements_transitions) {
 
1585
    Label fail;
 
1586
    ElementsTransitionGenerator::GenerateDoubleToObject(masm, &fail);
 
1587
    __ movq(rax, rdx);
 
1588
    __ Ret();
 
1589
    __ bind(&fail);
 
1590
  }
 
1591
 
 
1592
  __ pop(rbx);
 
1593
  __ push(rdx);
 
1594
  __ push(rbx);  // return address
 
1595
  __ TailCallRuntime(Runtime::kTransitionElementsDoubleToObject, 1, 1);
 
1596
}
 
1597
 
 
1598
 
1565
1599
#undef __
1566
1600
 
1567
1601
 
1573
1607
    case Token::LT:
1574
1608
      return less;
1575
1609
    case Token::GT:
1576
 
      // Reverse left and right operands to obtain ECMA-262 conversion order.
1577
 
      return less;
 
1610
      return greater;
1578
1611
    case Token::LTE:
1579
 
      // Reverse left and right operands to obtain ECMA-262 conversion order.
1580
 
      return greater_equal;
 
1612
      return less_equal;
1581
1613
    case Token::GTE:
1582
1614
      return greater_equal;
1583
1615
    default: