Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/x64/lithium-codegen-x64.cc

Issue 7060010: Merge bleeding edge into the GC branch up to 7948. The asserts (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 619 matching lines...) Expand 10 before | Expand all | Expand 10 after
630 } 630 }
631 631
632 632
633 void LCodeGen::RecordSafepoint( 633 void LCodeGen::RecordSafepoint(
634 LPointerMap* pointers, 634 LPointerMap* pointers,
635 Safepoint::Kind kind, 635 Safepoint::Kind kind,
636 int arguments, 636 int arguments,
637 int deoptimization_index) { 637 int deoptimization_index) {
638 ASSERT(kind == expected_safepoint_kind_); 638 ASSERT(kind == expected_safepoint_kind_);
639 639
640 const ZoneList<LOperand*>* operands = pointers->operands(); 640 const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands();
641 641
642 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), 642 Safepoint safepoint = safepoints_.DefineSafepoint(masm(),
643 kind, arguments, deoptimization_index); 643 kind, arguments, deoptimization_index);
644 for (int i = 0; i < operands->length(); i++) { 644 for (int i = 0; i < operands->length(); i++) {
645 LOperand* pointer = operands->at(i); 645 LOperand* pointer = operands->at(i);
646 if (pointer->IsStackSlot()) { 646 if (pointer->IsStackSlot()) {
647 safepoint.DefinePointerSlot(pointer->index()); 647 safepoint.DefinePointerSlot(pointer->index());
648 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { 648 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
649 safepoint.DefinePointerRegister(ToRegister(pointer)); 649 safepoint.DefinePointerRegister(ToRegister(pointer));
650 } 650 }
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 778
779 void LCodeGen::DoModI(LModI* instr) { 779 void LCodeGen::DoModI(LModI* instr) {
780 if (instr->hydrogen()->HasPowerOf2Divisor()) { 780 if (instr->hydrogen()->HasPowerOf2Divisor()) {
781 Register dividend = ToRegister(instr->InputAt(0)); 781 Register dividend = ToRegister(instr->InputAt(0));
782 782
783 int32_t divisor = 783 int32_t divisor =
784 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); 784 HConstant::cast(instr->hydrogen()->right())->Integer32Value();
785 785
786 if (divisor < 0) divisor = -divisor; 786 if (divisor < 0) divisor = -divisor;
787 787
788 NearLabel positive_dividend, done; 788 Label positive_dividend, done;
789 __ testl(dividend, dividend); 789 __ testl(dividend, dividend);
790 __ j(not_sign, &positive_dividend); 790 __ j(not_sign, &positive_dividend, Label::kNear);
791 __ negl(dividend); 791 __ negl(dividend);
792 __ andl(dividend, Immediate(divisor - 1)); 792 __ andl(dividend, Immediate(divisor - 1));
793 __ negl(dividend); 793 __ negl(dividend);
794 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 794 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
795 __ j(not_zero, &done); 795 __ j(not_zero, &done, Label::kNear);
796 DeoptimizeIf(no_condition, instr->environment()); 796 DeoptimizeIf(no_condition, instr->environment());
797 } 797 }
798 __ bind(&positive_dividend); 798 __ bind(&positive_dividend);
799 __ andl(dividend, Immediate(divisor - 1)); 799 __ andl(dividend, Immediate(divisor - 1));
800 __ bind(&done); 800 __ bind(&done);
801 } else { 801 } else {
802 NearLabel done, remainder_eq_dividend, slow, do_subtraction, both_positive; 802 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive;
803 Register left_reg = ToRegister(instr->InputAt(0)); 803 Register left_reg = ToRegister(instr->InputAt(0));
804 Register right_reg = ToRegister(instr->InputAt(1)); 804 Register right_reg = ToRegister(instr->InputAt(1));
805 Register result_reg = ToRegister(instr->result()); 805 Register result_reg = ToRegister(instr->result());
806 806
807 ASSERT(left_reg.is(rax)); 807 ASSERT(left_reg.is(rax));
808 ASSERT(result_reg.is(rdx)); 808 ASSERT(result_reg.is(rdx));
809 ASSERT(!right_reg.is(rax)); 809 ASSERT(!right_reg.is(rax));
810 ASSERT(!right_reg.is(rdx)); 810 ASSERT(!right_reg.is(rdx));
811 811
812 // Check for x % 0. 812 // Check for x % 0.
813 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 813 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
814 __ testl(right_reg, right_reg); 814 __ testl(right_reg, right_reg);
815 DeoptimizeIf(zero, instr->environment()); 815 DeoptimizeIf(zero, instr->environment());
816 } 816 }
817 817
818 __ testl(left_reg, left_reg); 818 __ testl(left_reg, left_reg);
819 __ j(zero, &remainder_eq_dividend); 819 __ j(zero, &remainder_eq_dividend, Label::kNear);
820 __ j(sign, &slow); 820 __ j(sign, &slow, Label::kNear);
821 821
822 __ testl(right_reg, right_reg); 822 __ testl(right_reg, right_reg);
823 __ j(not_sign, &both_positive); 823 __ j(not_sign, &both_positive, Label::kNear);
824 // The sign of the divisor doesn't matter. 824 // The sign of the divisor doesn't matter.
825 __ neg(right_reg); 825 __ neg(right_reg);
826 826
827 __ bind(&both_positive); 827 __ bind(&both_positive);
828 // If the dividend is smaller than the nonnegative 828 // If the dividend is smaller than the nonnegative
829 // divisor, the dividend is the result. 829 // divisor, the dividend is the result.
830 __ cmpl(left_reg, right_reg); 830 __ cmpl(left_reg, right_reg);
831 __ j(less, &remainder_eq_dividend); 831 __ j(less, &remainder_eq_dividend, Label::kNear);
832 832
833 // Check if the divisor is a PowerOfTwo integer. 833 // Check if the divisor is a PowerOfTwo integer.
834 Register scratch = ToRegister(instr->TempAt(0)); 834 Register scratch = ToRegister(instr->TempAt(0));
835 __ movl(scratch, right_reg); 835 __ movl(scratch, right_reg);
836 __ subl(scratch, Immediate(1)); 836 __ subl(scratch, Immediate(1));
837 __ testl(scratch, right_reg); 837 __ testl(scratch, right_reg);
838 __ j(not_zero, &do_subtraction); 838 __ j(not_zero, &do_subtraction, Label::kNear);
839 __ andl(left_reg, scratch); 839 __ andl(left_reg, scratch);
840 __ jmp(&remainder_eq_dividend); 840 __ jmp(&remainder_eq_dividend, Label::kNear);
841 841
842 __ bind(&do_subtraction); 842 __ bind(&do_subtraction);
843 const int kUnfolds = 3; 843 const int kUnfolds = 3;
844 // Try a few subtractions of the dividend. 844 // Try a few subtractions of the dividend.
845 __ movl(scratch, left_reg); 845 __ movl(scratch, left_reg);
846 for (int i = 0; i < kUnfolds; i++) { 846 for (int i = 0; i < kUnfolds; i++) {
847 // Reduce the dividend by the divisor. 847 // Reduce the dividend by the divisor.
848 __ subl(left_reg, right_reg); 848 __ subl(left_reg, right_reg);
849 // Check if the dividend is less than the divisor. 849 // Check if the dividend is less than the divisor.
850 __ cmpl(left_reg, right_reg); 850 __ cmpl(left_reg, right_reg);
851 __ j(less, &remainder_eq_dividend); 851 __ j(less, &remainder_eq_dividend, Label::kNear);
852 } 852 }
853 __ movl(left_reg, scratch); 853 __ movl(left_reg, scratch);
854 854
855 // Slow case, using idiv instruction. 855 // Slow case, using idiv instruction.
856 __ bind(&slow); 856 __ bind(&slow);
857 // Sign extend eax to edx. 857 // Sign extend eax to edx.
858 // (We are using only the low 32 bits of the values.) 858 // (We are using only the low 32 bits of the values.)
859 __ cdq(); 859 __ cdq();
860 860
861 // Check for (0 % -x) that will produce negative zero. 861 // Check for (0 % -x) that will produce negative zero.
862 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 862 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
863 NearLabel positive_left; 863 Label positive_left;
864 NearLabel done; 864 Label done;
865 __ testl(left_reg, left_reg); 865 __ testl(left_reg, left_reg);
866 __ j(not_sign, &positive_left); 866 __ j(not_sign, &positive_left, Label::kNear);
867 __ idivl(right_reg); 867 __ idivl(right_reg);
868 868
869 // Test the remainder for 0, because then the result would be -0. 869 // Test the remainder for 0, because then the result would be -0.
870 __ testl(result_reg, result_reg); 870 __ testl(result_reg, result_reg);
871 __ j(not_zero, &done); 871 __ j(not_zero, &done, Label::kNear);
872 872
873 DeoptimizeIf(no_condition, instr->environment()); 873 DeoptimizeIf(no_condition, instr->environment());
874 __ bind(&positive_left); 874 __ bind(&positive_left);
875 __ idivl(right_reg); 875 __ idivl(right_reg);
876 __ bind(&done); 876 __ bind(&done);
877 } else { 877 } else {
878 __ idivl(right_reg); 878 __ idivl(right_reg);
879 } 879 }
880 __ jmp(&done); 880 __ jmp(&done, Label::kNear);
881 881
882 __ bind(&remainder_eq_dividend); 882 __ bind(&remainder_eq_dividend);
883 __ movl(result_reg, left_reg); 883 __ movl(result_reg, left_reg);
884 884
885 __ bind(&done); 885 __ bind(&done);
886 } 886 }
887 } 887 }
888 888
889 889
890 void LCodeGen::DoDivI(LDivI* instr) { 890 void LCodeGen::DoDivI(LDivI* instr) {
891 LOperand* right = instr->InputAt(1); 891 LOperand* right = instr->InputAt(1);
892 ASSERT(ToRegister(instr->result()).is(rax)); 892 ASSERT(ToRegister(instr->result()).is(rax));
893 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); 893 ASSERT(ToRegister(instr->InputAt(0)).is(rax));
894 ASSERT(!ToRegister(instr->InputAt(1)).is(rax)); 894 ASSERT(!ToRegister(instr->InputAt(1)).is(rax));
895 ASSERT(!ToRegister(instr->InputAt(1)).is(rdx)); 895 ASSERT(!ToRegister(instr->InputAt(1)).is(rdx));
896 896
897 Register left_reg = rax; 897 Register left_reg = rax;
898 898
899 // Check for x / 0. 899 // Check for x / 0.
900 Register right_reg = ToRegister(right); 900 Register right_reg = ToRegister(right);
901 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 901 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
902 __ testl(right_reg, right_reg); 902 __ testl(right_reg, right_reg);
903 DeoptimizeIf(zero, instr->environment()); 903 DeoptimizeIf(zero, instr->environment());
904 } 904 }
905 905
906 // Check for (0 / -x) that will produce negative zero. 906 // Check for (0 / -x) that will produce negative zero.
907 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 907 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
908 NearLabel left_not_zero; 908 Label left_not_zero;
909 __ testl(left_reg, left_reg); 909 __ testl(left_reg, left_reg);
910 __ j(not_zero, &left_not_zero); 910 __ j(not_zero, &left_not_zero, Label::kNear);
911 __ testl(right_reg, right_reg); 911 __ testl(right_reg, right_reg);
912 DeoptimizeIf(sign, instr->environment()); 912 DeoptimizeIf(sign, instr->environment());
913 __ bind(&left_not_zero); 913 __ bind(&left_not_zero);
914 } 914 }
915 915
916 // Check for (-kMinInt / -1). 916 // Check for (-kMinInt / -1).
917 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 917 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
918 NearLabel left_not_min_int; 918 Label left_not_min_int;
919 __ cmpl(left_reg, Immediate(kMinInt)); 919 __ cmpl(left_reg, Immediate(kMinInt));
920 __ j(not_zero, &left_not_min_int); 920 __ j(not_zero, &left_not_min_int, Label::kNear);
921 __ cmpl(right_reg, Immediate(-1)); 921 __ cmpl(right_reg, Immediate(-1));
922 DeoptimizeIf(zero, instr->environment()); 922 DeoptimizeIf(zero, instr->environment());
923 __ bind(&left_not_min_int); 923 __ bind(&left_not_min_int);
924 } 924 }
925 925
926 // Sign extend to rdx. 926 // Sign extend to rdx.
927 __ cdq(); 927 __ cdq();
928 __ idivl(right_reg); 928 __ idivl(right_reg);
929 929
930 // Deoptimize if remainder is not 0. 930 // Deoptimize if remainder is not 0.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
989 } else { 989 } else {
990 __ imull(left, ToRegister(right)); 990 __ imull(left, ToRegister(right));
991 } 991 }
992 992
993 if (can_overflow) { 993 if (can_overflow) {
994 DeoptimizeIf(overflow, instr->environment()); 994 DeoptimizeIf(overflow, instr->environment());
995 } 995 }
996 996
997 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 997 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
998 // Bail out if the result is supposed to be negative zero. 998 // Bail out if the result is supposed to be negative zero.
999 NearLabel done; 999 Label done;
1000 __ testl(left, left); 1000 __ testl(left, left);
1001 __ j(not_zero, &done); 1001 __ j(not_zero, &done, Label::kNear);
1002 if (right->IsConstantOperand()) { 1002 if (right->IsConstantOperand()) {
1003 if (ToInteger32(LConstantOperand::cast(right)) <= 0) { 1003 if (ToInteger32(LConstantOperand::cast(right)) <= 0) {
1004 DeoptimizeIf(no_condition, instr->environment()); 1004 DeoptimizeIf(no_condition, instr->environment());
1005 } 1005 }
1006 } else if (right->IsStackSlot()) { 1006 } else if (right->IsStackSlot()) {
1007 __ or_(kScratchRegister, ToOperand(right)); 1007 __ or_(kScratchRegister, ToOperand(right));
1008 DeoptimizeIf(sign, instr->environment()); 1008 DeoptimizeIf(sign, instr->environment());
1009 } else { 1009 } else {
1010 // Test the non-zero operand for negative sign. 1010 // Test the non-zero operand for negative sign.
1011 __ or_(kScratchRegister, ToRegister(right)); 1011 __ or_(kScratchRegister, ToRegister(right));
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
1196 Register result = ToRegister(instr->result()); 1196 Register result = ToRegister(instr->result());
1197 Register array = ToRegister(instr->InputAt(0)); 1197 Register array = ToRegister(instr->InputAt(0));
1198 __ movl(result, FieldOperand(array, ExternalPixelArray::kLengthOffset)); 1198 __ movl(result, FieldOperand(array, ExternalPixelArray::kLengthOffset));
1199 } 1199 }
1200 1200
1201 1201
1202 void LCodeGen::DoValueOf(LValueOf* instr) { 1202 void LCodeGen::DoValueOf(LValueOf* instr) {
1203 Register input = ToRegister(instr->InputAt(0)); 1203 Register input = ToRegister(instr->InputAt(0));
1204 Register result = ToRegister(instr->result()); 1204 Register result = ToRegister(instr->result());
1205 ASSERT(input.is(result)); 1205 ASSERT(input.is(result));
1206 NearLabel done; 1206 Label done;
1207 // If the object is a smi return the object. 1207 // If the object is a smi return the object.
1208 __ JumpIfSmi(input, &done); 1208 __ JumpIfSmi(input, &done, Label::kNear);
1209 1209
1210 // If the object is not a value type, return the object. 1210 // If the object is not a value type, return the object.
1211 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); 1211 __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister);
1212 __ j(not_equal, &done); 1212 __ j(not_equal, &done, Label::kNear);
1213 __ movq(result, FieldOperand(input, JSValue::kValueOffset)); 1213 __ movq(result, FieldOperand(input, JSValue::kValueOffset));
1214 1214
1215 __ bind(&done); 1215 __ bind(&done);
1216 } 1216 }
1217 1217
1218 1218
1219 void LCodeGen::DoBitNotI(LBitNotI* instr) { 1219 void LCodeGen::DoBitNotI(LBitNotI* instr) {
1220 LOperand* input = instr->InputAt(0); 1220 LOperand* input = instr->InputAt(0);
1221 ASSERT(input->Equals(instr->result())); 1221 ASSERT(input->Equals(instr->result()));
1222 __ not_(ToRegister(input)); 1222 __ not_(ToRegister(input));
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
1360 __ j(equal, false_label); 1360 __ j(equal, false_label);
1361 __ CompareRoot(reg, Heap::kTrueValueRootIndex); 1361 __ CompareRoot(reg, Heap::kTrueValueRootIndex);
1362 __ j(equal, true_label); 1362 __ j(equal, true_label);
1363 __ CompareRoot(reg, Heap::kFalseValueRootIndex); 1363 __ CompareRoot(reg, Heap::kFalseValueRootIndex);
1364 __ j(equal, false_label); 1364 __ j(equal, false_label);
1365 __ Cmp(reg, Smi::FromInt(0)); 1365 __ Cmp(reg, Smi::FromInt(0));
1366 __ j(equal, false_label); 1366 __ j(equal, false_label);
1367 __ JumpIfSmi(reg, true_label); 1367 __ JumpIfSmi(reg, true_label);
1368 1368
1369 // Test for double values. Plus/minus zero and NaN are false. 1369 // Test for double values. Plus/minus zero and NaN are false.
1370 NearLabel call_stub; 1370 Label call_stub;
1371 __ CompareRoot(FieldOperand(reg, HeapObject::kMapOffset), 1371 __ CompareRoot(FieldOperand(reg, HeapObject::kMapOffset),
1372 Heap::kHeapNumberMapRootIndex); 1372 Heap::kHeapNumberMapRootIndex);
1373 __ j(not_equal, &call_stub); 1373 __ j(not_equal, &call_stub, Label::kNear);
1374 1374
1375 // HeapNumber => false iff +0, -0, or NaN. These three cases set the 1375 // HeapNumber => false iff +0, -0, or NaN. These three cases set the
1376 // zero flag when compared to zero using ucomisd. 1376 // zero flag when compared to zero using ucomisd.
1377 __ xorps(xmm0, xmm0); 1377 __ xorps(xmm0, xmm0);
1378 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); 1378 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset));
1379 __ j(zero, false_label); 1379 __ j(zero, false_label);
1380 __ jmp(true_label); 1380 __ jmp(true_label);
1381 1381
1382 // The conversion stub doesn't cause garbage collections so it's 1382 // The conversion stub doesn't cause garbage collections so it's
1383 // safe to not record a safepoint after the call. 1383 // safe to not record a safepoint after the call.
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1477 __ cmpl(ToRegister(left), ToOperand(right)); 1477 __ cmpl(ToRegister(left), ToOperand(right));
1478 } 1478 }
1479 } 1479 }
1480 1480
1481 1481
1482 void LCodeGen::DoCmpID(LCmpID* instr) { 1482 void LCodeGen::DoCmpID(LCmpID* instr) {
1483 LOperand* left = instr->InputAt(0); 1483 LOperand* left = instr->InputAt(0);
1484 LOperand* right = instr->InputAt(1); 1484 LOperand* right = instr->InputAt(1);
1485 LOperand* result = instr->result(); 1485 LOperand* result = instr->result();
1486 1486
1487 NearLabel unordered; 1487 Label unordered;
1488 if (instr->is_double()) { 1488 if (instr->is_double()) {
1489 // Don't base result on EFLAGS when a NaN is involved. Instead 1489 // Don't base result on EFLAGS when a NaN is involved. Instead
1490 // jump to the unordered case, which produces a false value. 1490 // jump to the unordered case, which produces a false value.
1491 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); 1491 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
1492 __ j(parity_even, &unordered); 1492 __ j(parity_even, &unordered, Label::kNear);
1493 } else { 1493 } else {
1494 EmitCmpI(left, right); 1494 EmitCmpI(left, right);
1495 } 1495 }
1496 1496
1497 NearLabel done; 1497 Label done;
1498 Condition cc = TokenToCondition(instr->op(), instr->is_double()); 1498 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1499 __ LoadRoot(ToRegister(result), Heap::kTrueValueRootIndex); 1499 __ LoadRoot(ToRegister(result), Heap::kTrueValueRootIndex);
1500 __ j(cc, &done); 1500 __ j(cc, &done, Label::kNear);
1501 1501
1502 __ bind(&unordered); 1502 __ bind(&unordered);
1503 __ LoadRoot(ToRegister(result), Heap::kFalseValueRootIndex); 1503 __ LoadRoot(ToRegister(result), Heap::kFalseValueRootIndex);
1504 __ bind(&done); 1504 __ bind(&done);
1505 } 1505 }
1506 1506
1507 1507
1508 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 1508 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
1509 LOperand* left = instr->InputAt(0); 1509 LOperand* left = instr->InputAt(0);
1510 LOperand* right = instr->InputAt(1); 1510 LOperand* right = instr->InputAt(1);
(...skipping 12 matching lines...) Expand all
1523 Condition cc = TokenToCondition(instr->op(), instr->is_double()); 1523 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1524 EmitBranch(true_block, false_block, cc); 1524 EmitBranch(true_block, false_block, cc);
1525 } 1525 }
1526 1526
1527 1527
1528 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { 1528 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) {
1529 Register left = ToRegister(instr->InputAt(0)); 1529 Register left = ToRegister(instr->InputAt(0));
1530 Register right = ToRegister(instr->InputAt(1)); 1530 Register right = ToRegister(instr->InputAt(1));
1531 Register result = ToRegister(instr->result()); 1531 Register result = ToRegister(instr->result());
1532 1532
1533 NearLabel different, done; 1533 Label different, done;
1534 __ cmpq(left, right); 1534 __ cmpq(left, right);
1535 __ j(not_equal, &different); 1535 __ j(not_equal, &different, Label::kNear);
1536 __ LoadRoot(result, Heap::kTrueValueRootIndex); 1536 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1537 __ jmp(&done); 1537 __ jmp(&done, Label::kNear);
1538 __ bind(&different); 1538 __ bind(&different);
1539 __ LoadRoot(result, Heap::kFalseValueRootIndex); 1539 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1540 __ bind(&done); 1540 __ bind(&done);
1541 } 1541 }
1542 1542
1543 1543
1544 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { 1544 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
1545 Register left = ToRegister(instr->InputAt(0)); 1545 Register left = ToRegister(instr->InputAt(0));
1546 Register right = ToRegister(instr->InputAt(1)); 1546 Register right = ToRegister(instr->InputAt(1));
1547 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1547 int false_block = chunk_->LookupDestination(instr->false_block_id());
1548 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1548 int true_block = chunk_->LookupDestination(instr->true_block_id());
1549 1549
1550 __ cmpq(left, right); 1550 __ cmpq(left, right);
1551 EmitBranch(true_block, false_block, equal); 1551 EmitBranch(true_block, false_block, equal);
1552 } 1552 }
1553 1553
1554 1554
1555 void LCodeGen::DoCmpSymbolEq(LCmpSymbolEq* instr) {
1556 Register left = ToRegister(instr->InputAt(0));
1557 Register right = ToRegister(instr->InputAt(1));
1558 Register result = ToRegister(instr->result());
1559
1560 Label done;
1561 __ cmpq(left, right);
1562 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1563 __ j(not_equal, &done, Label::kNear);
1564 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1565 __ bind(&done);
1566 }
1567
1568
1569 void LCodeGen::DoCmpSymbolEqAndBranch(LCmpSymbolEqAndBranch* instr) {
1570 Register left = ToRegister(instr->InputAt(0));
1571 Register right = ToRegister(instr->InputAt(1));
1572 int false_block = chunk_->LookupDestination(instr->false_block_id());
1573 int true_block = chunk_->LookupDestination(instr->true_block_id());
1574
1575 __ cmpq(left, right);
1576 EmitBranch(true_block, false_block, equal);
1577 }
1578
1579
1555 void LCodeGen::DoIsNull(LIsNull* instr) { 1580 void LCodeGen::DoIsNull(LIsNull* instr) {
1556 Register reg = ToRegister(instr->InputAt(0)); 1581 Register reg = ToRegister(instr->InputAt(0));
1557 Register result = ToRegister(instr->result()); 1582 Register result = ToRegister(instr->result());
1558 1583
1559 // If the expression is known to be a smi, then it's 1584 // If the expression is known to be a smi, then it's
1560 // definitely not null. Materialize false. 1585 // definitely not null. Materialize false.
1561 // Consider adding other type and representation tests too. 1586 // Consider adding other type and representation tests too.
1562 if (instr->hydrogen()->value()->type().IsSmi()) { 1587 if (instr->hydrogen()->value()->type().IsSmi()) {
1563 __ LoadRoot(result, Heap::kFalseValueRootIndex); 1588 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1564 return; 1589 return;
1565 } 1590 }
1566 1591
1567 __ CompareRoot(reg, Heap::kNullValueRootIndex); 1592 __ CompareRoot(reg, Heap::kNullValueRootIndex);
1568 if (instr->is_strict()) { 1593 if (instr->is_strict()) {
1569 ASSERT(Heap::kTrueValueRootIndex >= 0); 1594 ASSERT(Heap::kTrueValueRootIndex >= 0);
1570 __ movl(result, Immediate(Heap::kTrueValueRootIndex)); 1595 __ movl(result, Immediate(Heap::kTrueValueRootIndex));
1571 NearLabel load; 1596 Label load;
1572 __ j(equal, &load); 1597 __ j(equal, &load, Label::kNear);
1573 __ Set(result, Heap::kFalseValueRootIndex); 1598 __ Set(result, Heap::kFalseValueRootIndex);
1574 __ bind(&load); 1599 __ bind(&load);
1575 __ LoadRootIndexed(result, result, 0); 1600 __ LoadRootIndexed(result, result, 0);
1576 } else { 1601 } else {
1577 NearLabel true_value, false_value, done; 1602 Label false_value, true_value, done;
1578 __ j(equal, &true_value); 1603 __ j(equal, &true_value, Label::kNear);
1579 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); 1604 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
1580 __ j(equal, &true_value); 1605 __ j(equal, &true_value, Label::kNear);
1581 __ JumpIfSmi(reg, &false_value); 1606 __ JumpIfSmi(reg, &false_value, Label::kNear);
1582 // Check for undetectable objects by looking in the bit field in 1607 // Check for undetectable objects by looking in the bit field in
1583 // the map. The object has already been smi checked. 1608 // the map. The object has already been smi checked.
1584 Register scratch = result; 1609 Register scratch = result;
1585 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 1610 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset));
1586 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), 1611 __ testb(FieldOperand(scratch, Map::kBitFieldOffset),
1587 Immediate(1 << Map::kIsUndetectable)); 1612 Immediate(1 << Map::kIsUndetectable));
1588 __ j(not_zero, &true_value); 1613 __ j(not_zero, &true_value, Label::kNear);
1589 __ bind(&false_value); 1614 __ bind(&false_value);
1590 __ LoadRoot(result, Heap::kFalseValueRootIndex); 1615 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1591 __ jmp(&done); 1616 __ jmp(&done, Label::kNear);
1592 __ bind(&true_value); 1617 __ bind(&true_value);
1593 __ LoadRoot(result, Heap::kTrueValueRootIndex); 1618 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1594 __ bind(&done); 1619 __ bind(&done);
1595 } 1620 }
1596 } 1621 }
1597 1622
1598 1623
1599 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { 1624 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
1600 Register reg = ToRegister(instr->InputAt(0)); 1625 Register reg = ToRegister(instr->InputAt(0));
1601 1626
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1716 Register input = ToRegister(instr->InputAt(0)); 1741 Register input = ToRegister(instr->InputAt(0));
1717 is_smi = masm()->CheckSmi(input); 1742 is_smi = masm()->CheckSmi(input);
1718 } else { 1743 } else {
1719 Operand input = ToOperand(instr->InputAt(0)); 1744 Operand input = ToOperand(instr->InputAt(0));
1720 is_smi = masm()->CheckSmi(input); 1745 is_smi = masm()->CheckSmi(input);
1721 } 1746 }
1722 EmitBranch(true_block, false_block, is_smi); 1747 EmitBranch(true_block, false_block, is_smi);
1723 } 1748 }
1724 1749
1725 1750
1751 void LCodeGen::DoIsUndetectable(LIsUndetectable* instr) {
1752 Register input = ToRegister(instr->InputAt(0));
1753 Register result = ToRegister(instr->result());
1754
1755 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1756 Label false_label, done;
1757 __ JumpIfSmi(input, &false_label);
1758 __ movq(result, FieldOperand(input, HeapObject::kMapOffset));
1759 __ testb(FieldOperand(result, Map::kBitFieldOffset),
1760 Immediate(1 << Map::kIsUndetectable));
1761 __ j(zero, &false_label);
1762 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1763 __ jmp(&done);
1764 __ bind(&false_label);
1765 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1766 __ bind(&done);
1767 }
1768
1769
1770 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
1771 Register input = ToRegister(instr->InputAt(0));
1772 Register temp = ToRegister(instr->TempAt(0));
1773
1774 int true_block = chunk_->LookupDestination(instr->true_block_id());
1775 int false_block = chunk_->LookupDestination(instr->false_block_id());
1776
1777 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block));
1778 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset));
1779 __ testb(FieldOperand(temp, Map::kBitFieldOffset),
1780 Immediate(1 << Map::kIsUndetectable));
1781 EmitBranch(true_block, false_block, not_zero);
1782 }
1783
1784
1726 static InstanceType TestType(HHasInstanceType* instr) { 1785 static InstanceType TestType(HHasInstanceType* instr) {
1727 InstanceType from = instr->from(); 1786 InstanceType from = instr->from();
1728 InstanceType to = instr->to(); 1787 InstanceType to = instr->to();
1729 if (from == FIRST_TYPE) return to; 1788 if (from == FIRST_TYPE) return to;
1730 ASSERT(from == to || to == LAST_TYPE); 1789 ASSERT(from == to || to == LAST_TYPE);
1731 return from; 1790 return from;
1732 } 1791 }
1733 1792
1734 1793
1735 static Condition BranchCondition(HHasInstanceType* instr) { 1794 static Condition BranchCondition(HHasInstanceType* instr) {
1736 InstanceType from = instr->from(); 1795 InstanceType from = instr->from();
1737 InstanceType to = instr->to(); 1796 InstanceType to = instr->to();
1738 if (from == to) return equal; 1797 if (from == to) return equal;
1739 if (to == LAST_TYPE) return above_equal; 1798 if (to == LAST_TYPE) return above_equal;
1740 if (from == FIRST_TYPE) return below_equal; 1799 if (from == FIRST_TYPE) return below_equal;
1741 UNREACHABLE(); 1800 UNREACHABLE();
1742 return equal; 1801 return equal;
1743 } 1802 }
1744 1803
1745 1804
1746 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { 1805 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
1747 Register input = ToRegister(instr->InputAt(0)); 1806 Register input = ToRegister(instr->InputAt(0));
1748 Register result = ToRegister(instr->result()); 1807 Register result = ToRegister(instr->result());
1749 1808
1750 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); 1809 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1751 __ testl(input, Immediate(kSmiTagMask)); 1810 __ testl(input, Immediate(kSmiTagMask));
1752 NearLabel done, is_false; 1811 Label done, is_false;
1753 __ j(zero, &is_false); 1812 __ j(zero, &is_false);
1754 __ CmpObjectType(input, TestType(instr->hydrogen()), result); 1813 __ CmpObjectType(input, TestType(instr->hydrogen()), result);
1755 __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false); 1814 __ j(NegateCondition(BranchCondition(instr->hydrogen())),
1815 &is_false, Label::kNear);
1756 __ LoadRoot(result, Heap::kTrueValueRootIndex); 1816 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1757 __ jmp(&done); 1817 __ jmp(&done, Label::kNear);
1758 __ bind(&is_false); 1818 __ bind(&is_false);
1759 __ LoadRoot(result, Heap::kFalseValueRootIndex); 1819 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1760 __ bind(&done); 1820 __ bind(&done);
1761 } 1821 }
1762 1822
1763 1823
1764 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 1824 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
1765 Register input = ToRegister(instr->InputAt(0)); 1825 Register input = ToRegister(instr->InputAt(0));
1766 1826
1767 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1827 int true_block = chunk_->LookupDestination(instr->true_block_id());
(...skipping 23 matching lines...) Expand all
1791 1851
1792 1852
1793 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { 1853 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
1794 Register input = ToRegister(instr->InputAt(0)); 1854 Register input = ToRegister(instr->InputAt(0));
1795 Register result = ToRegister(instr->result()); 1855 Register result = ToRegister(instr->result());
1796 1856
1797 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); 1857 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1798 __ LoadRoot(result, Heap::kTrueValueRootIndex); 1858 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1799 __ testl(FieldOperand(input, String::kHashFieldOffset), 1859 __ testl(FieldOperand(input, String::kHashFieldOffset),
1800 Immediate(String::kContainsCachedArrayIndexMask)); 1860 Immediate(String::kContainsCachedArrayIndexMask));
1801 NearLabel done; 1861 Label done;
1802 __ j(zero, &done); 1862 __ j(zero, &done, Label::kNear);
1803 __ LoadRoot(result, Heap::kFalseValueRootIndex); 1863 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1804 __ bind(&done); 1864 __ bind(&done);
1805 } 1865 }
1806 1866
1807 1867
1808 void LCodeGen::DoHasCachedArrayIndexAndBranch( 1868 void LCodeGen::DoHasCachedArrayIndexAndBranch(
1809 LHasCachedArrayIndexAndBranch* instr) { 1869 LHasCachedArrayIndexAndBranch* instr) {
1810 Register input = ToRegister(instr->InputAt(0)); 1870 Register input = ToRegister(instr->InputAt(0));
1811 1871
1812 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1872 int true_block = chunk_->LookupDestination(instr->true_block_id());
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1871 // End with the answer in the z flag. 1931 // End with the answer in the z flag.
1872 } 1932 }
1873 1933
1874 1934
1875 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { 1935 void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
1876 Register input = ToRegister(instr->InputAt(0)); 1936 Register input = ToRegister(instr->InputAt(0));
1877 Register result = ToRegister(instr->result()); 1937 Register result = ToRegister(instr->result());
1878 ASSERT(input.is(result)); 1938 ASSERT(input.is(result));
1879 Register temp = ToRegister(instr->TempAt(0)); 1939 Register temp = ToRegister(instr->TempAt(0));
1880 Handle<String> class_name = instr->hydrogen()->class_name(); 1940 Handle<String> class_name = instr->hydrogen()->class_name();
1881 NearLabel done; 1941 Label done;
1882 Label is_true, is_false; 1942 Label is_true, is_false;
1883 1943
1884 EmitClassOfTest(&is_true, &is_false, class_name, input, temp); 1944 EmitClassOfTest(&is_true, &is_false, class_name, input, temp);
1885 1945
1886 __ j(not_equal, &is_false); 1946 __ j(not_equal, &is_false);
1887 1947
1888 __ bind(&is_true); 1948 __ bind(&is_true);
1889 __ LoadRoot(result, Heap::kTrueValueRootIndex); 1949 __ LoadRoot(result, Heap::kTrueValueRootIndex);
1890 __ jmp(&done); 1950 __ jmp(&done, Label::kNear);
1891 1951
1892 __ bind(&is_false); 1952 __ bind(&is_false);
1893 __ LoadRoot(result, Heap::kFalseValueRootIndex); 1953 __ LoadRoot(result, Heap::kFalseValueRootIndex);
1894 __ bind(&done); 1954 __ bind(&done);
1895 } 1955 }
1896 1956
1897 1957
1898 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 1958 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
1899 Register input = ToRegister(instr->InputAt(0)); 1959 Register input = ToRegister(instr->InputAt(0));
1900 Register temp = ToRegister(instr->TempAt(0)); 1960 Register temp = ToRegister(instr->TempAt(0));
(...skipping 19 matching lines...) Expand all
1920 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); 1980 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map());
1921 EmitBranch(true_block, false_block, equal); 1981 EmitBranch(true_block, false_block, equal);
1922 } 1982 }
1923 1983
1924 1984
1925 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { 1985 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
1926 InstanceofStub stub(InstanceofStub::kNoFlags); 1986 InstanceofStub stub(InstanceofStub::kNoFlags);
1927 __ push(ToRegister(instr->InputAt(0))); 1987 __ push(ToRegister(instr->InputAt(0)));
1928 __ push(ToRegister(instr->InputAt(1))); 1988 __ push(ToRegister(instr->InputAt(1)));
1929 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 1989 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1930 NearLabel true_value, done; 1990 Label true_value, done;
1931 __ testq(rax, rax); 1991 __ testq(rax, rax);
1932 __ j(zero, &true_value); 1992 __ j(zero, &true_value, Label::kNear);
1933 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); 1993 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
1934 __ jmp(&done); 1994 __ jmp(&done, Label::kNear);
1935 __ bind(&true_value); 1995 __ bind(&true_value);
1936 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); 1996 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
1937 __ bind(&done); 1997 __ bind(&done);
1938 } 1998 }
1939 1999
1940 2000
1941 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { 2001 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) {
1942 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2002 int true_block = chunk_->LookupDestination(instr->true_block_id());
1943 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2003 int false_block = chunk_->LookupDestination(instr->false_block_id());
1944 2004
(...skipping 29 matching lines...) Expand all
1974 2034
1975 Label done, false_result; 2035 Label done, false_result;
1976 Register object = ToRegister(instr->InputAt(0)); 2036 Register object = ToRegister(instr->InputAt(0));
1977 2037
1978 // A Smi is not an instance of anything. 2038 // A Smi is not an instance of anything.
1979 __ JumpIfSmi(object, &false_result); 2039 __ JumpIfSmi(object, &false_result);
1980 2040
1981 // This is the inlined call site instanceof cache. The two occurences of the 2041 // This is the inlined call site instanceof cache. The two occurences of the
1982 // hole value will be patched to the last map/result pair generated by the 2042 // hole value will be patched to the last map/result pair generated by the
1983 // instanceof stub. 2043 // instanceof stub.
1984 NearLabel cache_miss; 2044 Label cache_miss;
1985 // Use a temp register to avoid memory operands with variable lengths. 2045 // Use a temp register to avoid memory operands with variable lengths.
1986 Register map = ToRegister(instr->TempAt(0)); 2046 Register map = ToRegister(instr->TempAt(0));
1987 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); 2047 __ movq(map, FieldOperand(object, HeapObject::kMapOffset));
1988 __ bind(deferred->map_check()); // Label for calculating code patching. 2048 __ bind(deferred->map_check()); // Label for calculating code patching.
1989 __ movq(kScratchRegister, factory()->the_hole_value(), 2049 __ movq(kScratchRegister, factory()->the_hole_value(),
1990 RelocInfo::EMBEDDED_OBJECT); 2050 RelocInfo::EMBEDDED_OBJECT);
1991 __ cmpq(map, kScratchRegister); // Patched to cached map. 2051 __ cmpq(map, kScratchRegister); // Patched to cached map.
1992 __ j(not_equal, &cache_miss); 2052 __ j(not_equal, &cache_miss, Label::kNear);
1993 // Patched to load either true or false. 2053 // Patched to load either true or false.
1994 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); 2054 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex);
1995 #ifdef DEBUG 2055 #ifdef DEBUG
1996 // Check that the code size between patch label and patch sites is invariant. 2056 // Check that the code size between patch label and patch sites is invariant.
1997 Label end_of_patched_code; 2057 Label end_of_patched_code;
1998 __ bind(&end_of_patched_code); 2058 __ bind(&end_of_patched_code);
1999 ASSERT(true); 2059 ASSERT(true);
2000 #endif 2060 #endif
2001 __ jmp(&done); 2061 __ jmp(&done);
2002 2062
2003 // The inlined call site cache did not match. Check for null and string 2063 // The inlined call site cache did not match. Check for null and string
2004 // before calling the deferred code. 2064 // before calling the deferred code.
2005 __ bind(&cache_miss); // Null is not an instance of anything. 2065 __ bind(&cache_miss); // Null is not an instance of anything.
2006 __ CompareRoot(object, Heap::kNullValueRootIndex); 2066 __ CompareRoot(object, Heap::kNullValueRootIndex);
2007 __ j(equal, &false_result); 2067 __ j(equal, &false_result, Label::kNear);
2008 2068
2009 // String values are not instances of anything. 2069 // String values are not instances of anything.
2010 __ JumpIfNotString(object, kScratchRegister, deferred->entry()); 2070 __ JumpIfNotString(object, kScratchRegister, deferred->entry());
2011 2071
2012 __ bind(&false_result); 2072 __ bind(&false_result);
2013 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); 2073 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
2014 2074
2015 __ bind(deferred->exit()); 2075 __ bind(deferred->exit());
2016 __ bind(&done); 2076 __ bind(&done);
2017 } 2077 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2064 void LCodeGen::DoCmpT(LCmpT* instr) { 2124 void LCodeGen::DoCmpT(LCmpT* instr) {
2065 Token::Value op = instr->op(); 2125 Token::Value op = instr->op();
2066 2126
2067 Handle<Code> ic = CompareIC::GetUninitialized(op); 2127 Handle<Code> ic = CompareIC::GetUninitialized(op);
2068 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2128 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2069 2129
2070 Condition condition = TokenToCondition(op, false); 2130 Condition condition = TokenToCondition(op, false);
2071 if (op == Token::GT || op == Token::LTE) { 2131 if (op == Token::GT || op == Token::LTE) {
2072 condition = ReverseCondition(condition); 2132 condition = ReverseCondition(condition);
2073 } 2133 }
2074 NearLabel true_value, done; 2134 Label true_value, done;
2075 __ testq(rax, rax); 2135 __ testq(rax, rax);
2076 __ j(condition, &true_value); 2136 __ j(condition, &true_value, Label::kNear);
2077 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); 2137 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex);
2078 __ jmp(&done); 2138 __ jmp(&done, Label::kNear);
2079 __ bind(&true_value); 2139 __ bind(&true_value);
2080 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); 2140 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex);
2081 __ bind(&done); 2141 __ bind(&done);
2082 } 2142 }
2083 2143
2084 2144
2085 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { 2145 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) {
2086 Token::Value op = instr->op(); 2146 Token::Value op = instr->op();
2087 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2147 int true_block = chunk_->LookupDestination(instr->true_block_id());
2088 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2148 int false_block = chunk_->LookupDestination(instr->false_block_id());
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
2241 2301
2242 int map_count = instr->hydrogen()->types()->length(); 2302 int map_count = instr->hydrogen()->types()->length();
2243 Handle<String> name = instr->hydrogen()->name(); 2303 Handle<String> name = instr->hydrogen()->name();
2244 2304
2245 if (map_count == 0) { 2305 if (map_count == 0) {
2246 ASSERT(instr->hydrogen()->need_generic()); 2306 ASSERT(instr->hydrogen()->need_generic());
2247 __ Move(rcx, instr->hydrogen()->name()); 2307 __ Move(rcx, instr->hydrogen()->name());
2248 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 2308 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
2249 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2309 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2250 } else { 2310 } else {
2251 NearLabel done; 2311 Label done;
2252 for (int i = 0; i < map_count - 1; ++i) { 2312 for (int i = 0; i < map_count - 1; ++i) {
2253 Handle<Map> map = instr->hydrogen()->types()->at(i); 2313 Handle<Map> map = instr->hydrogen()->types()->at(i);
2254 NearLabel next; 2314 Label next;
2255 __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); 2315 __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map);
2256 __ j(not_equal, &next); 2316 __ j(not_equal, &next, Label::kNear);
2257 EmitLoadFieldOrConstantFunction(result, object, map, name); 2317 EmitLoadFieldOrConstantFunction(result, object, map, name);
2258 __ jmp(&done); 2318 __ jmp(&done, Label::kNear);
2259 __ bind(&next); 2319 __ bind(&next);
2260 } 2320 }
2261 Handle<Map> map = instr->hydrogen()->types()->last(); 2321 Handle<Map> map = instr->hydrogen()->types()->last();
2262 __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); 2322 __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map);
2263 if (instr->hydrogen()->need_generic()) { 2323 if (instr->hydrogen()->need_generic()) {
2264 NearLabel generic; 2324 Label generic;
2265 __ j(not_equal, &generic); 2325 __ j(not_equal, &generic, Label::kNear);
2266 EmitLoadFieldOrConstantFunction(result, object, map, name); 2326 EmitLoadFieldOrConstantFunction(result, object, map, name);
2267 __ jmp(&done); 2327 __ jmp(&done, Label::kNear);
2268 __ bind(&generic); 2328 __ bind(&generic);
2269 __ Move(rcx, instr->hydrogen()->name()); 2329 __ Move(rcx, instr->hydrogen()->name());
2270 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 2330 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
2271 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2331 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2272 } else { 2332 } else {
2273 DeoptimizeIf(not_equal, instr->environment()); 2333 DeoptimizeIf(not_equal, instr->environment());
2274 EmitLoadFieldOrConstantFunction(result, object, map, name); 2334 EmitLoadFieldOrConstantFunction(result, object, map, name);
2275 } 2335 }
2276 __ bind(&done); 2336 __ bind(&done);
2277 } 2337 }
(...skipping 12 matching lines...) Expand all
2290 2350
2291 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { 2351 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
2292 Register function = ToRegister(instr->function()); 2352 Register function = ToRegister(instr->function());
2293 Register result = ToRegister(instr->result()); 2353 Register result = ToRegister(instr->result());
2294 2354
2295 // Check that the function really is a function. 2355 // Check that the function really is a function.
2296 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); 2356 __ CmpObjectType(function, JS_FUNCTION_TYPE, result);
2297 DeoptimizeIf(not_equal, instr->environment()); 2357 DeoptimizeIf(not_equal, instr->environment());
2298 2358
2299 // Check whether the function has an instance prototype. 2359 // Check whether the function has an instance prototype.
2300 NearLabel non_instance; 2360 Label non_instance;
2301 __ testb(FieldOperand(result, Map::kBitFieldOffset), 2361 __ testb(FieldOperand(result, Map::kBitFieldOffset),
2302 Immediate(1 << Map::kHasNonInstancePrototype)); 2362 Immediate(1 << Map::kHasNonInstancePrototype));
2303 __ j(not_zero, &non_instance); 2363 __ j(not_zero, &non_instance, Label::kNear);
2304 2364
2305 // Get the prototype or initial map from the function. 2365 // Get the prototype or initial map from the function.
2306 __ movq(result, 2366 __ movq(result,
2307 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 2367 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2308 2368
2309 // Check that the function has a prototype or an initial map. 2369 // Check that the function has a prototype or an initial map.
2310 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 2370 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
2311 DeoptimizeIf(equal, instr->environment()); 2371 DeoptimizeIf(equal, instr->environment());
2312 2372
2313 // If the function does not have an initial map, we're done. 2373 // If the function does not have an initial map, we're done.
2314 NearLabel done; 2374 Label done;
2315 __ CmpObjectType(result, MAP_TYPE, kScratchRegister); 2375 __ CmpObjectType(result, MAP_TYPE, kScratchRegister);
2316 __ j(not_equal, &done); 2376 __ j(not_equal, &done, Label::kNear);
2317 2377
2318 // Get the prototype from the initial map. 2378 // Get the prototype from the initial map.
2319 __ movq(result, FieldOperand(result, Map::kPrototypeOffset)); 2379 __ movq(result, FieldOperand(result, Map::kPrototypeOffset));
2320 __ jmp(&done); 2380 __ jmp(&done, Label::kNear);
2321 2381
2322 // Non-instance prototype: Fetch prototype from constructor field 2382 // Non-instance prototype: Fetch prototype from constructor field
2323 // in the function's map. 2383 // in the function's map.
2324 __ bind(&non_instance); 2384 __ bind(&non_instance);
2325 __ movq(result, FieldOperand(result, Map::kConstructorOffset)); 2385 __ movq(result, FieldOperand(result, Map::kConstructorOffset));
2326 2386
2327 // All done. 2387 // All done.
2328 __ bind(&done); 2388 __ bind(&done);
2329 } 2389 }
2330 2390
2331 2391
2332 void LCodeGen::DoLoadElements(LLoadElements* instr) { 2392 void LCodeGen::DoLoadElements(LLoadElements* instr) {
2333 Register result = ToRegister(instr->result()); 2393 Register result = ToRegister(instr->result());
2334 Register input = ToRegister(instr->InputAt(0)); 2394 Register input = ToRegister(instr->InputAt(0));
2335 __ movq(result, FieldOperand(input, JSObject::kElementsOffset)); 2395 __ movq(result, FieldOperand(input, JSObject::kElementsOffset));
2336 if (FLAG_debug_code) { 2396 if (FLAG_debug_code) {
2337 NearLabel done; 2397 Label done;
2338 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), 2398 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset),
2339 Heap::kFixedArrayMapRootIndex); 2399 Heap::kFixedArrayMapRootIndex);
2340 __ j(equal, &done); 2400 __ j(equal, &done, Label::kNear);
2341 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), 2401 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset),
2342 Heap::kFixedCOWArrayMapRootIndex); 2402 Heap::kFixedCOWArrayMapRootIndex);
2343 __ j(equal, &done); 2403 __ j(equal, &done, Label::kNear);
2344 Register temp((result.is(rax)) ? rbx : rax); 2404 Register temp((result.is(rax)) ? rbx : rax);
2345 __ push(temp); 2405 __ push(temp);
2346 __ movq(temp, FieldOperand(result, HeapObject::kMapOffset)); 2406 __ movq(temp, FieldOperand(result, HeapObject::kMapOffset));
2347 __ movzxbq(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 2407 __ movzxbq(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
2348 __ subq(temp, Immediate(FIRST_EXTERNAL_ARRAY_TYPE)); 2408 __ subq(temp, Immediate(FIRST_EXTERNAL_ARRAY_TYPE));
2349 __ cmpq(temp, Immediate(kExternalArrayTypeCount)); 2409 __ cmpq(temp, Immediate(kExternalArrayTypeCount));
2350 __ pop(temp); 2410 __ pop(temp);
2351 __ Check(below, "Check for fast elements failed."); 2411 __ Check(below, "Check for fast elements failed.");
2352 __ bind(&done); 2412 __ bind(&done);
2353 } 2413 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2387 Register result = ToRegister(instr->result()); 2447 Register result = ToRegister(instr->result());
2388 ASSERT(result.is(elements)); 2448 ASSERT(result.is(elements));
2389 2449
2390 // Load the result. 2450 // Load the result.
2391 __ movq(result, FieldOperand(elements, 2451 __ movq(result, FieldOperand(elements,
2392 key, 2452 key,
2393 times_pointer_size, 2453 times_pointer_size,
2394 FixedArray::kHeaderSize)); 2454 FixedArray::kHeaderSize));
2395 2455
2396 // Check for the hole value. 2456 // Check for the hole value.
2397 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 2457 if (instr->hydrogen()->RequiresHoleCheck()) {
2398 DeoptimizeIf(equal, instr->environment()); 2458 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
2459 DeoptimizeIf(equal, instr->environment());
2460 }
2461 }
2462
2463
2464 Operand LCodeGen::BuildExternalArrayOperand(LOperand* external_pointer,
2465 LOperand* key,
2466 ExternalArrayType array_type) {
2467 Register external_pointer_reg = ToRegister(external_pointer);
2468 int shift_size = ExternalArrayTypeToShiftSize(array_type);
2469 if (key->IsConstantOperand()) {
2470 int constant_value = ToInteger32(LConstantOperand::cast(key));
2471 if (constant_value & 0xF0000000) {
2472 Abort("array index constant value too big");
2473 }
2474 return Operand(external_pointer_reg, constant_value * (1 << shift_size));
2475 } else {
2476 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
2477 return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0);
2478 }
2399 } 2479 }
2400 2480
2401 2481
2402 void LCodeGen::DoLoadKeyedSpecializedArrayElement( 2482 void LCodeGen::DoLoadKeyedSpecializedArrayElement(
2403 LLoadKeyedSpecializedArrayElement* instr) { 2483 LLoadKeyedSpecializedArrayElement* instr) {
2404 Register external_pointer = ToRegister(instr->external_pointer());
2405 Register key = ToRegister(instr->key());
2406 ExternalArrayType array_type = instr->array_type(); 2484 ExternalArrayType array_type = instr->array_type();
2485 Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
2486 instr->key(), array_type));
2407 if (array_type == kExternalFloatArray) { 2487 if (array_type == kExternalFloatArray) {
2408 XMMRegister result(ToDoubleRegister(instr->result())); 2488 XMMRegister result(ToDoubleRegister(instr->result()));
2409 __ movss(result, Operand(external_pointer, key, times_4, 0)); 2489 __ movss(result, operand);
2410 __ cvtss2sd(result, result); 2490 __ cvtss2sd(result, result);
2411 } else if (array_type == kExternalDoubleArray) { 2491 } else if (array_type == kExternalDoubleArray) {
2412 __ movsd(ToDoubleRegister(instr->result()), 2492 __ movsd(ToDoubleRegister(instr->result()), operand);
2413 Operand(external_pointer, key, times_8, 0));
2414 } else { 2493 } else {
2415 Register result(ToRegister(instr->result())); 2494 Register result(ToRegister(instr->result()));
2416 switch (array_type) { 2495 switch (array_type) {
2417 case kExternalByteArray: 2496 case kExternalByteArray:
2418 __ movsxbq(result, Operand(external_pointer, key, times_1, 0)); 2497 __ movsxbq(result, operand);
2419 break; 2498 break;
2420 case kExternalUnsignedByteArray: 2499 case kExternalUnsignedByteArray:
2421 case kExternalPixelArray: 2500 case kExternalPixelArray:
2422 __ movzxbq(result, Operand(external_pointer, key, times_1, 0)); 2501 __ movzxbq(result, operand);
2423 break; 2502 break;
2424 case kExternalShortArray: 2503 case kExternalShortArray:
2425 __ movsxwq(result, Operand(external_pointer, key, times_2, 0)); 2504 __ movsxwq(result, operand);
2426 break; 2505 break;
2427 case kExternalUnsignedShortArray: 2506 case kExternalUnsignedShortArray:
2428 __ movzxwq(result, Operand(external_pointer, key, times_2, 0)); 2507 __ movzxwq(result, operand);
2429 break; 2508 break;
2430 case kExternalIntArray: 2509 case kExternalIntArray:
2431 __ movsxlq(result, Operand(external_pointer, key, times_4, 0)); 2510 __ movsxlq(result, operand);
2432 break; 2511 break;
2433 case kExternalUnsignedIntArray: 2512 case kExternalUnsignedIntArray:
2434 __ movl(result, Operand(external_pointer, key, times_4, 0)); 2513 __ movl(result, operand);
2435 __ testl(result, result); 2514 __ testl(result, result);
2436 // TODO(danno): we could be more clever here, perhaps having a special 2515 // TODO(danno): we could be more clever here, perhaps having a special
2437 // version of the stub that detects if the overflow case actually 2516 // version of the stub that detects if the overflow case actually
2438 // happens, and generate code that returns a double rather than int. 2517 // happens, and generate code that returns a double rather than int.
2439 DeoptimizeIf(negative, instr->environment()); 2518 DeoptimizeIf(negative, instr->environment());
2440 break; 2519 break;
2441 case kExternalFloatArray: 2520 case kExternalFloatArray:
2442 case kExternalDoubleArray: 2521 case kExternalDoubleArray:
2443 UNREACHABLE(); 2522 UNREACHABLE();
2444 break; 2523 break;
2445 } 2524 }
2446 } 2525 }
2447 } 2526 }
2448 2527
2449 2528
2450 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { 2529 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
2451 ASSERT(ToRegister(instr->object()).is(rdx)); 2530 ASSERT(ToRegister(instr->object()).is(rdx));
2452 ASSERT(ToRegister(instr->key()).is(rax)); 2531 ASSERT(ToRegister(instr->key()).is(rax));
2453 2532
2454 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2533 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2455 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2534 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2456 } 2535 }
2457 2536
2458 2537
2459 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { 2538 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
2460 Register result = ToRegister(instr->result()); 2539 Register result = ToRegister(instr->result());
2461 2540
2462 // Check for arguments adapter frame. 2541 // Check for arguments adapter frame.
2463 NearLabel done, adapted; 2542 Label done, adapted;
2464 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2543 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2465 __ Cmp(Operand(result, StandardFrameConstants::kContextOffset), 2544 __ Cmp(Operand(result, StandardFrameConstants::kContextOffset),
2466 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2545 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2467 __ j(equal, &adapted); 2546 __ j(equal, &adapted, Label::kNear);
2468 2547
2469 // No arguments adaptor frame. 2548 // No arguments adaptor frame.
2470 __ movq(result, rbp); 2549 __ movq(result, rbp);
2471 __ jmp(&done); 2550 __ jmp(&done, Label::kNear);
2472 2551
2473 // Arguments adaptor frame present. 2552 // Arguments adaptor frame present.
2474 __ bind(&adapted); 2553 __ bind(&adapted);
2475 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2554 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2476 2555
2477 // Result is the frame pointer for the frame if not adapted and for the real 2556 // Result is the frame pointer for the frame if not adapted and for the real
2478 // frame below the adaptor frame if adapted. 2557 // frame below the adaptor frame if adapted.
2479 __ bind(&done); 2558 __ bind(&done);
2480 } 2559 }
2481 2560
2482 2561
2483 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { 2562 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
2484 Register result = ToRegister(instr->result()); 2563 Register result = ToRegister(instr->result());
2485 2564
2486 NearLabel done; 2565 Label done;
2487 2566
2488 // If no arguments adaptor frame the number of arguments is fixed. 2567 // If no arguments adaptor frame the number of arguments is fixed.
2489 if (instr->InputAt(0)->IsRegister()) { 2568 if (instr->InputAt(0)->IsRegister()) {
2490 __ cmpq(rbp, ToRegister(instr->InputAt(0))); 2569 __ cmpq(rbp, ToRegister(instr->InputAt(0)));
2491 } else { 2570 } else {
2492 __ cmpq(rbp, ToOperand(instr->InputAt(0))); 2571 __ cmpq(rbp, ToOperand(instr->InputAt(0)));
2493 } 2572 }
2494 __ movl(result, Immediate(scope()->num_parameters())); 2573 __ movl(result, Immediate(scope()->num_parameters()));
2495 __ j(equal, &done); 2574 __ j(equal, &done, Label::kNear);
2496 2575
2497 // Arguments adaptor frame present. Get argument length from there. 2576 // Arguments adaptor frame present. Get argument length from there.
2498 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 2577 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
2499 __ SmiToInteger32(result, 2578 __ SmiToInteger32(result,
2500 Operand(result, 2579 Operand(result,
2501 ArgumentsAdaptorFrameConstants::kLengthOffset)); 2580 ArgumentsAdaptorFrameConstants::kLengthOffset));
2502 2581
2503 // Argument length is in result register. 2582 // Argument length is in result register.
2504 __ bind(&done); 2583 __ bind(&done);
2505 } 2584 }
2506 2585
2507 2586
2508 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 2587 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
2509 Register receiver = ToRegister(instr->receiver()); 2588 Register receiver = ToRegister(instr->receiver());
2510 Register function = ToRegister(instr->function()); 2589 Register function = ToRegister(instr->function());
2511 Register length = ToRegister(instr->length()); 2590 Register length = ToRegister(instr->length());
2512 Register elements = ToRegister(instr->elements()); 2591 Register elements = ToRegister(instr->elements());
2513 ASSERT(receiver.is(rax)); // Used for parameter count. 2592 ASSERT(receiver.is(rax)); // Used for parameter count.
2514 ASSERT(function.is(rdi)); // Required by InvokeFunction. 2593 ASSERT(function.is(rdi)); // Required by InvokeFunction.
2515 ASSERT(ToRegister(instr->result()).is(rax)); 2594 ASSERT(ToRegister(instr->result()).is(rax));
2516 2595
2517 // If the receiver is null or undefined, we have to pass the global object 2596 // If the receiver is null or undefined, we have to pass the global object
2518 // as a receiver. 2597 // as a receiver.
2519 NearLabel global_object, receiver_ok; 2598 Label global_object, receiver_ok;
2520 __ CompareRoot(receiver, Heap::kNullValueRootIndex); 2599 __ CompareRoot(receiver, Heap::kNullValueRootIndex);
2521 __ j(equal, &global_object); 2600 __ j(equal, &global_object, Label::kNear);
2522 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); 2601 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex);
2523 __ j(equal, &global_object); 2602 __ j(equal, &global_object, Label::kNear);
2524 2603
2525 // The receiver should be a JS object. 2604 // The receiver should be a JS object.
2526 Condition is_smi = __ CheckSmi(receiver); 2605 Condition is_smi = __ CheckSmi(receiver);
2527 DeoptimizeIf(is_smi, instr->environment()); 2606 DeoptimizeIf(is_smi, instr->environment());
2528 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister); 2607 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister);
2529 DeoptimizeIf(below, instr->environment()); 2608 DeoptimizeIf(below, instr->environment());
2530 __ jmp(&receiver_ok); 2609 __ jmp(&receiver_ok, Label::kNear);
2531 2610
2532 __ bind(&global_object); 2611 __ bind(&global_object);
2533 // TODO(kmillikin): We have a hydrogen value for the global object. See 2612 // TODO(kmillikin): We have a hydrogen value for the global object. See
2534 // if it's better to use it than to explicitly fetch it from the context 2613 // if it's better to use it than to explicitly fetch it from the context
2535 // here. 2614 // here.
2536 __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset)); 2615 __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset));
2537 __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); 2616 __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX));
2538 __ bind(&receiver_ok); 2617 __ bind(&receiver_ok);
2539 2618
2540 // Copy the arguments to this function possibly from the 2619 // Copy the arguments to this function possibly from the
2541 // adaptor frame below it. 2620 // adaptor frame below it.
2542 const uint32_t kArgumentsLimit = 1 * KB; 2621 const uint32_t kArgumentsLimit = 1 * KB;
2543 __ cmpq(length, Immediate(kArgumentsLimit)); 2622 __ cmpq(length, Immediate(kArgumentsLimit));
2544 DeoptimizeIf(above, instr->environment()); 2623 DeoptimizeIf(above, instr->environment());
2545 2624
2546 __ push(receiver); 2625 __ push(receiver);
2547 __ movq(receiver, length); 2626 __ movq(receiver, length);
2548 2627
2549 // Loop through the arguments pushing them onto the execution 2628 // Loop through the arguments pushing them onto the execution
2550 // stack. 2629 // stack.
2551 NearLabel invoke, loop; 2630 Label invoke, loop;
2552 // length is a small non-negative integer, due to the test above. 2631 // length is a small non-negative integer, due to the test above.
2553 __ testl(length, length); 2632 __ testl(length, length);
2554 __ j(zero, &invoke); 2633 __ j(zero, &invoke, Label::kNear);
2555 __ bind(&loop); 2634 __ bind(&loop);
2556 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); 2635 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
2557 __ decl(length); 2636 __ decl(length);
2558 __ j(not_zero, &loop); 2637 __ j(not_zero, &loop);
2559 2638
2560 // Invoke the function. 2639 // Invoke the function.
2561 __ bind(&invoke); 2640 __ bind(&invoke);
2562 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 2641 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
2563 LPointerMap* pointers = instr->pointer_map(); 2642 LPointerMap* pointers = instr->pointer_map();
2564 LEnvironment* env = instr->deoptimization_environment(); 2643 LEnvironment* env = instr->deoptimization_environment();
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
2791 2870
2792 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { 2871 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
2793 const XMMRegister xmm_scratch = xmm0; 2872 const XMMRegister xmm_scratch = xmm0;
2794 Register output_reg = ToRegister(instr->result()); 2873 Register output_reg = ToRegister(instr->result());
2795 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2874 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2796 2875
2797 Label done; 2876 Label done;
2798 // xmm_scratch = 0.5 2877 // xmm_scratch = 0.5
2799 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); 2878 __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE);
2800 __ movq(xmm_scratch, kScratchRegister); 2879 __ movq(xmm_scratch, kScratchRegister);
2801 NearLabel below_half; 2880 Label below_half;
2802 __ ucomisd(xmm_scratch, input_reg); 2881 __ ucomisd(xmm_scratch, input_reg);
2803 __ j(above, &below_half); // If input_reg is NaN, this doesn't jump. 2882 // If input_reg is NaN, this doesn't jump.
2883 __ j(above, &below_half, Label::kNear);
2804 // input = input + 0.5 2884 // input = input + 0.5
2805 // This addition might give a result that isn't the correct for 2885 // This addition might give a result that isn't the correct for
2806 // rounding, due to loss of precision, but only for a number that's 2886 // rounding, due to loss of precision, but only for a number that's
2807 // so big that the conversion below will overflow anyway. 2887 // so big that the conversion below will overflow anyway.
2808 __ addsd(input_reg, xmm_scratch); 2888 __ addsd(input_reg, xmm_scratch);
2809 // Compute Math.floor(input). 2889 // Compute Math.floor(input).
2810 // Use truncating instruction (OK because input is positive). 2890 // Use truncating instruction (OK because input is positive).
2811 __ cvttsd2si(output_reg, input_reg); 2891 __ cvttsd2si(output_reg, input_reg);
2812 // Overflow is signalled with minint. 2892 // Overflow is signalled with minint.
2813 __ cmpl(output_reg, Immediate(0x80000000)); 2893 __ cmpl(output_reg, Immediate(0x80000000));
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
3085 __ Move(rcx, instr->hydrogen()->name()); 3165 __ Move(rcx, instr->hydrogen()->name());
3086 Handle<Code> ic = instr->strict_mode() 3166 Handle<Code> ic = instr->strict_mode()
3087 ? isolate()->builtins()->StoreIC_Initialize_Strict() 3167 ? isolate()->builtins()->StoreIC_Initialize_Strict()
3088 : isolate()->builtins()->StoreIC_Initialize(); 3168 : isolate()->builtins()->StoreIC_Initialize();
3089 CallCode(ic, RelocInfo::CODE_TARGET, instr); 3169 CallCode(ic, RelocInfo::CODE_TARGET, instr);
3090 } 3170 }
3091 3171
3092 3172
3093 void LCodeGen::DoStoreKeyedSpecializedArrayElement( 3173 void LCodeGen::DoStoreKeyedSpecializedArrayElement(
3094 LStoreKeyedSpecializedArrayElement* instr) { 3174 LStoreKeyedSpecializedArrayElement* instr) {
3095 Register external_pointer = ToRegister(instr->external_pointer());
3096 Register key = ToRegister(instr->key());
3097 ExternalArrayType array_type = instr->array_type(); 3175 ExternalArrayType array_type = instr->array_type();
3176 Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
3177 instr->key(), array_type));
3098 if (array_type == kExternalFloatArray) { 3178 if (array_type == kExternalFloatArray) {
3099 XMMRegister value(ToDoubleRegister(instr->value())); 3179 XMMRegister value(ToDoubleRegister(instr->value()));
3100 __ cvtsd2ss(value, value); 3180 __ cvtsd2ss(value, value);
3101 __ movss(Operand(external_pointer, key, times_4, 0), value); 3181 __ movss(operand, value);
3102 } else if (array_type == kExternalDoubleArray) { 3182 } else if (array_type == kExternalDoubleArray) {
3103 __ movsd(Operand(external_pointer, key, times_8, 0), 3183 __ movsd(operand, ToDoubleRegister(instr->value()));
3104 ToDoubleRegister(instr->value()));
3105 } else { 3184 } else {
3106 Register value(ToRegister(instr->value())); 3185 Register value(ToRegister(instr->value()));
3107 switch (array_type) { 3186 switch (array_type) {
3108 case kExternalPixelArray: 3187 case kExternalPixelArray:
3109 { // Clamp the value to [0..255].
3110 NearLabel done;
3111 __ testl(value, Immediate(0xFFFFFF00));
3112 __ j(zero, &done);
3113 __ setcc(negative, value); // 1 if negative, 0 if positive.
3114 __ decb(value); // 0 if negative, 255 if positive.
3115 __ bind(&done);
3116 __ movb(Operand(external_pointer, key, times_1, 0), value);
3117 }
3118 break;
3119 case kExternalByteArray: 3188 case kExternalByteArray:
3120 case kExternalUnsignedByteArray: 3189 case kExternalUnsignedByteArray:
3121 __ movb(Operand(external_pointer, key, times_1, 0), value); 3190 __ movb(operand, value);
3122 break; 3191 break;
3123 case kExternalShortArray: 3192 case kExternalShortArray:
3124 case kExternalUnsignedShortArray: 3193 case kExternalUnsignedShortArray:
3125 __ movw(Operand(external_pointer, key, times_2, 0), value); 3194 __ movw(operand, value);
3126 break; 3195 break;
3127 case kExternalIntArray: 3196 case kExternalIntArray:
3128 case kExternalUnsignedIntArray: 3197 case kExternalUnsignedIntArray:
3129 __ movl(Operand(external_pointer, key, times_4, 0), value); 3198 __ movl(operand, value);
3130 break; 3199 break;
3131 case kExternalFloatArray: 3200 case kExternalFloatArray:
3132 case kExternalDoubleArray: 3201 case kExternalDoubleArray:
3133 UNREACHABLE(); 3202 UNREACHABLE();
3134 break; 3203 break;
3135 } 3204 }
3136 } 3205 }
3137 } 3206 }
3138 3207
3139 3208
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
3225 return; 3294 return;
3226 } 3295 }
3227 } else { 3296 } else {
3228 index = ToRegister(instr->index()); 3297 index = ToRegister(instr->index());
3229 } 3298 }
3230 Register result = ToRegister(instr->result()); 3299 Register result = ToRegister(instr->result());
3231 3300
3232 DeferredStringCharCodeAt* deferred = 3301 DeferredStringCharCodeAt* deferred =
3233 new DeferredStringCharCodeAt(this, instr); 3302 new DeferredStringCharCodeAt(this, instr);
3234 3303
3235 NearLabel flat_string, ascii_string, done; 3304 Label flat_string, ascii_string, done;
3236 3305
3237 // Fetch the instance type of the receiver into result register. 3306 // Fetch the instance type of the receiver into result register.
3238 __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); 3307 __ movq(result, FieldOperand(string, HeapObject::kMapOffset));
3239 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); 3308 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
3240 3309
3241 // We need special handling for non-sequential strings. 3310 // We need special handling for non-sequential strings.
3242 STATIC_ASSERT(kSeqStringTag == 0); 3311 STATIC_ASSERT(kSeqStringTag == 0);
3243 __ testb(result, Immediate(kStringRepresentationMask)); 3312 __ testb(result, Immediate(kStringRepresentationMask));
3244 __ j(zero, &flat_string); 3313 __ j(zero, &flat_string, Label::kNear);
3245 3314
3246 // Handle cons strings and go to deferred code for the rest. 3315 // Handle cons strings and go to deferred code for the rest.
3247 __ testb(result, Immediate(kIsConsStringMask)); 3316 __ testb(result, Immediate(kIsConsStringMask));
3248 __ j(zero, deferred->entry()); 3317 __ j(zero, deferred->entry());
3249 3318
3250 // ConsString. 3319 // ConsString.
3251 // Check whether the right hand side is the empty string (i.e. if 3320 // Check whether the right hand side is the empty string (i.e. if
3252 // this is really a flat string in a cons string). If that is not 3321 // this is really a flat string in a cons string). If that is not
3253 // the case we would rather go to the runtime system now to flatten 3322 // the case we would rather go to the runtime system now to flatten
3254 // the string. 3323 // the string.
3255 __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset), 3324 __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset),
3256 Heap::kEmptyStringRootIndex); 3325 Heap::kEmptyStringRootIndex);
3257 __ j(not_equal, deferred->entry()); 3326 __ j(not_equal, deferred->entry());
3258 // Get the first of the two strings and load its instance type. 3327 // Get the first of the two strings and load its instance type.
3259 __ movq(string, FieldOperand(string, ConsString::kFirstOffset)); 3328 __ movq(string, FieldOperand(string, ConsString::kFirstOffset));
3260 __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); 3329 __ movq(result, FieldOperand(string, HeapObject::kMapOffset));
3261 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); 3330 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
3262 // If the first cons component is also non-flat, then go to runtime. 3331 // If the first cons component is also non-flat, then go to runtime.
3263 STATIC_ASSERT(kSeqStringTag == 0); 3332 STATIC_ASSERT(kSeqStringTag == 0);
3264 __ testb(result, Immediate(kStringRepresentationMask)); 3333 __ testb(result, Immediate(kStringRepresentationMask));
3265 __ j(not_zero, deferred->entry()); 3334 __ j(not_zero, deferred->entry());
3266 3335
3267 // Check for ASCII or two-byte string. 3336 // Check for ASCII or two-byte string.
3268 __ bind(&flat_string); 3337 __ bind(&flat_string);
3269 STATIC_ASSERT(kAsciiStringTag != 0); 3338 STATIC_ASSERT(kAsciiStringTag != 0);
3270 __ testb(result, Immediate(kStringEncodingMask)); 3339 __ testb(result, Immediate(kStringEncodingMask));
3271 __ j(not_zero, &ascii_string); 3340 __ j(not_zero, &ascii_string, Label::kNear);
3272 3341
3273 // Two-byte string. 3342 // Two-byte string.
3274 // Load the two-byte character code into the result register. 3343 // Load the two-byte character code into the result register.
3275 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 3344 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3276 if (instr->index()->IsConstantOperand()) { 3345 if (instr->index()->IsConstantOperand()) {
3277 __ movzxwl(result, 3346 __ movzxwl(result,
3278 FieldOperand(string, 3347 FieldOperand(string,
3279 SeqTwoByteString::kHeaderSize + 3348 SeqTwoByteString::kHeaderSize +
3280 (kUC16Size * const_index))); 3349 (kUC16Size * const_index)));
3281 } else { 3350 } else {
3282 __ movzxwl(result, FieldOperand(string, 3351 __ movzxwl(result, FieldOperand(string,
3283 index, 3352 index,
3284 times_2, 3353 times_2,
3285 SeqTwoByteString::kHeaderSize)); 3354 SeqTwoByteString::kHeaderSize));
3286 } 3355 }
3287 __ jmp(&done); 3356 __ jmp(&done, Label::kNear);
3288 3357
3289 // ASCII string. 3358 // ASCII string.
3290 // Load the byte into the result register. 3359 // Load the byte into the result register.
3291 __ bind(&ascii_string); 3360 __ bind(&ascii_string);
3292 if (instr->index()->IsConstantOperand()) { 3361 if (instr->index()->IsConstantOperand()) {
3293 __ movzxbl(result, FieldOperand(string, 3362 __ movzxbl(result, FieldOperand(string,
3294 SeqAsciiString::kHeaderSize + const_index)); 3363 SeqAsciiString::kHeaderSize + const_index));
3295 } else { 3364 } else {
3296 __ movzxbl(result, FieldOperand(string, 3365 __ movzxbl(result, FieldOperand(string,
3297 index, 3366 index,
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
3467 Condition is_smi = __ CheckSmi(input); 3536 Condition is_smi = __ CheckSmi(input);
3468 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); 3537 DeoptimizeIf(NegateCondition(is_smi), instr->environment());
3469 } 3538 }
3470 __ SmiToInteger32(input, input); 3539 __ SmiToInteger32(input, input);
3471 } 3540 }
3472 3541
3473 3542
3474 void LCodeGen::EmitNumberUntagD(Register input_reg, 3543 void LCodeGen::EmitNumberUntagD(Register input_reg,
3475 XMMRegister result_reg, 3544 XMMRegister result_reg,
3476 LEnvironment* env) { 3545 LEnvironment* env) {
3477 NearLabel load_smi, heap_number, done; 3546 Label load_smi, heap_number, done;
3478 3547
3479 // Smi check. 3548 // Smi check.
3480 __ JumpIfSmi(input_reg, &load_smi); 3549 __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
3481 3550
3482 // Heap number map check. 3551 // Heap number map check.
3483 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 3552 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
3484 Heap::kHeapNumberMapRootIndex); 3553 Heap::kHeapNumberMapRootIndex);
3485 __ j(equal, &heap_number); 3554 __ j(equal, &heap_number, Label::kNear);
3486 3555
3487 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); 3556 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
3488 DeoptimizeIf(not_equal, env); 3557 DeoptimizeIf(not_equal, env);
3489 3558
3490 // Convert undefined to NaN. Compute NaN as 0/0. 3559 // Convert undefined to NaN. Compute NaN as 0/0.
3491 __ xorps(result_reg, result_reg); 3560 __ xorps(result_reg, result_reg);
3492 __ divsd(result_reg, result_reg); 3561 __ divsd(result_reg, result_reg);
3493 __ jmp(&done); 3562 __ jmp(&done, Label::kNear);
3494 3563
3495 // Heap number to XMM conversion. 3564 // Heap number to XMM conversion.
3496 __ bind(&heap_number); 3565 __ bind(&heap_number);
3497 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); 3566 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
3498 __ jmp(&done); 3567 __ jmp(&done, Label::kNear);
3499 3568
3500 // Smi to XMM conversion 3569 // Smi to XMM conversion
3501 __ bind(&load_smi); 3570 __ bind(&load_smi);
3502 __ SmiToInteger32(kScratchRegister, input_reg); 3571 __ SmiToInteger32(kScratchRegister, input_reg);
3503 __ cvtlsi2sd(result_reg, kScratchRegister); 3572 __ cvtlsi2sd(result_reg, kScratchRegister);
3504 __ bind(&done); 3573 __ bind(&done);
3505 } 3574 }
3506 3575
3507 3576
3508 class DeferredTaggedToI: public LDeferredCode { 3577 class DeferredTaggedToI: public LDeferredCode {
3509 public: 3578 public:
3510 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 3579 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
3511 : LDeferredCode(codegen), instr_(instr) { } 3580 : LDeferredCode(codegen), instr_(instr) { }
3512 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } 3581 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); }
3513 private: 3582 private:
3514 LTaggedToI* instr_; 3583 LTaggedToI* instr_;
3515 }; 3584 };
3516 3585
3517 3586
3518 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { 3587 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
3519 NearLabel done, heap_number; 3588 Label done, heap_number;
3520 Register input_reg = ToRegister(instr->InputAt(0)); 3589 Register input_reg = ToRegister(instr->InputAt(0));
3521 3590
3522 // Heap number map check. 3591 // Heap number map check.
3523 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 3592 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
3524 Heap::kHeapNumberMapRootIndex); 3593 Heap::kHeapNumberMapRootIndex);
3525 3594
3526 if (instr->truncating()) { 3595 if (instr->truncating()) {
3527 __ j(equal, &heap_number); 3596 __ j(equal, &heap_number, Label::kNear);
3528 // Check for undefined. Undefined is converted to zero for truncating 3597 // Check for undefined. Undefined is converted to zero for truncating
3529 // conversions. 3598 // conversions.
3530 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); 3599 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
3531 DeoptimizeIf(not_equal, instr->environment()); 3600 DeoptimizeIf(not_equal, instr->environment());
3532 __ Set(input_reg, 0); 3601 __ Set(input_reg, 0);
3533 __ jmp(&done); 3602 __ jmp(&done, Label::kNear);
3534 3603
3535 __ bind(&heap_number); 3604 __ bind(&heap_number);
3536 3605
3537 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 3606 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
3538 __ cvttsd2siq(input_reg, xmm0); 3607 __ cvttsd2siq(input_reg, xmm0);
3539 __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); 3608 __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000));
3540 __ cmpq(input_reg, kScratchRegister); 3609 __ cmpq(input_reg, kScratchRegister);
3541 DeoptimizeIf(equal, instr->environment()); 3610 DeoptimizeIf(equal, instr->environment());
3542 } else { 3611 } else {
3543 // Deoptimize if we don't have a heap number. 3612 // Deoptimize if we don't have a heap number.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
3604 __ movq(kScratchRegister, V8_INT64_C(0x8000000000000000), RelocInfo::NONE); 3673 __ movq(kScratchRegister, V8_INT64_C(0x8000000000000000), RelocInfo::NONE);
3605 __ cmpq(result_reg, kScratchRegister); 3674 __ cmpq(result_reg, kScratchRegister);
3606 DeoptimizeIf(equal, instr->environment()); 3675 DeoptimizeIf(equal, instr->environment());
3607 } else { 3676 } else {
3608 __ cvttsd2si(result_reg, input_reg); 3677 __ cvttsd2si(result_reg, input_reg);
3609 __ cvtlsi2sd(xmm0, result_reg); 3678 __ cvtlsi2sd(xmm0, result_reg);
3610 __ ucomisd(xmm0, input_reg); 3679 __ ucomisd(xmm0, input_reg);
3611 DeoptimizeIf(not_equal, instr->environment()); 3680 DeoptimizeIf(not_equal, instr->environment());
3612 DeoptimizeIf(parity_even, instr->environment()); // NaN. 3681 DeoptimizeIf(parity_even, instr->environment()); // NaN.
3613 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3682 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3614 NearLabel done; 3683 Label done;
3615 // The integer converted back is equal to the original. We 3684 // The integer converted back is equal to the original. We
3616 // only have to test if we got -0 as an input. 3685 // only have to test if we got -0 as an input.
3617 __ testl(result_reg, result_reg); 3686 __ testl(result_reg, result_reg);
3618 __ j(not_zero, &done); 3687 __ j(not_zero, &done, Label::kNear);
3619 __ movmskpd(result_reg, input_reg); 3688 __ movmskpd(result_reg, input_reg);
3620 // Bit 0 contains the sign of the double in input_reg. 3689 // Bit 0 contains the sign of the double in input_reg.
3621 // If input was positive, we are ok and return 0, otherwise 3690 // If input was positive, we are ok and return 0, otherwise
3622 // deoptimize. 3691 // deoptimize.
3623 __ andl(result_reg, Immediate(1)); 3692 __ andl(result_reg, Immediate(1));
3624 DeoptimizeIf(not_zero, instr->environment()); 3693 DeoptimizeIf(not_zero, instr->environment());
3625 __ bind(&done); 3694 __ bind(&done);
3626 } 3695 }
3627 } 3696 }
3628 } 3697 }
3629 3698
3630 3699
3631 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 3700 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
3632 LOperand* input = instr->InputAt(0); 3701 LOperand* input = instr->InputAt(0);
3633 Condition cc = masm()->CheckSmi(ToRegister(input)); 3702 Condition cc = masm()->CheckSmi(ToRegister(input));
3634 DeoptimizeIf(NegateCondition(cc), instr->environment()); 3703 DeoptimizeIf(NegateCondition(cc), instr->environment());
3635 } 3704 }
3636 3705
3637 3706
3638 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 3707 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
3639 LOperand* input = instr->InputAt(0); 3708 LOperand* input = instr->InputAt(0);
3640 Condition cc = masm()->CheckSmi(ToRegister(input)); 3709 Condition cc = masm()->CheckSmi(ToRegister(input));
3641 DeoptimizeIf(cc, instr->environment()); 3710 DeoptimizeIf(cc, instr->environment());
3642 } 3711 }
3643 3712
3644 3713
3645 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 3714 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
3646 Register input = ToRegister(instr->InputAt(0)); 3715 Register input = ToRegister(instr->InputAt(0));
3647 InstanceType first = instr->hydrogen()->first();
3648 InstanceType last = instr->hydrogen()->last();
3649 3716
3650 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); 3717 __ movq(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset));
3651 3718
3652 // If there is only one type in the interval check for equality. 3719 if (instr->hydrogen()->is_interval_check()) {
3653 if (first == last) { 3720 InstanceType first;
3721 InstanceType last;
3722 instr->hydrogen()->GetCheckInterval(&first, &last);
3723
3654 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 3724 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
3655 Immediate(static_cast<int8_t>(first))); 3725 Immediate(static_cast<int8_t>(first)));
3656 DeoptimizeIf(not_equal, instr->environment()); 3726
3657 } else if (first == FIRST_STRING_TYPE && last == LAST_STRING_TYPE) { 3727 // If there is only one type in the interval check for equality.
3658 // String has a dedicated bit in instance type. 3728 if (first == last) {
3659 __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 3729 DeoptimizeIf(not_equal, instr->environment());
3660 Immediate(kIsNotStringMask)); 3730 } else {
3661 DeoptimizeIf(not_zero, instr->environment()); 3731 DeoptimizeIf(below, instr->environment());
3732 // Omit check for the last type.
3733 if (last != LAST_TYPE) {
3734 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
3735 Immediate(static_cast<int8_t>(last)));
3736 DeoptimizeIf(above, instr->environment());
3737 }
3738 }
3662 } else { 3739 } else {
3663 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 3740 uint8_t mask;
3664 Immediate(static_cast<int8_t>(first))); 3741 uint8_t tag;
3665 DeoptimizeIf(below, instr->environment()); 3742 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
3666 // Omit check for the last type. 3743
3667 if (last != LAST_TYPE) { 3744 if (IsPowerOf2(mask)) {
3668 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 3745 ASSERT(tag == 0 || IsPowerOf2(tag));
3669 Immediate(static_cast<int8_t>(last))); 3746 __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
3670 DeoptimizeIf(above, instr->environment()); 3747 Immediate(mask));
3748 DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment());
3749 } else {
3750 __ movzxbl(kScratchRegister,
3751 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset));
3752 __ andb(kScratchRegister, Immediate(mask));
3753 __ cmpb(kScratchRegister, Immediate(tag));
3754 DeoptimizeIf(not_equal, instr->environment());
3671 } 3755 }
3672 } 3756 }
3673 } 3757 }
3674 3758
3675 3759
3676 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { 3760 void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
3677 ASSERT(instr->InputAt(0)->IsRegister()); 3761 ASSERT(instr->InputAt(0)->IsRegister());
3678 Register reg = ToRegister(instr->InputAt(0)); 3762 Register reg = ToRegister(instr->InputAt(0));
3679 __ Cmp(reg, instr->hydrogen()->target()); 3763 __ Cmp(reg, instr->hydrogen()->target());
3680 DeoptimizeIf(not_equal, instr->environment()); 3764 DeoptimizeIf(not_equal, instr->environment());
3681 } 3765 }
3682 3766
3683 3767
3684 void LCodeGen::DoCheckMap(LCheckMap* instr) { 3768 void LCodeGen::DoCheckMap(LCheckMap* instr) {
3685 LOperand* input = instr->InputAt(0); 3769 LOperand* input = instr->InputAt(0);
3686 ASSERT(input->IsRegister()); 3770 ASSERT(input->IsRegister());
3687 Register reg = ToRegister(input); 3771 Register reg = ToRegister(input);
3688 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), 3772 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset),
3689 instr->hydrogen()->map()); 3773 instr->hydrogen()->map());
3690 DeoptimizeIf(not_equal, instr->environment()); 3774 DeoptimizeIf(not_equal, instr->environment());
3691 } 3775 }
3692 3776
3693 3777
3778 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
3779 XMMRegister value_reg = ToDoubleRegister(instr->unclamped());
3780 Register result_reg = ToRegister(instr->result());
3781 Register temp_reg = ToRegister(instr->TempAt(0));
3782 __ ClampDoubleToUint8(value_reg, xmm0, result_reg, temp_reg);
3783 }
3784
3785
3786 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
3787 ASSERT(instr->unclamped()->Equals(instr->result()));
3788 Register value_reg = ToRegister(instr->result());
3789 __ ClampUint8(value_reg);
3790 }
3791
3792
3793 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
3794 ASSERT(instr->unclamped()->Equals(instr->result()));
3795 Register input_reg = ToRegister(instr->unclamped());
3796 Register temp_reg = ToRegister(instr->TempAt(0));
3797 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->TempAt(1));
3798 Label is_smi, done, heap_number;
3799
3800 __ JumpIfSmi(input_reg, &is_smi);
3801
3802 // Check for heap number
3803 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
3804 factory()->heap_number_map());
3805 __ j(equal, &heap_number, Label::kNear);
3806
3807 // Check for undefined. Undefined is converted to zero for clamping
3808 // conversions.
3809 __ Cmp(input_reg, factory()->undefined_value());
3810 DeoptimizeIf(not_equal, instr->environment());
3811 __ movq(input_reg, Immediate(0));
3812 __ jmp(&done, Label::kNear);
3813
3814 // Heap number
3815 __ bind(&heap_number);
3816 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
3817 __ ClampDoubleToUint8(xmm0, temp_xmm_reg, input_reg, temp_reg);
3818 __ jmp(&done, Label::kNear);
3819
3820 // smi
3821 __ bind(&is_smi);
3822 __ SmiToInteger32(input_reg, input_reg);
3823 __ ClampUint8(input_reg);
3824
3825 __ bind(&done);
3826 }
3827
3828
3694 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) { 3829 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) {
3695 if (heap()->InNewSpace(*object)) { 3830 if (heap()->InNewSpace(*object)) {
3696 Handle<JSGlobalPropertyCell> cell = 3831 Handle<JSGlobalPropertyCell> cell =
3697 factory()->NewJSGlobalPropertyCell(object); 3832 factory()->NewJSGlobalPropertyCell(object);
3698 __ movq(result, cell, RelocInfo::GLOBAL_PROPERTY_CELL); 3833 __ movq(result, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
3699 __ movq(result, Operand(result, 0)); 3834 __ movq(result, Operand(result, 0));
3700 } else { 3835 } else {
3701 __ Move(result, object); 3836 __ Move(result, object);
3702 } 3837 }
3703 } 3838 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
3776 3911
3777 3912
3778 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { 3913 void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
3779 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); 3914 ASSERT(ToRegister(instr->InputAt(0)).is(rax));
3780 __ push(rax); 3915 __ push(rax);
3781 CallRuntime(Runtime::kToFastProperties, 1, instr); 3916 CallRuntime(Runtime::kToFastProperties, 1, instr);
3782 } 3917 }
3783 3918
3784 3919
3785 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { 3920 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
3786 NearLabel materialized; 3921 Label materialized;
3787 // Registers will be used as follows: 3922 // Registers will be used as follows:
3788 // rdi = JS function. 3923 // rdi = JS function.
3789 // rcx = literals array. 3924 // rcx = literals array.
3790 // rbx = regexp literal. 3925 // rbx = regexp literal.
3791 // rax = regexp literal clone. 3926 // rax = regexp literal clone.
3792 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 3927 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
3793 __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 3928 __ movq(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
3794 int literal_offset = FixedArray::kHeaderSize + 3929 int literal_offset = FixedArray::kHeaderSize +
3795 instr->hydrogen()->literal_index() * kPointerSize; 3930 instr->hydrogen()->literal_index() * kPointerSize;
3796 __ movq(rbx, FieldOperand(rcx, literal_offset)); 3931 __ movq(rbx, FieldOperand(rcx, literal_offset));
3797 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); 3932 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
3798 __ j(not_equal, &materialized); 3933 __ j(not_equal, &materialized, Label::kNear);
3799 3934
3800 // Create regexp literal using runtime function 3935 // Create regexp literal using runtime function
3801 // Result will be in rax. 3936 // Result will be in rax.
3802 __ push(rcx); 3937 __ push(rcx);
3803 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); 3938 __ Push(Smi::FromInt(instr->hydrogen()->literal_index()));
3804 __ Push(instr->hydrogen()->pattern()); 3939 __ Push(instr->hydrogen()->pattern());
3805 __ Push(instr->hydrogen()->flags()); 3940 __ Push(instr->hydrogen()->flags());
3806 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); 3941 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
3807 __ movq(rbx, rax); 3942 __ movq(rbx, rax);
3808 3943
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
3860 EmitPushTaggedOperand(input); 3995 EmitPushTaggedOperand(input);
3861 CallRuntime(Runtime::kTypeof, 1, instr); 3996 CallRuntime(Runtime::kTypeof, 1, instr);
3862 } 3997 }
3863 3998
3864 3999
3865 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { 4000 void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
3866 Register input = ToRegister(instr->InputAt(0)); 4001 Register input = ToRegister(instr->InputAt(0));
3867 Register result = ToRegister(instr->result()); 4002 Register result = ToRegister(instr->result());
3868 Label true_label; 4003 Label true_label;
3869 Label false_label; 4004 Label false_label;
3870 NearLabel done; 4005 Label done;
3871 4006
3872 Condition final_branch_condition = EmitTypeofIs(&true_label, 4007 Condition final_branch_condition = EmitTypeofIs(&true_label,
3873 &false_label, 4008 &false_label,
3874 input, 4009 input,
3875 instr->type_literal()); 4010 instr->type_literal());
3876 __ j(final_branch_condition, &true_label); 4011 __ j(final_branch_condition, &true_label);
3877 __ bind(&false_label); 4012 __ bind(&false_label);
3878 __ LoadRoot(result, Heap::kFalseValueRootIndex); 4013 __ LoadRoot(result, Heap::kFalseValueRootIndex);
3879 __ jmp(&done); 4014 __ jmp(&done, Label::kNear);
3880 4015
3881 __ bind(&true_label); 4016 __ bind(&true_label);
3882 __ LoadRoot(result, Heap::kTrueValueRootIndex); 4017 __ LoadRoot(result, Heap::kTrueValueRootIndex);
3883 4018
3884 __ bind(&done); 4019 __ bind(&done);
3885 } 4020 }
3886 4021
3887 4022
3888 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { 4023 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
3889 ASSERT(!operand->IsDoubleRegister()); 4024 ASSERT(!operand->IsDoubleRegister());
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
3971 final_branch_condition = never; 4106 final_branch_condition = never;
3972 __ jmp(false_label); 4107 __ jmp(false_label);
3973 } 4108 }
3974 4109
3975 return final_branch_condition; 4110 return final_branch_condition;
3976 } 4111 }
3977 4112
3978 4113
3979 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { 4114 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) {
3980 Register result = ToRegister(instr->result()); 4115 Register result = ToRegister(instr->result());
3981 NearLabel true_label; 4116 Label true_label;
3982 NearLabel false_label; 4117 Label done;
3983 NearLabel done;
3984 4118
3985 EmitIsConstructCall(result); 4119 EmitIsConstructCall(result);
3986 __ j(equal, &true_label); 4120 __ j(equal, &true_label, Label::kNear);
3987 4121
3988 __ LoadRoot(result, Heap::kFalseValueRootIndex); 4122 __ LoadRoot(result, Heap::kFalseValueRootIndex);
3989 __ jmp(&done); 4123 __ jmp(&done, Label::kNear);
3990 4124
3991 __ bind(&true_label); 4125 __ bind(&true_label);
3992 __ LoadRoot(result, Heap::kTrueValueRootIndex); 4126 __ LoadRoot(result, Heap::kTrueValueRootIndex);
3993 4127
3994 4128
3995 __ bind(&done); 4129 __ bind(&done);
3996 } 4130 }
3997 4131
3998 4132
3999 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 4133 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
4000 Register temp = ToRegister(instr->TempAt(0)); 4134 Register temp = ToRegister(instr->TempAt(0));
4001 int true_block = chunk_->LookupDestination(instr->true_block_id()); 4135 int true_block = chunk_->LookupDestination(instr->true_block_id());
4002 int false_block = chunk_->LookupDestination(instr->false_block_id()); 4136 int false_block = chunk_->LookupDestination(instr->false_block_id());
4003 4137
4004 EmitIsConstructCall(temp); 4138 EmitIsConstructCall(temp);
4005 EmitBranch(true_block, false_block, equal); 4139 EmitBranch(true_block, false_block, equal);
4006 } 4140 }
4007 4141
4008 4142
4009 void LCodeGen::EmitIsConstructCall(Register temp) { 4143 void LCodeGen::EmitIsConstructCall(Register temp) {
4010 // Get the frame pointer for the calling frame. 4144 // Get the frame pointer for the calling frame.
4011 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 4145 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
4012 4146
4013 // Skip the arguments adaptor frame if it exists. 4147 // Skip the arguments adaptor frame if it exists.
4014 NearLabel check_frame_marker; 4148 Label check_frame_marker;
4015 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), 4149 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset),
4016 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 4150 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
4017 __ j(not_equal, &check_frame_marker); 4151 __ j(not_equal, &check_frame_marker, Label::kNear);
4018 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 4152 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset));
4019 4153
4020 // Check the marker in the calling frame. 4154 // Check the marker in the calling frame.
4021 __ bind(&check_frame_marker); 4155 __ bind(&check_frame_marker);
4022 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), 4156 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset),
4023 Smi::FromInt(StackFrame::CONSTRUCT)); 4157 Smi::FromInt(StackFrame::CONSTRUCT));
4024 } 4158 }
4025 4159
4026 4160
4027 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { 4161 void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
4071 // builtin) 4205 // builtin)
4072 SafepointGenerator safepoint_generator(this, 4206 SafepointGenerator safepoint_generator(this,
4073 pointers, 4207 pointers,
4074 env->deoptimization_index()); 4208 env->deoptimization_index());
4075 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); 4209 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
4076 } 4210 }
4077 4211
4078 4212
4079 void LCodeGen::DoStackCheck(LStackCheck* instr) { 4213 void LCodeGen::DoStackCheck(LStackCheck* instr) {
4080 // Perform stack overflow check. 4214 // Perform stack overflow check.
4081 NearLabel done; 4215 Label done;
4082 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 4216 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
4083 __ j(above_equal, &done); 4217 __ j(above_equal, &done, Label::kNear);
4084 4218
4085 StackCheckStub stub; 4219 StackCheckStub stub;
4086 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4220 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4087 __ bind(&done); 4221 __ bind(&done);
4088 } 4222 }
4089 4223
4090 4224
4091 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { 4225 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
4092 // This is a pseudo-instruction that ensures that the environment here is 4226 // This is a pseudo-instruction that ensures that the environment here is
4093 // properly registered for deoptimization and records the assembler's PC 4227 // properly registered for deoptimization and records the assembler's PC
4094 // offset. 4228 // offset.
4095 LEnvironment* environment = instr->environment(); 4229 LEnvironment* environment = instr->environment();
4096 environment->SetSpilledRegisters(instr->SpilledRegisterArray(), 4230 environment->SetSpilledRegisters(instr->SpilledRegisterArray(),
4097 instr->SpilledDoubleRegisterArray()); 4231 instr->SpilledDoubleRegisterArray());
4098 4232
4099 // If the environment were already registered, we would have no way of 4233 // If the environment were already registered, we would have no way of
4100 // backpatching it with the spill slot operands. 4234 // backpatching it with the spill slot operands.
4101 ASSERT(!environment->HasBeenRegistered()); 4235 ASSERT(!environment->HasBeenRegistered());
4102 RegisterEnvironmentForDeoptimization(environment); 4236 RegisterEnvironmentForDeoptimization(environment);
4103 ASSERT(osr_pc_offset_ == -1); 4237 ASSERT(osr_pc_offset_ == -1);
4104 osr_pc_offset_ = masm()->pc_offset(); 4238 osr_pc_offset_ = masm()->pc_offset();
4105 } 4239 }
4106 4240
4107 #undef __ 4241 #undef __
4108 4242
4109 } } // namespace v8::internal 4243 } } // namespace v8::internal
4110 4244
4111 #endif // V8_TARGET_ARCH_X64 4245 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698