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

Side by Side Diff: src/ia32/lithium-codegen-ia32.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/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.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 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 539
540 if (FLAG_deopt_every_n_times != 0) { 540 if (FLAG_deopt_every_n_times != 0) {
541 Handle<SharedFunctionInfo> shared(info_->shared_info()); 541 Handle<SharedFunctionInfo> shared(info_->shared_info());
542 Label no_deopt; 542 Label no_deopt;
543 __ pushfd(); 543 __ pushfd();
544 __ push(eax); 544 __ push(eax);
545 __ push(ebx); 545 __ push(ebx);
546 __ mov(ebx, shared); 546 __ mov(ebx, shared);
547 __ mov(eax, FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset)); 547 __ mov(eax, FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset));
548 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 548 __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
549 __ j(not_zero, &no_deopt); 549 __ j(not_zero, &no_deopt, Label::kNear);
550 if (FLAG_trap_on_deopt) __ int3(); 550 if (FLAG_trap_on_deopt) __ int3();
551 __ mov(eax, Immediate(Smi::FromInt(FLAG_deopt_every_n_times))); 551 __ mov(eax, Immediate(Smi::FromInt(FLAG_deopt_every_n_times)));
552 __ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax); 552 __ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax);
553 __ pop(ebx); 553 __ pop(ebx);
554 __ pop(eax); 554 __ pop(eax);
555 __ popfd(); 555 __ popfd();
556 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); 556 __ jmp(entry, RelocInfo::RUNTIME_ENTRY);
557 557
558 __ bind(&no_deopt); 558 __ bind(&no_deopt);
559 __ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax); 559 __ mov(FieldOperand(ebx, SharedFunctionInfo::kDeoptCounterOffset), eax);
560 __ pop(ebx); 560 __ pop(ebx);
561 __ pop(eax); 561 __ pop(eax);
562 __ popfd(); 562 __ popfd();
563 } 563 }
564 564
565 if (cc == no_condition) { 565 if (cc == no_condition) {
566 if (FLAG_trap_on_deopt) __ int3(); 566 if (FLAG_trap_on_deopt) __ int3();
567 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); 567 __ jmp(entry, RelocInfo::RUNTIME_ENTRY);
568 } else { 568 } else {
569 if (FLAG_trap_on_deopt) { 569 if (FLAG_trap_on_deopt) {
570 NearLabel done; 570 Label done;
571 __ j(NegateCondition(cc), &done); 571 __ j(NegateCondition(cc), &done, Label::kNear);
572 __ int3(); 572 __ int3();
573 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); 573 __ jmp(entry, RelocInfo::RUNTIME_ENTRY);
574 __ bind(&done); 574 __ bind(&done);
575 } else { 575 } else {
576 __ j(cc, entry, RelocInfo::RUNTIME_ENTRY, not_taken); 576 __ j(cc, entry, RelocInfo::RUNTIME_ENTRY);
577 } 577 }
578 } 578 }
579 } 579 }
580 580
581 581
582 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { 582 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
583 int length = deoptimizations_.length(); 583 int length = deoptimizations_.length();
584 if (length == 0) return; 584 if (length == 0) return;
585 ASSERT(FLAG_deopt); 585 ASSERT(FLAG_deopt);
586 Handle<DeoptimizationInputData> data = 586 Handle<DeoptimizationInputData> data =
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 781
782 void LCodeGen::DoModI(LModI* instr) { 782 void LCodeGen::DoModI(LModI* instr) {
783 if (instr->hydrogen()->HasPowerOf2Divisor()) { 783 if (instr->hydrogen()->HasPowerOf2Divisor()) {
784 Register dividend = ToRegister(instr->InputAt(0)); 784 Register dividend = ToRegister(instr->InputAt(0));
785 785
786 int32_t divisor = 786 int32_t divisor =
787 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); 787 HConstant::cast(instr->hydrogen()->right())->Integer32Value();
788 788
789 if (divisor < 0) divisor = -divisor; 789 if (divisor < 0) divisor = -divisor;
790 790
791 NearLabel positive_dividend, done; 791 Label positive_dividend, done;
792 __ test(dividend, Operand(dividend)); 792 __ test(dividend, Operand(dividend));
793 __ j(not_sign, &positive_dividend); 793 __ j(not_sign, &positive_dividend, Label::kNear);
794 __ neg(dividend); 794 __ neg(dividend);
795 __ and_(dividend, divisor - 1); 795 __ and_(dividend, divisor - 1);
796 __ neg(dividend); 796 __ neg(dividend);
797 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 797 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
798 __ j(not_zero, &done); 798 __ j(not_zero, &done, Label::kNear);
799 DeoptimizeIf(no_condition, instr->environment()); 799 DeoptimizeIf(no_condition, instr->environment());
800 } 800 }
801 __ bind(&positive_dividend); 801 __ bind(&positive_dividend);
802 __ and_(dividend, divisor - 1); 802 __ and_(dividend, divisor - 1);
803 __ bind(&done); 803 __ bind(&done);
804 } else { 804 } else {
805 NearLabel done, remainder_eq_dividend, slow, do_subtraction, both_positive; 805 Label done, remainder_eq_dividend, slow, do_subtraction, both_positive;
806 Register left_reg = ToRegister(instr->InputAt(0)); 806 Register left_reg = ToRegister(instr->InputAt(0));
807 Register right_reg = ToRegister(instr->InputAt(1)); 807 Register right_reg = ToRegister(instr->InputAt(1));
808 Register result_reg = ToRegister(instr->result()); 808 Register result_reg = ToRegister(instr->result());
809 809
810 ASSERT(left_reg.is(eax)); 810 ASSERT(left_reg.is(eax));
811 ASSERT(result_reg.is(edx)); 811 ASSERT(result_reg.is(edx));
812 ASSERT(!right_reg.is(eax)); 812 ASSERT(!right_reg.is(eax));
813 ASSERT(!right_reg.is(edx)); 813 ASSERT(!right_reg.is(edx));
814 814
815 // Check for x % 0. 815 // Check for x % 0.
816 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 816 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
817 __ test(right_reg, Operand(right_reg)); 817 __ test(right_reg, Operand(right_reg));
818 DeoptimizeIf(zero, instr->environment()); 818 DeoptimizeIf(zero, instr->environment());
819 } 819 }
820 820
821 __ test(left_reg, Operand(left_reg)); 821 __ test(left_reg, Operand(left_reg));
822 __ j(zero, &remainder_eq_dividend); 822 __ j(zero, &remainder_eq_dividend, Label::kNear);
823 __ j(sign, &slow); 823 __ j(sign, &slow, Label::kNear);
824 824
825 __ test(right_reg, Operand(right_reg)); 825 __ test(right_reg, Operand(right_reg));
826 __ j(not_sign, &both_positive); 826 __ j(not_sign, &both_positive, Label::kNear);
827 // The sign of the divisor doesn't matter. 827 // The sign of the divisor doesn't matter.
828 __ neg(right_reg); 828 __ neg(right_reg);
829 829
830 __ bind(&both_positive); 830 __ bind(&both_positive);
831 // If the dividend is smaller than the nonnegative 831 // If the dividend is smaller than the nonnegative
832 // divisor, the dividend is the result. 832 // divisor, the dividend is the result.
833 __ cmp(left_reg, Operand(right_reg)); 833 __ cmp(left_reg, Operand(right_reg));
834 __ j(less, &remainder_eq_dividend); 834 __ j(less, &remainder_eq_dividend, Label::kNear);
835 835
836 // Check if the divisor is a PowerOfTwo integer. 836 // Check if the divisor is a PowerOfTwo integer.
837 Register scratch = ToRegister(instr->TempAt(0)); 837 Register scratch = ToRegister(instr->TempAt(0));
838 __ mov(scratch, right_reg); 838 __ mov(scratch, right_reg);
839 __ sub(Operand(scratch), Immediate(1)); 839 __ sub(Operand(scratch), Immediate(1));
840 __ test(scratch, Operand(right_reg)); 840 __ test(scratch, Operand(right_reg));
841 __ j(not_zero, &do_subtraction); 841 __ j(not_zero, &do_subtraction, Label::kNear);
842 __ and_(left_reg, Operand(scratch)); 842 __ and_(left_reg, Operand(scratch));
843 __ jmp(&remainder_eq_dividend); 843 __ jmp(&remainder_eq_dividend, Label::kNear);
844 844
845 __ bind(&do_subtraction); 845 __ bind(&do_subtraction);
846 const int kUnfolds = 3; 846 const int kUnfolds = 3;
847 // Try a few subtractions of the dividend. 847 // Try a few subtractions of the dividend.
848 __ mov(scratch, left_reg); 848 __ mov(scratch, left_reg);
849 for (int i = 0; i < kUnfolds; i++) { 849 for (int i = 0; i < kUnfolds; i++) {
850 // Reduce the dividend by the divisor. 850 // Reduce the dividend by the divisor.
851 __ sub(left_reg, Operand(right_reg)); 851 __ sub(left_reg, Operand(right_reg));
852 // Check if the dividend is less than the divisor. 852 // Check if the dividend is less than the divisor.
853 __ cmp(left_reg, Operand(right_reg)); 853 __ cmp(left_reg, Operand(right_reg));
854 __ j(less, &remainder_eq_dividend); 854 __ j(less, &remainder_eq_dividend, Label::kNear);
855 } 855 }
856 __ mov(left_reg, scratch); 856 __ mov(left_reg, scratch);
857 857
858 // Slow case, using idiv instruction. 858 // Slow case, using idiv instruction.
859 __ bind(&slow); 859 __ bind(&slow);
860 // Sign extend to edx. 860 // Sign extend to edx.
861 __ cdq(); 861 __ cdq();
862 862
863 // Check for (0 % -x) that will produce negative zero. 863 // Check for (0 % -x) that will produce negative zero.
864 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 864 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
865 NearLabel positive_left; 865 Label positive_left;
866 NearLabel done; 866 Label done;
867 __ test(left_reg, Operand(left_reg)); 867 __ test(left_reg, Operand(left_reg));
868 __ j(not_sign, &positive_left); 868 __ j(not_sign, &positive_left, Label::kNear);
869 __ idiv(right_reg); 869 __ idiv(right_reg);
870 870
871 // Test the remainder for 0, because then the result would be -0. 871 // Test the remainder for 0, because then the result would be -0.
872 __ test(result_reg, Operand(result_reg)); 872 __ test(result_reg, Operand(result_reg));
873 __ j(not_zero, &done); 873 __ j(not_zero, &done, Label::kNear);
874 874
875 DeoptimizeIf(no_condition, instr->environment()); 875 DeoptimizeIf(no_condition, instr->environment());
876 __ bind(&positive_left); 876 __ bind(&positive_left);
877 __ idiv(right_reg); 877 __ idiv(right_reg);
878 __ bind(&done); 878 __ bind(&done);
879 } else { 879 } else {
880 __ idiv(right_reg); 880 __ idiv(right_reg);
881 } 881 }
882 __ jmp(&done); 882 __ jmp(&done, Label::kNear);
883 883
884 __ bind(&remainder_eq_dividend); 884 __ bind(&remainder_eq_dividend);
885 __ mov(result_reg, left_reg); 885 __ mov(result_reg, left_reg);
886 886
887 __ bind(&done); 887 __ bind(&done);
888 } 888 }
889 } 889 }
890 890
891 891
892 void LCodeGen::DoDivI(LDivI* instr) { 892 void LCodeGen::DoDivI(LDivI* instr) {
893 LOperand* right = instr->InputAt(1); 893 LOperand* right = instr->InputAt(1);
894 ASSERT(ToRegister(instr->result()).is(eax)); 894 ASSERT(ToRegister(instr->result()).is(eax));
895 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); 895 ASSERT(ToRegister(instr->InputAt(0)).is(eax));
896 ASSERT(!ToRegister(instr->InputAt(1)).is(eax)); 896 ASSERT(!ToRegister(instr->InputAt(1)).is(eax));
897 ASSERT(!ToRegister(instr->InputAt(1)).is(edx)); 897 ASSERT(!ToRegister(instr->InputAt(1)).is(edx));
898 898
899 Register left_reg = eax; 899 Register left_reg = eax;
900 900
901 // Check for x / 0. 901 // Check for x / 0.
902 Register right_reg = ToRegister(right); 902 Register right_reg = ToRegister(right);
903 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 903 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
904 __ test(right_reg, ToOperand(right)); 904 __ test(right_reg, ToOperand(right));
905 DeoptimizeIf(zero, instr->environment()); 905 DeoptimizeIf(zero, instr->environment());
906 } 906 }
907 907
908 // Check for (0 / -x) that will produce negative zero. 908 // Check for (0 / -x) that will produce negative zero.
909 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 909 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
910 NearLabel left_not_zero; 910 Label left_not_zero;
911 __ test(left_reg, Operand(left_reg)); 911 __ test(left_reg, Operand(left_reg));
912 __ j(not_zero, &left_not_zero); 912 __ j(not_zero, &left_not_zero, Label::kNear);
913 __ test(right_reg, ToOperand(right)); 913 __ test(right_reg, ToOperand(right));
914 DeoptimizeIf(sign, instr->environment()); 914 DeoptimizeIf(sign, instr->environment());
915 __ bind(&left_not_zero); 915 __ bind(&left_not_zero);
916 } 916 }
917 917
918 // Check for (-kMinInt / -1). 918 // Check for (-kMinInt / -1).
919 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 919 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
920 NearLabel left_not_min_int; 920 Label left_not_min_int;
921 __ cmp(left_reg, kMinInt); 921 __ cmp(left_reg, kMinInt);
922 __ j(not_zero, &left_not_min_int); 922 __ j(not_zero, &left_not_min_int, Label::kNear);
923 __ cmp(right_reg, -1); 923 __ cmp(right_reg, -1);
924 DeoptimizeIf(zero, instr->environment()); 924 DeoptimizeIf(zero, instr->environment());
925 __ bind(&left_not_min_int); 925 __ bind(&left_not_min_int);
926 } 926 }
927 927
928 // Sign extend to edx. 928 // Sign extend to edx.
929 __ cdq(); 929 __ cdq();
930 __ idiv(right_reg); 930 __ idiv(right_reg);
931 931
932 // Deoptimize if remainder is not 0. 932 // Deoptimize if remainder is not 0.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 } else { 990 } else {
991 __ imul(left, ToOperand(right)); 991 __ imul(left, ToOperand(right));
992 } 992 }
993 993
994 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 994 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
995 DeoptimizeIf(overflow, instr->environment()); 995 DeoptimizeIf(overflow, instr->environment());
996 } 996 }
997 997
998 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 998 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
999 // Bail out if the result is supposed to be negative zero. 999 // Bail out if the result is supposed to be negative zero.
1000 NearLabel done; 1000 Label done;
1001 __ test(left, Operand(left)); 1001 __ test(left, Operand(left));
1002 __ j(not_zero, &done); 1002 __ j(not_zero, &done, Label::kNear);
1003 if (right->IsConstantOperand()) { 1003 if (right->IsConstantOperand()) {
1004 if (ToInteger32(LConstantOperand::cast(right)) <= 0) { 1004 if (ToInteger32(LConstantOperand::cast(right)) <= 0) {
1005 DeoptimizeIf(no_condition, instr->environment()); 1005 DeoptimizeIf(no_condition, instr->environment());
1006 } 1006 }
1007 } else { 1007 } else {
1008 // Test the non-zero operand for negative sign. 1008 // Test the non-zero operand for negative sign.
1009 __ or_(ToRegister(instr->TempAt(0)), ToOperand(right)); 1009 __ or_(ToRegister(instr->TempAt(0)), ToOperand(right));
1010 DeoptimizeIf(sign, instr->environment()); 1010 DeoptimizeIf(sign, instr->environment());
1011 } 1011 }
1012 __ bind(&done); 1012 __ bind(&done);
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
1197 Register array = ToRegister(instr->InputAt(0)); 1197 Register array = ToRegister(instr->InputAt(0));
1198 __ mov(result, FieldOperand(array, ExternalArray::kLengthOffset)); 1198 __ mov(result, FieldOperand(array, ExternalArray::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 Register map = ToRegister(instr->TempAt(0)); 1205 Register map = ToRegister(instr->TempAt(0));
1206 ASSERT(input.is(result)); 1206 ASSERT(input.is(result));
1207 NearLabel done; 1207 Label done;
1208 // If the object is a smi return the object. 1208 // If the object is a smi return the object.
1209 __ test(input, Immediate(kSmiTagMask)); 1209 __ test(input, Immediate(kSmiTagMask));
1210 __ j(zero, &done); 1210 __ j(zero, &done, Label::kNear);
1211 1211
1212 // If the object is not a value type, return the object. 1212 // If the object is not a value type, return the object.
1213 __ CmpObjectType(input, JS_VALUE_TYPE, map); 1213 __ CmpObjectType(input, JS_VALUE_TYPE, map);
1214 __ j(not_equal, &done); 1214 __ j(not_equal, &done, Label::kNear);
1215 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); 1215 __ mov(result, FieldOperand(input, JSValue::kValueOffset));
1216 1216
1217 __ bind(&done); 1217 __ bind(&done);
1218 } 1218 }
1219 1219
1220 1220
1221 void LCodeGen::DoBitNotI(LBitNotI* instr) { 1221 void LCodeGen::DoBitNotI(LBitNotI* instr) {
1222 LOperand* input = instr->InputAt(0); 1222 LOperand* input = instr->InputAt(0);
1223 ASSERT(input->Equals(instr->result())); 1223 ASSERT(input->Equals(instr->result()));
1224 __ not_(ToRegister(input)); 1224 __ not_(ToRegister(input));
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
1362 __ cmp(reg, factory()->true_value()); 1362 __ cmp(reg, factory()->true_value());
1363 __ j(equal, true_label); 1363 __ j(equal, true_label);
1364 __ cmp(reg, factory()->false_value()); 1364 __ cmp(reg, factory()->false_value());
1365 __ j(equal, false_label); 1365 __ j(equal, false_label);
1366 __ test(reg, Operand(reg)); 1366 __ test(reg, Operand(reg));
1367 __ j(equal, false_label); 1367 __ j(equal, false_label);
1368 __ test(reg, Immediate(kSmiTagMask)); 1368 __ test(reg, Immediate(kSmiTagMask));
1369 __ j(zero, true_label); 1369 __ j(zero, true_label);
1370 1370
1371 // Test for double values. Zero is false. 1371 // Test for double values. Zero is false.
1372 NearLabel call_stub; 1372 Label call_stub;
1373 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 1373 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
1374 factory()->heap_number_map()); 1374 factory()->heap_number_map());
1375 __ j(not_equal, &call_stub); 1375 __ j(not_equal, &call_stub, Label::kNear);
1376 __ fldz(); 1376 __ fldz();
1377 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); 1377 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
1378 __ FCmp(); 1378 __ FCmp();
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.
1384 __ bind(&call_stub); 1384 __ bind(&call_stub);
1385 ToBooleanStub stub; 1385 ToBooleanStub stub;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1471 __ cmp(ToRegister(left), ToOperand(right)); 1471 __ cmp(ToRegister(left), ToOperand(right));
1472 } 1472 }
1473 } 1473 }
1474 1474
1475 1475
1476 void LCodeGen::DoCmpID(LCmpID* instr) { 1476 void LCodeGen::DoCmpID(LCmpID* instr) {
1477 LOperand* left = instr->InputAt(0); 1477 LOperand* left = instr->InputAt(0);
1478 LOperand* right = instr->InputAt(1); 1478 LOperand* right = instr->InputAt(1);
1479 LOperand* result = instr->result(); 1479 LOperand* result = instr->result();
1480 1480
1481 NearLabel unordered; 1481 Label unordered;
1482 if (instr->is_double()) { 1482 if (instr->is_double()) {
1483 // Don't base result on EFLAGS when a NaN is involved. Instead 1483 // Don't base result on EFLAGS when a NaN is involved. Instead
1484 // jump to the unordered case, which produces a false value. 1484 // jump to the unordered case, which produces a false value.
1485 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); 1485 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
1486 __ j(parity_even, &unordered, not_taken); 1486 __ j(parity_even, &unordered, Label::kNear);
1487 } else { 1487 } else {
1488 EmitCmpI(left, right); 1488 EmitCmpI(left, right);
1489 } 1489 }
1490 1490
1491 NearLabel done; 1491 Label done;
1492 Condition cc = TokenToCondition(instr->op(), instr->is_double()); 1492 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1493 __ mov(ToRegister(result), factory()->true_value()); 1493 __ mov(ToRegister(result), factory()->true_value());
1494 __ j(cc, &done); 1494 __ j(cc, &done, Label::kNear);
1495 1495
1496 __ bind(&unordered); 1496 __ bind(&unordered);
1497 __ mov(ToRegister(result), factory()->false_value()); 1497 __ mov(ToRegister(result), factory()->false_value());
1498 __ bind(&done); 1498 __ bind(&done);
1499 } 1499 }
1500 1500
1501 1501
1502 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 1502 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
1503 LOperand* left = instr->InputAt(0); 1503 LOperand* left = instr->InputAt(0);
1504 LOperand* right = instr->InputAt(1); 1504 LOperand* right = instr->InputAt(1);
(...skipping 14 matching lines...) Expand all
1519 } 1519 }
1520 1520
1521 1521
1522 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { 1522 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) {
1523 Register left = ToRegister(instr->InputAt(0)); 1523 Register left = ToRegister(instr->InputAt(0));
1524 Register right = ToRegister(instr->InputAt(1)); 1524 Register right = ToRegister(instr->InputAt(1));
1525 Register result = ToRegister(instr->result()); 1525 Register result = ToRegister(instr->result());
1526 1526
1527 __ cmp(left, Operand(right)); 1527 __ cmp(left, Operand(right));
1528 __ mov(result, factory()->true_value()); 1528 __ mov(result, factory()->true_value());
1529 NearLabel done; 1529 Label done;
1530 __ j(equal, &done); 1530 __ j(equal, &done, Label::kNear);
1531 __ mov(result, factory()->false_value()); 1531 __ mov(result, factory()->false_value());
1532 __ bind(&done); 1532 __ bind(&done);
1533 } 1533 }
1534 1534
1535 1535
1536 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { 1536 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
1537 Register left = ToRegister(instr->InputAt(0)); 1537 Register left = ToRegister(instr->InputAt(0));
1538 Register right = ToRegister(instr->InputAt(1)); 1538 Register right = ToRegister(instr->InputAt(1));
1539 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1539 int false_block = chunk_->LookupDestination(instr->false_block_id());
1540 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1540 int true_block = chunk_->LookupDestination(instr->true_block_id());
1541 1541
1542 __ cmp(left, Operand(right)); 1542 __ cmp(left, Operand(right));
1543 EmitBranch(true_block, false_block, equal); 1543 EmitBranch(true_block, false_block, equal);
1544 } 1544 }
1545 1545
1546 1546
1547 void LCodeGen::DoCmpSymbolEq(LCmpSymbolEq* instr) {
1548 Register left = ToRegister(instr->InputAt(0));
1549 Register right = ToRegister(instr->InputAt(1));
1550 Register result = ToRegister(instr->result());
1551
1552 Label done;
1553 __ cmp(left, Operand(right));
1554 __ mov(result, factory()->false_value());
1555 __ j(not_equal, &done, Label::kNear);
1556 __ mov(result, factory()->true_value());
1557 __ bind(&done);
1558 }
1559
1560
1561 void LCodeGen::DoCmpSymbolEqAndBranch(LCmpSymbolEqAndBranch* instr) {
1562 Register left = ToRegister(instr->InputAt(0));
1563 Register right = ToRegister(instr->InputAt(1));
1564 int false_block = chunk_->LookupDestination(instr->false_block_id());
1565 int true_block = chunk_->LookupDestination(instr->true_block_id());
1566
1567 __ cmp(left, Operand(right));
1568 EmitBranch(true_block, false_block, equal);
1569 }
1570
1571
1547 void LCodeGen::DoIsNull(LIsNull* instr) { 1572 void LCodeGen::DoIsNull(LIsNull* instr) {
1548 Register reg = ToRegister(instr->InputAt(0)); 1573 Register reg = ToRegister(instr->InputAt(0));
1549 Register result = ToRegister(instr->result()); 1574 Register result = ToRegister(instr->result());
1550 1575
1551 // TODO(fsc): If the expression is known to be a smi, then it's 1576 // TODO(fsc): If the expression is known to be a smi, then it's
1552 // definitely not null. Materialize false. 1577 // definitely not null. Materialize false.
1553 1578
1554 __ cmp(reg, factory()->null_value()); 1579 __ cmp(reg, factory()->null_value());
1555 if (instr->is_strict()) { 1580 if (instr->is_strict()) {
1556 __ mov(result, factory()->true_value()); 1581 __ mov(result, factory()->true_value());
1557 NearLabel done; 1582 Label done;
1558 __ j(equal, &done); 1583 __ j(equal, &done, Label::kNear);
1559 __ mov(result, factory()->false_value()); 1584 __ mov(result, factory()->false_value());
1560 __ bind(&done); 1585 __ bind(&done);
1561 } else { 1586 } else {
1562 NearLabel true_value, false_value, done; 1587 Label true_value, false_value, done;
1563 __ j(equal, &true_value); 1588 __ j(equal, &true_value, Label::kNear);
1564 __ cmp(reg, factory()->undefined_value()); 1589 __ cmp(reg, factory()->undefined_value());
1565 __ j(equal, &true_value); 1590 __ j(equal, &true_value, Label::kNear);
1566 __ test(reg, Immediate(kSmiTagMask)); 1591 __ test(reg, Immediate(kSmiTagMask));
1567 __ j(zero, &false_value); 1592 __ j(zero, &false_value, Label::kNear);
1568 // Check for undetectable objects by looking in the bit field in 1593 // Check for undetectable objects by looking in the bit field in
1569 // the map. The object has already been smi checked. 1594 // the map. The object has already been smi checked.
1570 Register scratch = result; 1595 Register scratch = result;
1571 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); 1596 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset));
1572 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); 1597 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
1573 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); 1598 __ test(scratch, Immediate(1 << Map::kIsUndetectable));
1574 __ j(not_zero, &true_value); 1599 __ j(not_zero, &true_value, Label::kNear);
1575 __ bind(&false_value); 1600 __ bind(&false_value);
1576 __ mov(result, factory()->false_value()); 1601 __ mov(result, factory()->false_value());
1577 __ jmp(&done); 1602 __ jmp(&done, Label::kNear);
1578 __ bind(&true_value); 1603 __ bind(&true_value);
1579 __ mov(result, factory()->true_value()); 1604 __ mov(result, factory()->true_value());
1580 __ bind(&done); 1605 __ bind(&done);
1581 } 1606 }
1582 } 1607 }
1583 1608
1584 1609
1585 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { 1610 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) {
1586 Register reg = ToRegister(instr->InputAt(0)); 1611 Register reg = ToRegister(instr->InputAt(0));
1587 1612
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1678 } 1703 }
1679 1704
1680 1705
1681 void LCodeGen::DoIsSmi(LIsSmi* instr) { 1706 void LCodeGen::DoIsSmi(LIsSmi* instr) {
1682 Operand input = ToOperand(instr->InputAt(0)); 1707 Operand input = ToOperand(instr->InputAt(0));
1683 Register result = ToRegister(instr->result()); 1708 Register result = ToRegister(instr->result());
1684 1709
1685 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); 1710 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1686 __ test(input, Immediate(kSmiTagMask)); 1711 __ test(input, Immediate(kSmiTagMask));
1687 __ mov(result, factory()->true_value()); 1712 __ mov(result, factory()->true_value());
1688 NearLabel done; 1713 Label done;
1689 __ j(zero, &done); 1714 __ j(zero, &done, Label::kNear);
1690 __ mov(result, factory()->false_value()); 1715 __ mov(result, factory()->false_value());
1691 __ bind(&done); 1716 __ bind(&done);
1692 } 1717 }
1693 1718
1694 1719
1695 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { 1720 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
1696 Operand input = ToOperand(instr->InputAt(0)); 1721 Operand input = ToOperand(instr->InputAt(0));
1697 1722
1698 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1723 int true_block = chunk_->LookupDestination(instr->true_block_id());
1699 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1724 int false_block = chunk_->LookupDestination(instr->false_block_id());
1700 1725
1701 __ test(input, Immediate(kSmiTagMask)); 1726 __ test(input, Immediate(kSmiTagMask));
1702 EmitBranch(true_block, false_block, zero); 1727 EmitBranch(true_block, false_block, zero);
1703 } 1728 }
1704 1729
1705 1730
1731 void LCodeGen::DoIsUndetectable(LIsUndetectable* instr) {
1732 Register input = ToRegister(instr->InputAt(0));
1733 Register result = ToRegister(instr->result());
1734
1735 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1736 Label false_label, done;
1737 STATIC_ASSERT(kSmiTag == 0);
1738 __ test(input, Immediate(kSmiTagMask));
1739 __ j(zero, &false_label, Label::kNear);
1740 __ mov(result, FieldOperand(input, HeapObject::kMapOffset));
1741 __ test_b(FieldOperand(result, Map::kBitFieldOffset),
1742 1 << Map::kIsUndetectable);
1743 __ j(zero, &false_label, Label::kNear);
1744 __ mov(result, factory()->true_value());
1745 __ jmp(&done);
1746 __ bind(&false_label);
1747 __ mov(result, factory()->false_value());
1748 __ bind(&done);
1749 }
1750
1751
1752 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
1753 Register input = ToRegister(instr->InputAt(0));
1754 Register temp = ToRegister(instr->TempAt(0));
1755
1756 int true_block = chunk_->LookupDestination(instr->true_block_id());
1757 int false_block = chunk_->LookupDestination(instr->false_block_id());
1758
1759 STATIC_ASSERT(kSmiTag == 0);
1760 __ test(input, Immediate(kSmiTagMask));
1761 __ j(zero, chunk_->GetAssemblyLabel(false_block));
1762 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
1763 __ test_b(FieldOperand(temp, Map::kBitFieldOffset),
1764 1 << Map::kIsUndetectable);
1765 EmitBranch(true_block, false_block, not_zero);
1766 }
1767
1768
1706 static InstanceType TestType(HHasInstanceType* instr) { 1769 static InstanceType TestType(HHasInstanceType* instr) {
1707 InstanceType from = instr->from(); 1770 InstanceType from = instr->from();
1708 InstanceType to = instr->to(); 1771 InstanceType to = instr->to();
1709 if (from == FIRST_TYPE) return to; 1772 if (from == FIRST_TYPE) return to;
1710 ASSERT(from == to || to == LAST_TYPE); 1773 ASSERT(from == to || to == LAST_TYPE);
1711 return from; 1774 return from;
1712 } 1775 }
1713 1776
1714 1777
1715 static Condition BranchCondition(HHasInstanceType* instr) { 1778 static Condition BranchCondition(HHasInstanceType* instr) {
1716 InstanceType from = instr->from(); 1779 InstanceType from = instr->from();
1717 InstanceType to = instr->to(); 1780 InstanceType to = instr->to();
1718 if (from == to) return equal; 1781 if (from == to) return equal;
1719 if (to == LAST_TYPE) return above_equal; 1782 if (to == LAST_TYPE) return above_equal;
1720 if (from == FIRST_TYPE) return below_equal; 1783 if (from == FIRST_TYPE) return below_equal;
1721 UNREACHABLE(); 1784 UNREACHABLE();
1722 return equal; 1785 return equal;
1723 } 1786 }
1724 1787
1725 1788
1726 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { 1789 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) {
1727 Register input = ToRegister(instr->InputAt(0)); 1790 Register input = ToRegister(instr->InputAt(0));
1728 Register result = ToRegister(instr->result()); 1791 Register result = ToRegister(instr->result());
1729 1792
1730 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); 1793 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1731 __ test(input, Immediate(kSmiTagMask)); 1794 __ test(input, Immediate(kSmiTagMask));
1732 NearLabel done, is_false; 1795 Label done, is_false;
1733 __ j(zero, &is_false); 1796 __ j(zero, &is_false, Label::kNear);
1734 __ CmpObjectType(input, TestType(instr->hydrogen()), result); 1797 __ CmpObjectType(input, TestType(instr->hydrogen()), result);
1735 __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false); 1798 __ j(NegateCondition(BranchCondition(instr->hydrogen())),
1799 &is_false, Label::kNear);
1736 __ mov(result, factory()->true_value()); 1800 __ mov(result, factory()->true_value());
1737 __ jmp(&done); 1801 __ jmp(&done, Label::kNear);
1738 __ bind(&is_false); 1802 __ bind(&is_false);
1739 __ mov(result, factory()->false_value()); 1803 __ mov(result, factory()->false_value());
1740 __ bind(&done); 1804 __ bind(&done);
1741 } 1805 }
1742 1806
1743 1807
1744 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { 1808 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
1745 Register input = ToRegister(instr->InputAt(0)); 1809 Register input = ToRegister(instr->InputAt(0));
1746 Register temp = ToRegister(instr->TempAt(0)); 1810 Register temp = ToRegister(instr->TempAt(0));
1747 1811
(...skipping 24 matching lines...) Expand all
1772 1836
1773 1837
1774 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { 1838 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) {
1775 Register input = ToRegister(instr->InputAt(0)); 1839 Register input = ToRegister(instr->InputAt(0));
1776 Register result = ToRegister(instr->result()); 1840 Register result = ToRegister(instr->result());
1777 1841
1778 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); 1842 ASSERT(instr->hydrogen()->value()->representation().IsTagged());
1779 __ mov(result, factory()->true_value()); 1843 __ mov(result, factory()->true_value());
1780 __ test(FieldOperand(input, String::kHashFieldOffset), 1844 __ test(FieldOperand(input, String::kHashFieldOffset),
1781 Immediate(String::kContainsCachedArrayIndexMask)); 1845 Immediate(String::kContainsCachedArrayIndexMask));
1782 NearLabel done; 1846 Label done;
1783 __ j(zero, &done); 1847 __ j(zero, &done, Label::kNear);
1784 __ mov(result, factory()->false_value()); 1848 __ mov(result, factory()->false_value());
1785 __ bind(&done); 1849 __ bind(&done);
1786 } 1850 }
1787 1851
1788 1852
1789 void LCodeGen::DoHasCachedArrayIndexAndBranch( 1853 void LCodeGen::DoHasCachedArrayIndexAndBranch(
1790 LHasCachedArrayIndexAndBranch* instr) { 1854 LHasCachedArrayIndexAndBranch* instr) {
1791 Register input = ToRegister(instr->InputAt(0)); 1855 Register input = ToRegister(instr->InputAt(0));
1792 1856
1793 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1857 int true_block = chunk_->LookupDestination(instr->true_block_id());
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1855 // End with the answer in the z flag. 1919 // End with the answer in the z flag.
1856 } 1920 }
1857 1921
1858 1922
1859 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { 1923 void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
1860 Register input = ToRegister(instr->InputAt(0)); 1924 Register input = ToRegister(instr->InputAt(0));
1861 Register result = ToRegister(instr->result()); 1925 Register result = ToRegister(instr->result());
1862 ASSERT(input.is(result)); 1926 ASSERT(input.is(result));
1863 Register temp = ToRegister(instr->TempAt(0)); 1927 Register temp = ToRegister(instr->TempAt(0));
1864 Handle<String> class_name = instr->hydrogen()->class_name(); 1928 Handle<String> class_name = instr->hydrogen()->class_name();
1865 NearLabel done; 1929 Label done;
1866 Label is_true, is_false; 1930 Label is_true, is_false;
1867 1931
1868 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); 1932 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input);
1869 1933
1870 __ j(not_equal, &is_false); 1934 __ j(not_equal, &is_false, Label::kNear);
1871 1935
1872 __ bind(&is_true); 1936 __ bind(&is_true);
1873 __ mov(result, factory()->true_value()); 1937 __ mov(result, factory()->true_value());
1874 __ jmp(&done); 1938 __ jmp(&done, Label::kNear);
1875 1939
1876 __ bind(&is_false); 1940 __ bind(&is_false);
1877 __ mov(result, factory()->false_value()); 1941 __ mov(result, factory()->false_value());
1878 __ bind(&done); 1942 __ bind(&done);
1879 } 1943 }
1880 1944
1881 1945
1882 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { 1946 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
1883 Register input = ToRegister(instr->InputAt(0)); 1947 Register input = ToRegister(instr->InputAt(0));
1884 Register temp = ToRegister(instr->TempAt(0)); 1948 Register temp = ToRegister(instr->TempAt(0));
(...skipping 27 matching lines...) Expand all
1912 EmitBranch(true_block, false_block, equal); 1976 EmitBranch(true_block, false_block, equal);
1913 } 1977 }
1914 1978
1915 1979
1916 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { 1980 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
1917 // Object and function are in fixed registers defined by the stub. 1981 // Object and function are in fixed registers defined by the stub.
1918 ASSERT(ToRegister(instr->context()).is(esi)); 1982 ASSERT(ToRegister(instr->context()).is(esi));
1919 InstanceofStub stub(InstanceofStub::kArgsInRegisters); 1983 InstanceofStub stub(InstanceofStub::kArgsInRegisters);
1920 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 1984 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED);
1921 1985
1922 NearLabel true_value, done; 1986 Label true_value, done;
1923 __ test(eax, Operand(eax)); 1987 __ test(eax, Operand(eax));
1924 __ j(zero, &true_value); 1988 __ j(zero, &true_value, Label::kNear);
1925 __ mov(ToRegister(instr->result()), factory()->false_value()); 1989 __ mov(ToRegister(instr->result()), factory()->false_value());
1926 __ jmp(&done); 1990 __ jmp(&done, Label::kNear);
1927 __ bind(&true_value); 1991 __ bind(&true_value);
1928 __ mov(ToRegister(instr->result()), factory()->true_value()); 1992 __ mov(ToRegister(instr->result()), factory()->true_value());
1929 __ bind(&done); 1993 __ bind(&done);
1930 } 1994 }
1931 1995
1932 1996
1933 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { 1997 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) {
1934 ASSERT(ToRegister(instr->context()).is(esi)); 1998 ASSERT(ToRegister(instr->context()).is(esi));
1935 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1999 int true_block = chunk_->LookupDestination(instr->true_block_id());
1936 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2000 int false_block = chunk_->LookupDestination(instr->false_block_id());
(...skipping 24 matching lines...) Expand all
1961 2025
1962 DeferredInstanceOfKnownGlobal* deferred; 2026 DeferredInstanceOfKnownGlobal* deferred;
1963 deferred = new DeferredInstanceOfKnownGlobal(this, instr); 2027 deferred = new DeferredInstanceOfKnownGlobal(this, instr);
1964 2028
1965 Label done, false_result; 2029 Label done, false_result;
1966 Register object = ToRegister(instr->InputAt(0)); 2030 Register object = ToRegister(instr->InputAt(0));
1967 Register temp = ToRegister(instr->TempAt(0)); 2031 Register temp = ToRegister(instr->TempAt(0));
1968 2032
1969 // A Smi is not an instance of anything. 2033 // A Smi is not an instance of anything.
1970 __ test(object, Immediate(kSmiTagMask)); 2034 __ test(object, Immediate(kSmiTagMask));
1971 __ j(zero, &false_result, not_taken); 2035 __ j(zero, &false_result);
1972 2036
1973 // This is the inlined call site instanceof cache. The two occurences of the 2037 // This is the inlined call site instanceof cache. The two occurences of the
1974 // hole value will be patched to the last map/result pair generated by the 2038 // hole value will be patched to the last map/result pair generated by the
1975 // instanceof stub. 2039 // instanceof stub.
1976 NearLabel cache_miss; 2040 Label cache_miss;
1977 Register map = ToRegister(instr->TempAt(0)); 2041 Register map = ToRegister(instr->TempAt(0));
1978 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); 2042 __ mov(map, FieldOperand(object, HeapObject::kMapOffset));
1979 __ bind(deferred->map_check()); // Label for calculating code patching. 2043 __ bind(deferred->map_check()); // Label for calculating code patching.
1980 __ cmp(map, factory()->the_hole_value()); // Patched to cached map. 2044 __ cmp(map, factory()->the_hole_value()); // Patched to cached map.
1981 __ j(not_equal, &cache_miss, not_taken); 2045 __ j(not_equal, &cache_miss, Label::kNear);
1982 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. 2046 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false.
1983 __ jmp(&done); 2047 __ jmp(&done);
1984 2048
1985 // The inlined call site cache did not match. Check for null and string 2049 // The inlined call site cache did not match. Check for null and string
1986 // before calling the deferred code. 2050 // before calling the deferred code.
1987 __ bind(&cache_miss); 2051 __ bind(&cache_miss);
1988 // Null is not an instance of anything. 2052 // Null is not an instance of anything.
1989 __ cmp(object, factory()->null_value()); 2053 __ cmp(object, factory()->null_value());
1990 __ j(equal, &false_result); 2054 __ j(equal, &false_result);
1991 2055
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
2063 void LCodeGen::DoCmpT(LCmpT* instr) { 2127 void LCodeGen::DoCmpT(LCmpT* instr) {
2064 Token::Value op = instr->op(); 2128 Token::Value op = instr->op();
2065 2129
2066 Handle<Code> ic = CompareIC::GetUninitialized(op); 2130 Handle<Code> ic = CompareIC::GetUninitialized(op);
2067 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 2131 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT);
2068 2132
2069 Condition condition = ComputeCompareCondition(op); 2133 Condition condition = ComputeCompareCondition(op);
2070 if (op == Token::GT || op == Token::LTE) { 2134 if (op == Token::GT || op == Token::LTE) {
2071 condition = ReverseCondition(condition); 2135 condition = ReverseCondition(condition);
2072 } 2136 }
2073 NearLabel true_value, done; 2137 Label true_value, done;
2074 __ test(eax, Operand(eax)); 2138 __ test(eax, Operand(eax));
2075 __ j(condition, &true_value); 2139 __ j(condition, &true_value, Label::kNear);
2076 __ mov(ToRegister(instr->result()), factory()->false_value()); 2140 __ mov(ToRegister(instr->result()), factory()->false_value());
2077 __ jmp(&done); 2141 __ jmp(&done, Label::kNear);
2078 __ bind(&true_value); 2142 __ bind(&true_value);
2079 __ mov(ToRegister(instr->result()), factory()->true_value()); 2143 __ mov(ToRegister(instr->result()), factory()->true_value());
2080 __ bind(&done); 2144 __ bind(&done);
2081 } 2145 }
2082 2146
2083 2147
2084 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { 2148 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) {
2085 Token::Value op = instr->op(); 2149 Token::Value op = instr->op();
2086 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2150 int true_block = chunk_->LookupDestination(instr->true_block_id());
2087 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2151 int false_block = chunk_->LookupDestination(instr->false_block_id());
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
2247 Register result = ToRegister(instr->result()); 2311 Register result = ToRegister(instr->result());
2248 2312
2249 int map_count = instr->hydrogen()->types()->length(); 2313 int map_count = instr->hydrogen()->types()->length();
2250 Handle<String> name = instr->hydrogen()->name(); 2314 Handle<String> name = instr->hydrogen()->name();
2251 if (map_count == 0) { 2315 if (map_count == 0) {
2252 ASSERT(instr->hydrogen()->need_generic()); 2316 ASSERT(instr->hydrogen()->need_generic());
2253 __ mov(ecx, name); 2317 __ mov(ecx, name);
2254 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 2318 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
2255 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 2319 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT);
2256 } else { 2320 } else {
2257 NearLabel done; 2321 Label done;
2258 for (int i = 0; i < map_count - 1; ++i) { 2322 for (int i = 0; i < map_count - 1; ++i) {
2259 Handle<Map> map = instr->hydrogen()->types()->at(i); 2323 Handle<Map> map = instr->hydrogen()->types()->at(i);
2260 NearLabel next; 2324 Label next;
2261 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); 2325 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map);
2262 __ j(not_equal, &next); 2326 __ j(not_equal, &next, Label::kNear);
2263 EmitLoadFieldOrConstantFunction(result, object, map, name); 2327 EmitLoadFieldOrConstantFunction(result, object, map, name);
2264 __ jmp(&done); 2328 __ jmp(&done, Label::kNear);
2265 __ bind(&next); 2329 __ bind(&next);
2266 } 2330 }
2267 Handle<Map> map = instr->hydrogen()->types()->last(); 2331 Handle<Map> map = instr->hydrogen()->types()->last();
2268 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map); 2332 __ cmp(FieldOperand(object, HeapObject::kMapOffset), map);
2269 if (instr->hydrogen()->need_generic()) { 2333 if (instr->hydrogen()->need_generic()) {
2270 NearLabel generic; 2334 Label generic;
2271 __ j(not_equal, &generic); 2335 __ j(not_equal, &generic, Label::kNear);
2272 EmitLoadFieldOrConstantFunction(result, object, map, name); 2336 EmitLoadFieldOrConstantFunction(result, object, map, name);
2273 __ jmp(&done); 2337 __ jmp(&done, Label::kNear);
2274 __ bind(&generic); 2338 __ bind(&generic);
2275 __ mov(ecx, name); 2339 __ mov(ecx, name);
2276 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 2340 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
2277 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 2341 CallCode(ic, RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT);
2278 } else { 2342 } else {
2279 DeoptimizeIf(not_equal, instr->environment()); 2343 DeoptimizeIf(not_equal, instr->environment());
2280 EmitLoadFieldOrConstantFunction(result, object, map, name); 2344 EmitLoadFieldOrConstantFunction(result, object, map, name);
2281 } 2345 }
2282 __ bind(&done); 2346 __ bind(&done);
2283 } 2347 }
(...skipping 14 matching lines...) Expand all
2298 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { 2362 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
2299 Register function = ToRegister(instr->function()); 2363 Register function = ToRegister(instr->function());
2300 Register temp = ToRegister(instr->TempAt(0)); 2364 Register temp = ToRegister(instr->TempAt(0));
2301 Register result = ToRegister(instr->result()); 2365 Register result = ToRegister(instr->result());
2302 2366
2303 // Check that the function really is a function. 2367 // Check that the function really is a function.
2304 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); 2368 __ CmpObjectType(function, JS_FUNCTION_TYPE, result);
2305 DeoptimizeIf(not_equal, instr->environment()); 2369 DeoptimizeIf(not_equal, instr->environment());
2306 2370
2307 // Check whether the function has an instance prototype. 2371 // Check whether the function has an instance prototype.
2308 NearLabel non_instance; 2372 Label non_instance;
2309 __ test_b(FieldOperand(result, Map::kBitFieldOffset), 2373 __ test_b(FieldOperand(result, Map::kBitFieldOffset),
2310 1 << Map::kHasNonInstancePrototype); 2374 1 << Map::kHasNonInstancePrototype);
2311 __ j(not_zero, &non_instance); 2375 __ j(not_zero, &non_instance, Label::kNear);
2312 2376
2313 // Get the prototype or initial map from the function. 2377 // Get the prototype or initial map from the function.
2314 __ mov(result, 2378 __ mov(result,
2315 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 2379 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2316 2380
2317 // Check that the function has a prototype or an initial map. 2381 // Check that the function has a prototype or an initial map.
2318 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); 2382 __ cmp(Operand(result), Immediate(factory()->the_hole_value()));
2319 DeoptimizeIf(equal, instr->environment()); 2383 DeoptimizeIf(equal, instr->environment());
2320 2384
2321 // If the function does not have an initial map, we're done. 2385 // If the function does not have an initial map, we're done.
2322 NearLabel done; 2386 Label done;
2323 __ CmpObjectType(result, MAP_TYPE, temp); 2387 __ CmpObjectType(result, MAP_TYPE, temp);
2324 __ j(not_equal, &done); 2388 __ j(not_equal, &done, Label::kNear);
2325 2389
2326 // Get the prototype from the initial map. 2390 // Get the prototype from the initial map.
2327 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); 2391 __ mov(result, FieldOperand(result, Map::kPrototypeOffset));
2328 __ jmp(&done); 2392 __ jmp(&done, Label::kNear);
2329 2393
2330 // Non-instance prototype: Fetch prototype from constructor field 2394 // Non-instance prototype: Fetch prototype from constructor field
2331 // in the function's map. 2395 // in the function's map.
2332 __ bind(&non_instance); 2396 __ bind(&non_instance);
2333 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); 2397 __ mov(result, FieldOperand(result, Map::kConstructorOffset));
2334 2398
2335 // All done. 2399 // All done.
2336 __ bind(&done); 2400 __ bind(&done);
2337 } 2401 }
2338 2402
2339 2403
2340 void LCodeGen::DoLoadElements(LLoadElements* instr) { 2404 void LCodeGen::DoLoadElements(LLoadElements* instr) {
2341 Register result = ToRegister(instr->result()); 2405 Register result = ToRegister(instr->result());
2342 Register input = ToRegister(instr->InputAt(0)); 2406 Register input = ToRegister(instr->InputAt(0));
2343 __ mov(result, FieldOperand(input, JSObject::kElementsOffset)); 2407 __ mov(result, FieldOperand(input, JSObject::kElementsOffset));
2344 if (FLAG_debug_code) { 2408 if (FLAG_debug_code) {
2345 NearLabel done; 2409 Label done;
2346 __ cmp(FieldOperand(result, HeapObject::kMapOffset), 2410 __ cmp(FieldOperand(result, HeapObject::kMapOffset),
2347 Immediate(factory()->fixed_array_map())); 2411 Immediate(factory()->fixed_array_map()));
2348 __ j(equal, &done); 2412 __ j(equal, &done, Label::kNear);
2349 __ cmp(FieldOperand(result, HeapObject::kMapOffset), 2413 __ cmp(FieldOperand(result, HeapObject::kMapOffset),
2350 Immediate(factory()->fixed_cow_array_map())); 2414 Immediate(factory()->fixed_cow_array_map()));
2351 __ j(equal, &done); 2415 __ j(equal, &done, Label::kNear);
2352 Register temp((result.is(eax)) ? ebx : eax); 2416 Register temp((result.is(eax)) ? ebx : eax);
2353 __ push(temp); 2417 __ push(temp);
2354 __ mov(temp, FieldOperand(result, HeapObject::kMapOffset)); 2418 __ mov(temp, FieldOperand(result, HeapObject::kMapOffset));
2355 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 2419 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
2356 __ sub(Operand(temp), Immediate(FIRST_EXTERNAL_ARRAY_TYPE)); 2420 __ sub(Operand(temp), Immediate(FIRST_EXTERNAL_ARRAY_TYPE));
2357 __ cmp(Operand(temp), Immediate(kExternalArrayTypeCount)); 2421 __ cmp(Operand(temp), Immediate(kExternalArrayTypeCount));
2358 __ pop(temp); 2422 __ pop(temp);
2359 __ Check(below, "Check for fast elements or pixel array failed."); 2423 __ Check(below, "Check for fast elements or pixel array failed.");
2360 __ bind(&done); 2424 __ bind(&done);
2361 } 2425 }
(...skipping 30 matching lines...) Expand all
2392 Register result = ToRegister(instr->result()); 2456 Register result = ToRegister(instr->result());
2393 ASSERT(result.is(elements)); 2457 ASSERT(result.is(elements));
2394 2458
2395 // Load the result. 2459 // Load the result.
2396 __ mov(result, FieldOperand(elements, 2460 __ mov(result, FieldOperand(elements,
2397 key, 2461 key,
2398 times_pointer_size, 2462 times_pointer_size,
2399 FixedArray::kHeaderSize)); 2463 FixedArray::kHeaderSize));
2400 2464
2401 // Check for the hole value. 2465 // Check for the hole value.
2402 __ cmp(result, factory()->the_hole_value()); 2466 if (instr->hydrogen()->RequiresHoleCheck()) {
2403 DeoptimizeIf(equal, instr->environment()); 2467 __ cmp(result, factory()->the_hole_value());
2468 DeoptimizeIf(equal, instr->environment());
2469 }
2470 }
2471
2472
2473 Operand LCodeGen::BuildExternalArrayOperand(LOperand* external_pointer,
2474 LOperand* key,
2475 ExternalArrayType array_type) {
2476 Register external_pointer_reg = ToRegister(external_pointer);
2477 int shift_size = ExternalArrayTypeToShiftSize(array_type);
2478 if (key->IsConstantOperand()) {
2479 int constant_value = ToInteger32(LConstantOperand::cast(key));
2480 if (constant_value & 0xF0000000) {
2481 Abort("array index constant value too big");
2482 }
2483 return Operand(external_pointer_reg, constant_value * (1 << shift_size));
2484 } else {
2485 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
2486 return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0);
2487 }
2404 } 2488 }
2405 2489
2406 2490
2407 void LCodeGen::DoLoadKeyedSpecializedArrayElement( 2491 void LCodeGen::DoLoadKeyedSpecializedArrayElement(
2408 LLoadKeyedSpecializedArrayElement* instr) { 2492 LLoadKeyedSpecializedArrayElement* instr) {
2409 Register external_pointer = ToRegister(instr->external_pointer());
2410 Register key = ToRegister(instr->key());
2411 ExternalArrayType array_type = instr->array_type(); 2493 ExternalArrayType array_type = instr->array_type();
2494 Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
2495 instr->key(), array_type));
2412 if (array_type == kExternalFloatArray) { 2496 if (array_type == kExternalFloatArray) {
2413 XMMRegister result(ToDoubleRegister(instr->result())); 2497 XMMRegister result(ToDoubleRegister(instr->result()));
2414 __ movss(result, Operand(external_pointer, key, times_4, 0)); 2498 __ movss(result, operand);
2415 __ cvtss2sd(result, result); 2499 __ cvtss2sd(result, result);
2416 } else if (array_type == kExternalDoubleArray) { 2500 } else if (array_type == kExternalDoubleArray) {
2417 __ movdbl(ToDoubleRegister(instr->result()), 2501 __ movdbl(ToDoubleRegister(instr->result()), operand);
2418 Operand(external_pointer, key, times_8, 0));
2419 } else { 2502 } else {
2420 Register result(ToRegister(instr->result())); 2503 Register result(ToRegister(instr->result()));
2421 switch (array_type) { 2504 switch (array_type) {
2422 case kExternalByteArray: 2505 case kExternalByteArray:
2423 __ movsx_b(result, Operand(external_pointer, key, times_1, 0)); 2506 __ movsx_b(result, operand);
2424 break; 2507 break;
2425 case kExternalUnsignedByteArray: 2508 case kExternalUnsignedByteArray:
2426 case kExternalPixelArray: 2509 case kExternalPixelArray:
2427 __ movzx_b(result, Operand(external_pointer, key, times_1, 0)); 2510 __ movzx_b(result, operand);
2428 break; 2511 break;
2429 case kExternalShortArray: 2512 case kExternalShortArray:
2430 __ movsx_w(result, Operand(external_pointer, key, times_2, 0)); 2513 __ movsx_w(result, operand);
2431 break; 2514 break;
2432 case kExternalUnsignedShortArray: 2515 case kExternalUnsignedShortArray:
2433 __ movzx_w(result, Operand(external_pointer, key, times_2, 0)); 2516 __ movzx_w(result, operand);
2434 break; 2517 break;
2435 case kExternalIntArray: 2518 case kExternalIntArray:
2436 __ mov(result, Operand(external_pointer, key, times_4, 0)); 2519 __ mov(result, operand);
2437 break; 2520 break;
2438 case kExternalUnsignedIntArray: 2521 case kExternalUnsignedIntArray:
2439 __ mov(result, Operand(external_pointer, key, times_4, 0)); 2522 __ mov(result, operand);
2440 __ test(result, Operand(result)); 2523 __ test(result, Operand(result));
2441 // TODO(danno): we could be more clever here, perhaps having a special 2524 // TODO(danno): we could be more clever here, perhaps having a special
2442 // version of the stub that detects if the overflow case actually 2525 // version of the stub that detects if the overflow case actually
2443 // happens, and generate code that returns a double rather than int. 2526 // happens, and generate code that returns a double rather than int.
2444 DeoptimizeIf(negative, instr->environment()); 2527 DeoptimizeIf(negative, instr->environment());
2445 break; 2528 break;
2446 case kExternalFloatArray: 2529 case kExternalFloatArray:
2447 case kExternalDoubleArray: 2530 case kExternalDoubleArray:
2448 UNREACHABLE(); 2531 UNREACHABLE();
2449 break; 2532 break;
2450 } 2533 }
2451 } 2534 }
2452 } 2535 }
2453 2536
2454 2537
2455 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { 2538 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
2456 ASSERT(ToRegister(instr->context()).is(esi)); 2539 ASSERT(ToRegister(instr->context()).is(esi));
2457 ASSERT(ToRegister(instr->object()).is(edx)); 2540 ASSERT(ToRegister(instr->object()).is(edx));
2458 ASSERT(ToRegister(instr->key()).is(eax)); 2541 ASSERT(ToRegister(instr->key()).is(eax));
2459 2542
2460 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2543 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2461 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED); 2544 CallCode(ic, RelocInfo::CODE_TARGET, instr, CONTEXT_ADJUSTED);
2462 } 2545 }
2463 2546
2464 2547
2465 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { 2548 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
2466 Register result = ToRegister(instr->result()); 2549 Register result = ToRegister(instr->result());
2467 2550
2468 // Check for arguments adapter frame. 2551 // Check for arguments adapter frame.
2469 NearLabel done, adapted; 2552 Label done, adapted;
2470 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2553 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2471 __ mov(result, Operand(result, StandardFrameConstants::kContextOffset)); 2554 __ mov(result, Operand(result, StandardFrameConstants::kContextOffset));
2472 __ cmp(Operand(result), 2555 __ cmp(Operand(result),
2473 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2556 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2474 __ j(equal, &adapted); 2557 __ j(equal, &adapted, Label::kNear);
2475 2558
2476 // No arguments adaptor frame. 2559 // No arguments adaptor frame.
2477 __ mov(result, Operand(ebp)); 2560 __ mov(result, Operand(ebp));
2478 __ jmp(&done); 2561 __ jmp(&done, Label::kNear);
2479 2562
2480 // Arguments adaptor frame present. 2563 // Arguments adaptor frame present.
2481 __ bind(&adapted); 2564 __ bind(&adapted);
2482 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2565 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2483 2566
2484 // Result is the frame pointer for the frame if not adapted and for the real 2567 // Result is the frame pointer for the frame if not adapted and for the real
2485 // frame below the adaptor frame if adapted. 2568 // frame below the adaptor frame if adapted.
2486 __ bind(&done); 2569 __ bind(&done);
2487 } 2570 }
2488 2571
2489 2572
2490 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { 2573 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
2491 Operand elem = ToOperand(instr->InputAt(0)); 2574 Operand elem = ToOperand(instr->InputAt(0));
2492 Register result = ToRegister(instr->result()); 2575 Register result = ToRegister(instr->result());
2493 2576
2494 NearLabel done; 2577 Label done;
2495 2578
2496 // If no arguments adaptor frame the number of arguments is fixed. 2579 // If no arguments adaptor frame the number of arguments is fixed.
2497 __ cmp(ebp, elem); 2580 __ cmp(ebp, elem);
2498 __ mov(result, Immediate(scope()->num_parameters())); 2581 __ mov(result, Immediate(scope()->num_parameters()));
2499 __ j(equal, &done); 2582 __ j(equal, &done, Label::kNear);
2500 2583
2501 // Arguments adaptor frame present. Get argument length from there. 2584 // Arguments adaptor frame present. Get argument length from there.
2502 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2585 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2503 __ mov(result, Operand(result, 2586 __ mov(result, Operand(result,
2504 ArgumentsAdaptorFrameConstants::kLengthOffset)); 2587 ArgumentsAdaptorFrameConstants::kLengthOffset));
2505 __ SmiUntag(result); 2588 __ SmiUntag(result);
2506 2589
2507 // Argument length is in result register. 2590 // Argument length is in result register.
2508 __ bind(&done); 2591 __ bind(&done);
2509 } 2592 }
2510 2593
2511 2594
2512 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 2595 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
2513 Register receiver = ToRegister(instr->receiver()); 2596 Register receiver = ToRegister(instr->receiver());
2514 Register function = ToRegister(instr->function()); 2597 Register function = ToRegister(instr->function());
2515 Register length = ToRegister(instr->length()); 2598 Register length = ToRegister(instr->length());
2516 Register elements = ToRegister(instr->elements()); 2599 Register elements = ToRegister(instr->elements());
2517 Register scratch = ToRegister(instr->TempAt(0)); 2600 Register scratch = ToRegister(instr->TempAt(0));
2518 ASSERT(receiver.is(eax)); // Used for parameter count. 2601 ASSERT(receiver.is(eax)); // Used for parameter count.
2519 ASSERT(function.is(edi)); // Required by InvokeFunction. 2602 ASSERT(function.is(edi)); // Required by InvokeFunction.
2520 ASSERT(ToRegister(instr->result()).is(eax)); 2603 ASSERT(ToRegister(instr->result()).is(eax));
2521 2604
2522 // If the receiver is null or undefined, we have to pass the global object 2605 // If the receiver is null or undefined, we have to pass the global object
2523 // as a receiver. 2606 // as a receiver.
2524 NearLabel global_object, receiver_ok; 2607 Label global_object, receiver_ok;
2525 __ cmp(receiver, factory()->null_value()); 2608 __ cmp(receiver, factory()->null_value());
2526 __ j(equal, &global_object); 2609 __ j(equal, &global_object, Label::kNear);
2527 __ cmp(receiver, factory()->undefined_value()); 2610 __ cmp(receiver, factory()->undefined_value());
2528 __ j(equal, &global_object); 2611 __ j(equal, &global_object, Label::kNear);
2529 2612
2530 // The receiver should be a JS object. 2613 // The receiver should be a JS object.
2531 __ test(receiver, Immediate(kSmiTagMask)); 2614 __ test(receiver, Immediate(kSmiTagMask));
2532 DeoptimizeIf(equal, instr->environment()); 2615 DeoptimizeIf(equal, instr->environment());
2533 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch); 2616 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch);
2534 DeoptimizeIf(below, instr->environment()); 2617 DeoptimizeIf(below, instr->environment());
2535 __ jmp(&receiver_ok); 2618 __ jmp(&receiver_ok, Label::kNear);
2536 2619
2537 __ bind(&global_object); 2620 __ bind(&global_object);
2538 // TODO(kmillikin): We have a hydrogen value for the global object. See 2621 // TODO(kmillikin): We have a hydrogen value for the global object. See
2539 // if it's better to use it than to explicitly fetch it from the context 2622 // if it's better to use it than to explicitly fetch it from the context
2540 // here. 2623 // here.
2541 __ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset)); 2624 __ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset));
2542 __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); 2625 __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX));
2543 __ bind(&receiver_ok); 2626 __ bind(&receiver_ok);
2544 2627
2545 // Copy the arguments to this function possibly from the 2628 // Copy the arguments to this function possibly from the
2546 // adaptor frame below it. 2629 // adaptor frame below it.
2547 const uint32_t kArgumentsLimit = 1 * KB; 2630 const uint32_t kArgumentsLimit = 1 * KB;
2548 __ cmp(length, kArgumentsLimit); 2631 __ cmp(length, kArgumentsLimit);
2549 DeoptimizeIf(above, instr->environment()); 2632 DeoptimizeIf(above, instr->environment());
2550 2633
2551 __ push(receiver); 2634 __ push(receiver);
2552 __ mov(receiver, length); 2635 __ mov(receiver, length);
2553 2636
2554 // Loop through the arguments pushing them onto the execution 2637 // Loop through the arguments pushing them onto the execution
2555 // stack. 2638 // stack.
2556 NearLabel invoke, loop; 2639 Label invoke, loop;
2557 // length is a small non-negative integer, due to the test above. 2640 // length is a small non-negative integer, due to the test above.
2558 __ test(length, Operand(length)); 2641 __ test(length, Operand(length));
2559 __ j(zero, &invoke); 2642 __ j(zero, &invoke, Label::kNear);
2560 __ bind(&loop); 2643 __ bind(&loop);
2561 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); 2644 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
2562 __ dec(length); 2645 __ dec(length);
2563 __ j(not_zero, &loop); 2646 __ j(not_zero, &loop);
2564 2647
2565 // Invoke the function. 2648 // Invoke the function.
2566 __ bind(&invoke); 2649 __ bind(&invoke);
2567 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment()); 2650 ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
2568 LPointerMap* pointers = instr->pointer_map(); 2651 LPointerMap* pointers = instr->pointer_map();
2569 LEnvironment* env = instr->deoptimization_environment(); 2652 LEnvironment* env = instr->deoptimization_environment();
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
2901 __ sub(Operand(esp), Immediate(kDoubleSize)); 2984 __ sub(Operand(esp), Immediate(kDoubleSize));
2902 __ fstp_d(Operand(esp, 0)); 2985 __ fstp_d(Operand(esp, 0));
2903 __ movdbl(result_reg, Operand(esp, 0)); 2986 __ movdbl(result_reg, Operand(esp, 0));
2904 __ add(Operand(esp), Immediate(kDoubleSize)); 2987 __ add(Operand(esp), Immediate(kDoubleSize));
2905 } 2988 }
2906 2989
2907 2990
2908 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { 2991 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
2909 ASSERT(instr->InputAt(0)->Equals(instr->result())); 2992 ASSERT(instr->InputAt(0)->Equals(instr->result()));
2910 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); 2993 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0));
2911 NearLabel positive, done, zero, negative; 2994 Label positive, done, zero;
2912 __ xorps(xmm0, xmm0); 2995 __ xorps(xmm0, xmm0);
2913 __ ucomisd(input_reg, xmm0); 2996 __ ucomisd(input_reg, xmm0);
2914 __ j(above, &positive); 2997 __ j(above, &positive, Label::kNear);
2915 __ j(equal, &zero); 2998 __ j(equal, &zero, Label::kNear);
2916 ExternalReference nan = ExternalReference::address_of_nan(); 2999 ExternalReference nan = ExternalReference::address_of_nan();
2917 __ movdbl(input_reg, Operand::StaticVariable(nan)); 3000 __ movdbl(input_reg, Operand::StaticVariable(nan));
2918 __ jmp(&done); 3001 __ jmp(&done, Label::kNear);
2919 __ bind(&zero); 3002 __ bind(&zero);
2920 __ push(Immediate(0xFFF00000)); 3003 __ push(Immediate(0xFFF00000));
2921 __ push(Immediate(0)); 3004 __ push(Immediate(0));
2922 __ movdbl(input_reg, Operand(esp, 0)); 3005 __ movdbl(input_reg, Operand(esp, 0));
2923 __ add(Operand(esp), Immediate(kDoubleSize)); 3006 __ add(Operand(esp), Immediate(kDoubleSize));
2924 __ jmp(&done); 3007 __ jmp(&done, Label::kNear);
2925 __ bind(&positive); 3008 __ bind(&positive);
2926 __ fldln2(); 3009 __ fldln2();
2927 __ sub(Operand(esp), Immediate(kDoubleSize)); 3010 __ sub(Operand(esp), Immediate(kDoubleSize));
2928 __ movdbl(Operand(esp, 0), input_reg); 3011 __ movdbl(Operand(esp, 0), input_reg);
2929 __ fld_d(Operand(esp, 0)); 3012 __ fld_d(Operand(esp, 0));
2930 __ fyl2x(); 3013 __ fyl2x();
2931 __ fstp_d(Operand(esp, 0)); 3014 __ fstp_d(Operand(esp, 0));
2932 __ movdbl(input_reg, Operand(esp, 0)); 3015 __ movdbl(input_reg, Operand(esp, 0));
2933 __ add(Operand(esp), Immediate(kDoubleSize)); 3016 __ add(Operand(esp), Immediate(kDoubleSize));
2934 __ bind(&done); 3017 __ bind(&done);
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
3113 3196
3114 3197
3115 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { 3198 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
3116 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); 3199 __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
3117 DeoptimizeIf(above_equal, instr->environment()); 3200 DeoptimizeIf(above_equal, instr->environment());
3118 } 3201 }
3119 3202
3120 3203
3121 void LCodeGen::DoStoreKeyedSpecializedArrayElement( 3204 void LCodeGen::DoStoreKeyedSpecializedArrayElement(
3122 LStoreKeyedSpecializedArrayElement* instr) { 3205 LStoreKeyedSpecializedArrayElement* instr) {
3123 Register external_pointer = ToRegister(instr->external_pointer());
3124 Register key = ToRegister(instr->key());
3125 ExternalArrayType array_type = instr->array_type(); 3206 ExternalArrayType array_type = instr->array_type();
3207 Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
3208 instr->key(), array_type));
3126 if (array_type == kExternalFloatArray) { 3209 if (array_type == kExternalFloatArray) {
3127 __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value())); 3210 __ cvtsd2ss(xmm0, ToDoubleRegister(instr->value()));
3128 __ movss(Operand(external_pointer, key, times_4, 0), xmm0); 3211 __ movss(operand, xmm0);
3129 } else if (array_type == kExternalDoubleArray) { 3212 } else if (array_type == kExternalDoubleArray) {
3130 __ movdbl(Operand(external_pointer, key, times_8, 0), 3213 __ movdbl(operand, ToDoubleRegister(instr->value()));
3131 ToDoubleRegister(instr->value()));
3132 } else { 3214 } else {
3133 Register value = ToRegister(instr->value()); 3215 Register value = ToRegister(instr->value());
3134 switch (array_type) { 3216 switch (array_type) {
3135 case kExternalPixelArray: { 3217 case kExternalPixelArray:
3136 // Clamp the value to [0..255].
3137 Register temp = ToRegister(instr->TempAt(0));
3138 // The dec_b below requires that the clamped value is in a byte
3139 // register. eax is an arbitrary choice to satisfy this requirement, we
3140 // hinted the register allocator to give us eax when building the
3141 // instruction.
3142 ASSERT(temp.is(eax));
3143 __ mov(temp, ToRegister(instr->value()));
3144 NearLabel done;
3145 __ test(temp, Immediate(0xFFFFFF00));
3146 __ j(zero, &done);
3147 __ setcc(negative, temp); // 1 if negative, 0 if positive.
3148 __ dec_b(temp); // 0 if negative, 255 if positive.
3149 __ bind(&done);
3150 __ mov_b(Operand(external_pointer, key, times_1, 0), temp);
3151 break;
3152 }
3153 case kExternalByteArray: 3218 case kExternalByteArray:
3154 case kExternalUnsignedByteArray: 3219 case kExternalUnsignedByteArray:
3155 __ mov_b(Operand(external_pointer, key, times_1, 0), value); 3220 __ mov_b(operand, value);
3156 break; 3221 break;
3157 case kExternalShortArray: 3222 case kExternalShortArray:
3158 case kExternalUnsignedShortArray: 3223 case kExternalUnsignedShortArray:
3159 __ mov_w(Operand(external_pointer, key, times_2, 0), value); 3224 __ mov_w(operand, value);
3160 break; 3225 break;
3161 case kExternalIntArray: 3226 case kExternalIntArray:
3162 case kExternalUnsignedIntArray: 3227 case kExternalUnsignedIntArray:
3163 __ mov(Operand(external_pointer, key, times_4, 0), value); 3228 __ mov(operand, value);
3164 break; 3229 break;
3165 case kExternalFloatArray: 3230 case kExternalFloatArray:
3166 case kExternalDoubleArray: 3231 case kExternalDoubleArray:
3167 UNREACHABLE(); 3232 UNREACHABLE();
3168 break; 3233 break;
3169 } 3234 }
3170 } 3235 }
3171 } 3236 }
3172 3237
3173 3238
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
3243 return; 3308 return;
3244 } 3309 }
3245 } else { 3310 } else {
3246 index = ToRegister(instr->index()); 3311 index = ToRegister(instr->index());
3247 } 3312 }
3248 Register result = ToRegister(instr->result()); 3313 Register result = ToRegister(instr->result());
3249 3314
3250 DeferredStringCharCodeAt* deferred = 3315 DeferredStringCharCodeAt* deferred =
3251 new DeferredStringCharCodeAt(this, instr); 3316 new DeferredStringCharCodeAt(this, instr);
3252 3317
3253 NearLabel flat_string, ascii_string, done; 3318 Label flat_string, ascii_string, done;
3254 3319
3255 // Fetch the instance type of the receiver into result register. 3320 // Fetch the instance type of the receiver into result register.
3256 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); 3321 __ mov(result, FieldOperand(string, HeapObject::kMapOffset));
3257 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); 3322 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
3258 3323
3259 // We need special handling for non-flat strings. 3324 // We need special handling for non-flat strings.
3260 STATIC_ASSERT(kSeqStringTag == 0); 3325 STATIC_ASSERT(kSeqStringTag == 0);
3261 __ test(result, Immediate(kStringRepresentationMask)); 3326 __ test(result, Immediate(kStringRepresentationMask));
3262 __ j(zero, &flat_string); 3327 __ j(zero, &flat_string, Label::kNear);
3263 3328
3264 // Handle non-flat strings. 3329 // Handle non-flat strings.
3265 __ test(result, Immediate(kIsConsStringMask)); 3330 __ test(result, Immediate(kIsConsStringMask));
3266 __ j(zero, deferred->entry()); 3331 __ j(zero, deferred->entry());
3267 3332
3268 // ConsString. 3333 // ConsString.
3269 // Check whether the right hand side is the empty string (i.e. if 3334 // Check whether the right hand side is the empty string (i.e. if
3270 // this is really a flat string in a cons string). If that is not 3335 // this is really a flat string in a cons string). If that is not
3271 // the case we would rather go to the runtime system now to flatten 3336 // the case we would rather go to the runtime system now to flatten
3272 // the string. 3337 // the string.
3273 __ cmp(FieldOperand(string, ConsString::kSecondOffset), 3338 __ cmp(FieldOperand(string, ConsString::kSecondOffset),
3274 Immediate(factory()->empty_string())); 3339 Immediate(factory()->empty_string()));
3275 __ j(not_equal, deferred->entry()); 3340 __ j(not_equal, deferred->entry());
3276 // Get the first of the two strings and load its instance type. 3341 // Get the first of the two strings and load its instance type.
3277 __ mov(string, FieldOperand(string, ConsString::kFirstOffset)); 3342 __ mov(string, FieldOperand(string, ConsString::kFirstOffset));
3278 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); 3343 __ mov(result, FieldOperand(string, HeapObject::kMapOffset));
3279 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); 3344 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
3280 // If the first cons component is also non-flat, then go to runtime. 3345 // If the first cons component is also non-flat, then go to runtime.
3281 STATIC_ASSERT(kSeqStringTag == 0); 3346 STATIC_ASSERT(kSeqStringTag == 0);
3282 __ test(result, Immediate(kStringRepresentationMask)); 3347 __ test(result, Immediate(kStringRepresentationMask));
3283 __ j(not_zero, deferred->entry()); 3348 __ j(not_zero, deferred->entry());
3284 3349
3285 // Check for ASCII or two-byte string. 3350 // Check for ASCII or two-byte string.
3286 __ bind(&flat_string); 3351 __ bind(&flat_string);
3287 STATIC_ASSERT(kAsciiStringTag != 0); 3352 STATIC_ASSERT(kAsciiStringTag != 0);
3288 __ test(result, Immediate(kStringEncodingMask)); 3353 __ test(result, Immediate(kStringEncodingMask));
3289 __ j(not_zero, &ascii_string); 3354 __ j(not_zero, &ascii_string, Label::kNear);
3290 3355
3291 // Two-byte string. 3356 // Two-byte string.
3292 // Load the two-byte character code into the result register. 3357 // Load the two-byte character code into the result register.
3293 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 3358 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3294 if (instr->index()->IsConstantOperand()) { 3359 if (instr->index()->IsConstantOperand()) {
3295 __ movzx_w(result, 3360 __ movzx_w(result,
3296 FieldOperand(string, 3361 FieldOperand(string,
3297 SeqTwoByteString::kHeaderSize + 3362 SeqTwoByteString::kHeaderSize +
3298 (kUC16Size * const_index))); 3363 (kUC16Size * const_index)));
3299 } else { 3364 } else {
3300 __ movzx_w(result, FieldOperand(string, 3365 __ movzx_w(result, FieldOperand(string,
3301 index, 3366 index,
3302 times_2, 3367 times_2,
3303 SeqTwoByteString::kHeaderSize)); 3368 SeqTwoByteString::kHeaderSize));
3304 } 3369 }
3305 __ jmp(&done); 3370 __ jmp(&done, Label::kNear);
3306 3371
3307 // ASCII string. 3372 // ASCII string.
3308 // Load the byte into the result register. 3373 // Load the byte into the result register.
3309 __ bind(&ascii_string); 3374 __ bind(&ascii_string);
3310 if (instr->index()->IsConstantOperand()) { 3375 if (instr->index()->IsConstantOperand()) {
3311 __ movzx_b(result, FieldOperand(string, 3376 __ movzx_b(result, FieldOperand(string,
3312 SeqAsciiString::kHeaderSize + const_index)); 3377 SeqAsciiString::kHeaderSize + const_index));
3313 } else { 3378 } else {
3314 __ movzx_b(result, FieldOperand(string, 3379 __ movzx_b(result, FieldOperand(string,
3315 index, 3380 index,
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
3456 Label slow; 3521 Label slow;
3457 Register reg = ToRegister(instr->InputAt(0)); 3522 Register reg = ToRegister(instr->InputAt(0));
3458 Register tmp = reg.is(eax) ? ecx : eax; 3523 Register tmp = reg.is(eax) ? ecx : eax;
3459 3524
3460 // Preserve the value of all registers. 3525 // Preserve the value of all registers.
3461 PushSafepointRegistersScope scope(this); 3526 PushSafepointRegistersScope scope(this);
3462 3527
3463 // There was overflow, so bits 30 and 31 of the original integer 3528 // There was overflow, so bits 30 and 31 of the original integer
3464 // disagree. Try to allocate a heap number in new space and store 3529 // disagree. Try to allocate a heap number in new space and store
3465 // the value in there. If that fails, call the runtime system. 3530 // the value in there. If that fails, call the runtime system.
3466 NearLabel done; 3531 Label done;
3467 __ SmiUntag(reg); 3532 __ SmiUntag(reg);
3468 __ xor_(reg, 0x80000000); 3533 __ xor_(reg, 0x80000000);
3469 __ cvtsi2sd(xmm0, Operand(reg)); 3534 __ cvtsi2sd(xmm0, Operand(reg));
3470 if (FLAG_inline_new) { 3535 if (FLAG_inline_new) {
3471 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); 3536 __ AllocateHeapNumber(reg, tmp, no_reg, &slow);
3472 __ jmp(&done); 3537 __ jmp(&done, Label::kNear);
3473 } 3538 }
3474 3539
3475 // Slow case: Call the runtime system to do the number allocation. 3540 // Slow case: Call the runtime system to do the number allocation.
3476 __ bind(&slow); 3541 __ bind(&slow);
3477 3542
3478 // TODO(3095996): Put a valid pointer value in the stack slot where the result 3543 // TODO(3095996): Put a valid pointer value in the stack slot where the result
3479 // register is stored, as this register is in the pointer map, but contains an 3544 // register is stored, as this register is in the pointer map, but contains an
3480 // integer value. 3545 // integer value.
3481 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); 3546 __ StoreToSafepointRegisterSlot(reg, Immediate(0));
3482 3547
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
3544 __ test(ToRegister(input), Immediate(kSmiTagMask)); 3609 __ test(ToRegister(input), Immediate(kSmiTagMask));
3545 DeoptimizeIf(not_zero, instr->environment()); 3610 DeoptimizeIf(not_zero, instr->environment());
3546 } 3611 }
3547 __ SmiUntag(ToRegister(input)); 3612 __ SmiUntag(ToRegister(input));
3548 } 3613 }
3549 3614
3550 3615
3551 void LCodeGen::EmitNumberUntagD(Register input_reg, 3616 void LCodeGen::EmitNumberUntagD(Register input_reg,
3552 XMMRegister result_reg, 3617 XMMRegister result_reg,
3553 LEnvironment* env) { 3618 LEnvironment* env) {
3554 NearLabel load_smi, heap_number, done; 3619 Label load_smi, heap_number, done;
3555 3620
3556 // Smi check. 3621 // Smi check.
3557 __ test(input_reg, Immediate(kSmiTagMask)); 3622 __ test(input_reg, Immediate(kSmiTagMask));
3558 __ j(zero, &load_smi, not_taken); 3623 __ j(zero, &load_smi, Label::kNear);
3559 3624
3560 // Heap number map check. 3625 // Heap number map check.
3561 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 3626 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
3562 factory()->heap_number_map()); 3627 factory()->heap_number_map());
3563 __ j(equal, &heap_number); 3628 __ j(equal, &heap_number, Label::kNear);
3564 3629
3565 __ cmp(input_reg, factory()->undefined_value()); 3630 __ cmp(input_reg, factory()->undefined_value());
3566 DeoptimizeIf(not_equal, env); 3631 DeoptimizeIf(not_equal, env);
3567 3632
3568 // Convert undefined to NaN. 3633 // Convert undefined to NaN.
3569 ExternalReference nan = ExternalReference::address_of_nan(); 3634 ExternalReference nan = ExternalReference::address_of_nan();
3570 __ movdbl(result_reg, Operand::StaticVariable(nan)); 3635 __ movdbl(result_reg, Operand::StaticVariable(nan));
3571 __ jmp(&done); 3636 __ jmp(&done, Label::kNear);
3572 3637
3573 // Heap number to XMM conversion. 3638 // Heap number to XMM conversion.
3574 __ bind(&heap_number); 3639 __ bind(&heap_number);
3575 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); 3640 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
3576 __ jmp(&done); 3641 __ jmp(&done, Label::kNear);
3577 3642
3578 // Smi to XMM conversion 3643 // Smi to XMM conversion
3579 __ bind(&load_smi); 3644 __ bind(&load_smi);
3580 __ SmiUntag(input_reg); // Untag smi before converting to float. 3645 __ SmiUntag(input_reg); // Untag smi before converting to float.
3581 __ cvtsi2sd(result_reg, Operand(input_reg)); 3646 __ cvtsi2sd(result_reg, Operand(input_reg));
3582 __ SmiTag(input_reg); // Retag smi. 3647 __ SmiTag(input_reg); // Retag smi.
3583 __ bind(&done); 3648 __ bind(&done);
3584 } 3649 }
3585 3650
3586 3651
3587 class DeferredTaggedToI: public LDeferredCode { 3652 class DeferredTaggedToI: public LDeferredCode {
3588 public: 3653 public:
3589 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 3654 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
3590 : LDeferredCode(codegen), instr_(instr) { } 3655 : LDeferredCode(codegen), instr_(instr) { }
3591 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } 3656 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); }
3592 private: 3657 private:
3593 LTaggedToI* instr_; 3658 LTaggedToI* instr_;
3594 }; 3659 };
3595 3660
3596 3661
3597 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { 3662 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) {
3598 NearLabel done, heap_number; 3663 Label done, heap_number;
3599 Register input_reg = ToRegister(instr->InputAt(0)); 3664 Register input_reg = ToRegister(instr->InputAt(0));
3600 3665
3601 // Heap number map check. 3666 // Heap number map check.
3602 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 3667 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
3603 factory()->heap_number_map()); 3668 factory()->heap_number_map());
3604 3669
3605 if (instr->truncating()) { 3670 if (instr->truncating()) {
3606 __ j(equal, &heap_number); 3671 __ j(equal, &heap_number, Label::kNear);
3607 // Check for undefined. Undefined is converted to zero for truncating 3672 // Check for undefined. Undefined is converted to zero for truncating
3608 // conversions. 3673 // conversions.
3609 __ cmp(input_reg, factory()->undefined_value()); 3674 __ cmp(input_reg, factory()->undefined_value());
3610 DeoptimizeIf(not_equal, instr->environment()); 3675 DeoptimizeIf(not_equal, instr->environment());
3611 __ mov(input_reg, 0); 3676 __ mov(input_reg, 0);
3612 __ jmp(&done); 3677 __ jmp(&done, Label::kNear);
3613 3678
3614 __ bind(&heap_number); 3679 __ bind(&heap_number);
3615 if (CpuFeatures::IsSupported(SSE3)) { 3680 if (CpuFeatures::IsSupported(SSE3)) {
3616 CpuFeatures::Scope scope(SSE3); 3681 CpuFeatures::Scope scope(SSE3);
3617 NearLabel convert; 3682 Label convert;
3618 // Use more powerful conversion when sse3 is available. 3683 // Use more powerful conversion when sse3 is available.
3619 // Load x87 register with heap number. 3684 // Load x87 register with heap number.
3620 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 3685 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
3621 // Get exponent alone and check for too-big exponent. 3686 // Get exponent alone and check for too-big exponent.
3622 __ mov(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 3687 __ mov(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3623 __ and_(input_reg, HeapNumber::kExponentMask); 3688 __ and_(input_reg, HeapNumber::kExponentMask);
3624 const uint32_t kTooBigExponent = 3689 const uint32_t kTooBigExponent =
3625 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; 3690 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
3626 __ cmp(Operand(input_reg), Immediate(kTooBigExponent)); 3691 __ cmp(Operand(input_reg), Immediate(kTooBigExponent));
3627 __ j(less, &convert); 3692 __ j(less, &convert, Label::kNear);
3628 // Pop FPU stack before deoptimizing. 3693 // Pop FPU stack before deoptimizing.
3629 __ ffree(0); 3694 __ ffree(0);
3630 __ fincstp(); 3695 __ fincstp();
3631 DeoptimizeIf(no_condition, instr->environment()); 3696 DeoptimizeIf(no_condition, instr->environment());
3632 3697
3633 // Reserve space for 64 bit answer. 3698 // Reserve space for 64 bit answer.
3634 __ bind(&convert); 3699 __ bind(&convert);
3635 __ sub(Operand(esp), Immediate(kDoubleSize)); 3700 __ sub(Operand(esp), Immediate(kDoubleSize));
3636 // Do conversion, which cannot fail because we checked the exponent. 3701 // Do conversion, which cannot fail because we checked the exponent.
3637 __ fisttp_d(Operand(esp, 0)); 3702 __ fisttp_d(Operand(esp, 0));
3638 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. 3703 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result.
3639 __ add(Operand(esp), Immediate(kDoubleSize)); 3704 __ add(Operand(esp), Immediate(kDoubleSize));
3640 } else { 3705 } else {
3641 NearLabel deopt;
3642 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); 3706 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0));
3643 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 3707 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
3644 __ cvttsd2si(input_reg, Operand(xmm0)); 3708 __ cvttsd2si(input_reg, Operand(xmm0));
3645 __ cmp(input_reg, 0x80000000u); 3709 __ cmp(input_reg, 0x80000000u);
3646 __ j(not_equal, &done); 3710 __ j(not_equal, &done);
3647 // Check if the input was 0x8000000 (kMinInt). 3711 // Check if the input was 0x8000000 (kMinInt).
3648 // If no, then we got an overflow and we deoptimize. 3712 // If no, then we got an overflow and we deoptimize.
3649 ExternalReference min_int = ExternalReference::address_of_min_int(); 3713 ExternalReference min_int = ExternalReference::address_of_min_int();
3650 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); 3714 __ movdbl(xmm_temp, Operand::StaticVariable(min_int));
3651 __ ucomisd(xmm_temp, xmm0); 3715 __ ucomisd(xmm_temp, xmm0);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
3718 Register result_reg = ToRegister(result); 3782 Register result_reg = ToRegister(result);
3719 3783
3720 if (instr->truncating()) { 3784 if (instr->truncating()) {
3721 // Performs a truncating conversion of a floating point number as used by 3785 // Performs a truncating conversion of a floating point number as used by
3722 // the JS bitwise operations. 3786 // the JS bitwise operations.
3723 __ cvttsd2si(result_reg, Operand(input_reg)); 3787 __ cvttsd2si(result_reg, Operand(input_reg));
3724 __ cmp(result_reg, 0x80000000u); 3788 __ cmp(result_reg, 0x80000000u);
3725 if (CpuFeatures::IsSupported(SSE3)) { 3789 if (CpuFeatures::IsSupported(SSE3)) {
3726 // This will deoptimize if the exponent of the input in out of range. 3790 // This will deoptimize if the exponent of the input in out of range.
3727 CpuFeatures::Scope scope(SSE3); 3791 CpuFeatures::Scope scope(SSE3);
3728 NearLabel convert, done; 3792 Label convert, done;
3729 __ j(not_equal, &done); 3793 __ j(not_equal, &done, Label::kNear);
3730 __ sub(Operand(esp), Immediate(kDoubleSize)); 3794 __ sub(Operand(esp), Immediate(kDoubleSize));
3731 __ movdbl(Operand(esp, 0), input_reg); 3795 __ movdbl(Operand(esp, 0), input_reg);
3732 // Get exponent alone and check for too-big exponent. 3796 // Get exponent alone and check for too-big exponent.
3733 __ mov(result_reg, Operand(esp, sizeof(int32_t))); 3797 __ mov(result_reg, Operand(esp, sizeof(int32_t)));
3734 __ and_(result_reg, HeapNumber::kExponentMask); 3798 __ and_(result_reg, HeapNumber::kExponentMask);
3735 const uint32_t kTooBigExponent = 3799 const uint32_t kTooBigExponent =
3736 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; 3800 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
3737 __ cmp(Operand(result_reg), Immediate(kTooBigExponent)); 3801 __ cmp(Operand(result_reg), Immediate(kTooBigExponent));
3738 __ j(less, &convert); 3802 __ j(less, &convert, Label::kNear);
3739 __ add(Operand(esp), Immediate(kDoubleSize)); 3803 __ add(Operand(esp), Immediate(kDoubleSize));
3740 DeoptimizeIf(no_condition, instr->environment()); 3804 DeoptimizeIf(no_condition, instr->environment());
3741 __ bind(&convert); 3805 __ bind(&convert);
3742 // Do conversion, which cannot fail because we checked the exponent. 3806 // Do conversion, which cannot fail because we checked the exponent.
3743 __ fld_d(Operand(esp, 0)); 3807 __ fld_d(Operand(esp, 0));
3744 __ fisttp_d(Operand(esp, 0)); 3808 __ fisttp_d(Operand(esp, 0));
3745 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. 3809 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result.
3746 __ add(Operand(esp), Immediate(kDoubleSize)); 3810 __ add(Operand(esp), Immediate(kDoubleSize));
3747 __ bind(&done); 3811 __ bind(&done);
3748 } else { 3812 } else {
3749 NearLabel done; 3813 Label done;
3750 Register temp_reg = ToRegister(instr->TempAt(0)); 3814 Register temp_reg = ToRegister(instr->TempAt(0));
3751 XMMRegister xmm_scratch = xmm0; 3815 XMMRegister xmm_scratch = xmm0;
3752 3816
3753 // If cvttsd2si succeeded, we're done. Otherwise, we attempt 3817 // If cvttsd2si succeeded, we're done. Otherwise, we attempt
3754 // manual conversion. 3818 // manual conversion.
3755 __ j(not_equal, &done); 3819 __ j(not_equal, &done, Label::kNear);
3756 3820
3757 // Get high 32 bits of the input in result_reg and temp_reg. 3821 // Get high 32 bits of the input in result_reg and temp_reg.
3758 __ pshufd(xmm_scratch, input_reg, 1); 3822 __ pshufd(xmm_scratch, input_reg, 1);
3759 __ movd(Operand(temp_reg), xmm_scratch); 3823 __ movd(Operand(temp_reg), xmm_scratch);
3760 __ mov(result_reg, temp_reg); 3824 __ mov(result_reg, temp_reg);
3761 3825
3762 // Prepare negation mask in temp_reg. 3826 // Prepare negation mask in temp_reg.
3763 __ sar(temp_reg, kBitsPerInt - 1); 3827 __ sar(temp_reg, kBitsPerInt - 1);
3764 3828
3765 // Extract the exponent from result_reg and subtract adjusted 3829 // Extract the exponent from result_reg and subtract adjusted
(...skipping 29 matching lines...) Expand all
3795 // Shift the input right and extract low 32 bits. 3859 // Shift the input right and extract low 32 bits.
3796 __ psrlq(input_reg, xmm_scratch); 3860 __ psrlq(input_reg, xmm_scratch);
3797 __ movd(Operand(result_reg), input_reg); 3861 __ movd(Operand(result_reg), input_reg);
3798 3862
3799 // Use the prepared mask in temp_reg to negate the result if necessary. 3863 // Use the prepared mask in temp_reg to negate the result if necessary.
3800 __ xor_(result_reg, Operand(temp_reg)); 3864 __ xor_(result_reg, Operand(temp_reg));
3801 __ sub(result_reg, Operand(temp_reg)); 3865 __ sub(result_reg, Operand(temp_reg));
3802 __ bind(&done); 3866 __ bind(&done);
3803 } 3867 }
3804 } else { 3868 } else {
3805 NearLabel done; 3869 Label done;
3806 __ cvttsd2si(result_reg, Operand(input_reg)); 3870 __ cvttsd2si(result_reg, Operand(input_reg));
3807 __ cvtsi2sd(xmm0, Operand(result_reg)); 3871 __ cvtsi2sd(xmm0, Operand(result_reg));
3808 __ ucomisd(xmm0, input_reg); 3872 __ ucomisd(xmm0, input_reg);
3809 DeoptimizeIf(not_equal, instr->environment()); 3873 DeoptimizeIf(not_equal, instr->environment());
3810 DeoptimizeIf(parity_even, instr->environment()); // NaN. 3874 DeoptimizeIf(parity_even, instr->environment()); // NaN.
3811 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3875 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3812 // The integer converted back is equal to the original. We 3876 // The integer converted back is equal to the original. We
3813 // only have to test if we got -0 as an input. 3877 // only have to test if we got -0 as an input.
3814 __ test(result_reg, Operand(result_reg)); 3878 __ test(result_reg, Operand(result_reg));
3815 __ j(not_zero, &done); 3879 __ j(not_zero, &done, Label::kNear);
3816 __ movmskpd(result_reg, input_reg); 3880 __ movmskpd(result_reg, input_reg);
3817 // Bit 0 contains the sign of the double in input_reg. 3881 // Bit 0 contains the sign of the double in input_reg.
3818 // If input was positive, we are ok and return 0, otherwise 3882 // If input was positive, we are ok and return 0, otherwise
3819 // deoptimize. 3883 // deoptimize.
3820 __ and_(result_reg, 1); 3884 __ and_(result_reg, 1);
3821 DeoptimizeIf(not_zero, instr->environment()); 3885 DeoptimizeIf(not_zero, instr->environment());
3822 } 3886 }
3823 __ bind(&done); 3887 __ bind(&done);
3824 } 3888 }
3825 } 3889 }
3826 3890
3827 3891
3828 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 3892 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
3829 LOperand* input = instr->InputAt(0); 3893 LOperand* input = instr->InputAt(0);
3830 __ test(ToRegister(input), Immediate(kSmiTagMask)); 3894 __ test(ToRegister(input), Immediate(kSmiTagMask));
3831 DeoptimizeIf(not_zero, instr->environment()); 3895 DeoptimizeIf(not_zero, instr->environment());
3832 } 3896 }
3833 3897
3834 3898
3835 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 3899 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
3836 LOperand* input = instr->InputAt(0); 3900 LOperand* input = instr->InputAt(0);
3837 __ test(ToRegister(input), Immediate(kSmiTagMask)); 3901 __ test(ToRegister(input), Immediate(kSmiTagMask));
3838 DeoptimizeIf(zero, instr->environment()); 3902 DeoptimizeIf(zero, instr->environment());
3839 } 3903 }
3840 3904
3841 3905
3842 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 3906 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
3843 Register input = ToRegister(instr->InputAt(0)); 3907 Register input = ToRegister(instr->InputAt(0));
3844 Register temp = ToRegister(instr->TempAt(0)); 3908 Register temp = ToRegister(instr->TempAt(0));
3845 InstanceType first = instr->hydrogen()->first();
3846 InstanceType last = instr->hydrogen()->last();
3847 3909
3848 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 3910 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
3849 3911
3850 // If there is only one type in the interval check for equality. 3912 if (instr->hydrogen()->is_interval_check()) {
3851 if (first == last) { 3913 InstanceType first;
3914 InstanceType last;
3915 instr->hydrogen()->GetCheckInterval(&first, &last);
3916
3852 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 3917 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
3853 static_cast<int8_t>(first)); 3918 static_cast<int8_t>(first));
3854 DeoptimizeIf(not_equal, instr->environment()); 3919
3855 } else if (first == FIRST_STRING_TYPE && last == LAST_STRING_TYPE) { 3920 // If there is only one type in the interval check for equality.
3856 // String has a dedicated bit in instance type. 3921 if (first == last) {
3857 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), kIsNotStringMask); 3922 DeoptimizeIf(not_equal, instr->environment());
3858 DeoptimizeIf(not_zero, instr->environment()); 3923 } else {
3859 } else { 3924 DeoptimizeIf(below, instr->environment());
3860 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 3925 // Omit check for the last type.
3861 static_cast<int8_t>(first)); 3926 if (last != LAST_TYPE) {
3862 DeoptimizeIf(below, instr->environment()); 3927 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
3863 // Omit check for the last type. 3928 static_cast<int8_t>(last));
3864 if (last != LAST_TYPE) { 3929 DeoptimizeIf(above, instr->environment());
3865 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), 3930 }
3866 static_cast<int8_t>(last)); 3931 }
3867 DeoptimizeIf(above, instr->environment()); 3932 } else {
3933 uint8_t mask;
3934 uint8_t tag;
3935 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
3936
3937 if (IsPowerOf2(mask)) {
3938 ASSERT(tag == 0 || IsPowerOf2(tag));
3939 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask);
3940 DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment());
3941 } else {
3942 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
3943 __ and_(temp, mask);
3944 __ cmpb(Operand(temp), tag);
3945 DeoptimizeIf(not_equal, instr->environment());
3868 } 3946 }
3869 } 3947 }
3870 } 3948 }
3871 3949
3872 3950
3873 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { 3951 void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
3874 ASSERT(instr->InputAt(0)->IsRegister()); 3952 ASSERT(instr->InputAt(0)->IsRegister());
3875 Register reg = ToRegister(instr->InputAt(0)); 3953 Register reg = ToRegister(instr->InputAt(0));
3876 __ cmp(reg, instr->hydrogen()->target()); 3954 __ cmp(reg, instr->hydrogen()->target());
3877 DeoptimizeIf(not_equal, instr->environment()); 3955 DeoptimizeIf(not_equal, instr->environment());
3878 } 3956 }
3879 3957
3880 3958
3881 void LCodeGen::DoCheckMap(LCheckMap* instr) { 3959 void LCodeGen::DoCheckMap(LCheckMap* instr) {
3882 LOperand* input = instr->InputAt(0); 3960 LOperand* input = instr->InputAt(0);
3883 ASSERT(input->IsRegister()); 3961 ASSERT(input->IsRegister());
3884 Register reg = ToRegister(input); 3962 Register reg = ToRegister(input);
3885 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 3963 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
3886 instr->hydrogen()->map()); 3964 instr->hydrogen()->map());
3887 DeoptimizeIf(not_equal, instr->environment()); 3965 DeoptimizeIf(not_equal, instr->environment());
3888 } 3966 }
3889 3967
3890 3968
3969 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
3970 XMMRegister value_reg = ToDoubleRegister(instr->unclamped());
3971 Register result_reg = ToRegister(instr->result());
3972 __ ClampDoubleToUint8(value_reg, xmm0, result_reg);
3973 }
3974
3975
3976 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
3977 ASSERT(instr->unclamped()->Equals(instr->result()));
3978 Register value_reg = ToRegister(instr->result());
3979 __ ClampUint8(value_reg);
3980 }
3981
3982
3983 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
3984 ASSERT(instr->unclamped()->Equals(instr->result()));
3985 Register input_reg = ToRegister(instr->unclamped());
3986 Label is_smi, done, heap_number;
3987
3988 __ JumpIfSmi(input_reg, &is_smi);
3989
3990 // Check for heap number
3991 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
3992 factory()->heap_number_map());
3993 __ j(equal, &heap_number, Label::kNear);
3994
3995 // Check for undefined. Undefined is converted to zero for clamping
3996 // conversions.
3997 __ cmp(input_reg, factory()->undefined_value());
3998 DeoptimizeIf(not_equal, instr->environment());
3999 __ mov(input_reg, 0);
4000 __ jmp(&done, Label::kNear);
4001
4002 // Heap number
4003 __ bind(&heap_number);
4004 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
4005 __ ClampDoubleToUint8(xmm0, xmm1, input_reg);
4006 __ jmp(&done, Label::kNear);
4007
4008 // smi
4009 __ bind(&is_smi);
4010 __ SmiUntag(input_reg);
4011 __ ClampUint8(input_reg);
4012
4013 __ bind(&done);
4014 }
4015
4016
3891 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) { 4017 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) {
3892 if (isolate()->heap()->InNewSpace(*object)) { 4018 if (isolate()->heap()->InNewSpace(*object)) {
3893 Handle<JSGlobalPropertyCell> cell = 4019 Handle<JSGlobalPropertyCell> cell =
3894 isolate()->factory()->NewJSGlobalPropertyCell(object); 4020 isolate()->factory()->NewJSGlobalPropertyCell(object);
3895 __ mov(result, Operand::Cell(cell)); 4021 __ mov(result, Operand::Cell(cell));
3896 } else { 4022 } else {
3897 __ mov(result, object); 4023 __ mov(result, object);
3898 } 4024 }
3899 } 4025 }
3900 4026
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
3982 4108
3983 4109
3984 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { 4110 void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
3985 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); 4111 ASSERT(ToRegister(instr->InputAt(0)).is(eax));
3986 __ push(eax); 4112 __ push(eax);
3987 CallRuntime(Runtime::kToFastProperties, 1, instr, CONTEXT_ADJUSTED); 4113 CallRuntime(Runtime::kToFastProperties, 1, instr, CONTEXT_ADJUSTED);
3988 } 4114 }
3989 4115
3990 4116
3991 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { 4117 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
3992 NearLabel materialized; 4118 Label materialized;
3993 // Registers will be used as follows: 4119 // Registers will be used as follows:
3994 // edi = JS function. 4120 // edi = JS function.
3995 // ecx = literals array. 4121 // ecx = literals array.
3996 // ebx = regexp literal. 4122 // ebx = regexp literal.
3997 // eax = regexp literal clone. 4123 // eax = regexp literal clone.
3998 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 4124 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
3999 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); 4125 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset));
4000 int literal_offset = FixedArray::kHeaderSize + 4126 int literal_offset = FixedArray::kHeaderSize +
4001 instr->hydrogen()->literal_index() * kPointerSize; 4127 instr->hydrogen()->literal_index() * kPointerSize;
4002 __ mov(ebx, FieldOperand(ecx, literal_offset)); 4128 __ mov(ebx, FieldOperand(ecx, literal_offset));
4003 __ cmp(ebx, factory()->undefined_value()); 4129 __ cmp(ebx, factory()->undefined_value());
4004 __ j(not_equal, &materialized); 4130 __ j(not_equal, &materialized, Label::kNear);
4005 4131
4006 // Create regexp literal using runtime function 4132 // Create regexp literal using runtime function
4007 // Result will be in eax. 4133 // Result will be in eax.
4008 __ push(ecx); 4134 __ push(ecx);
4009 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); 4135 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
4010 __ push(Immediate(instr->hydrogen()->pattern())); 4136 __ push(Immediate(instr->hydrogen()->pattern()));
4011 __ push(Immediate(instr->hydrogen()->flags())); 4137 __ push(Immediate(instr->hydrogen()->flags()));
4012 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr, RESTORE_CONTEXT); 4138 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr, RESTORE_CONTEXT);
4013 __ mov(ebx, eax); 4139 __ mov(ebx, eax);
4014 4140
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
4070 } 4196 }
4071 CallRuntime(Runtime::kTypeof, 1, instr, RESTORE_CONTEXT); 4197 CallRuntime(Runtime::kTypeof, 1, instr, RESTORE_CONTEXT);
4072 } 4198 }
4073 4199
4074 4200
4075 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { 4201 void LCodeGen::DoTypeofIs(LTypeofIs* instr) {
4076 Register input = ToRegister(instr->InputAt(0)); 4202 Register input = ToRegister(instr->InputAt(0));
4077 Register result = ToRegister(instr->result()); 4203 Register result = ToRegister(instr->result());
4078 Label true_label; 4204 Label true_label;
4079 Label false_label; 4205 Label false_label;
4080 NearLabel done; 4206 Label done;
4081 4207
4082 Condition final_branch_condition = EmitTypeofIs(&true_label, 4208 Condition final_branch_condition = EmitTypeofIs(&true_label,
4083 &false_label, 4209 &false_label,
4084 input, 4210 input,
4085 instr->type_literal()); 4211 instr->type_literal());
4086 __ j(final_branch_condition, &true_label); 4212 __ j(final_branch_condition, &true_label, Label::kNear);
4087 __ bind(&false_label); 4213 __ bind(&false_label);
4088 __ mov(result, factory()->false_value()); 4214 __ mov(result, factory()->false_value());
4089 __ jmp(&done); 4215 __ jmp(&done, Label::kNear);
4090 4216
4091 __ bind(&true_label); 4217 __ bind(&true_label);
4092 __ mov(result, factory()->true_value()); 4218 __ mov(result, factory()->true_value());
4093 4219
4094 __ bind(&done); 4220 __ bind(&done);
4095 } 4221 }
4096 4222
4097 4223
4098 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 4224 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
4099 Register input = ToRegister(instr->InputAt(0)); 4225 Register input = ToRegister(instr->InputAt(0));
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
4173 __ jmp(false_label); 4299 __ jmp(false_label);
4174 // A dead branch instruction will be generated after this point. 4300 // A dead branch instruction will be generated after this point.
4175 } 4301 }
4176 4302
4177 return final_branch_condition; 4303 return final_branch_condition;
4178 } 4304 }
4179 4305
4180 4306
4181 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { 4307 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) {
4182 Register result = ToRegister(instr->result()); 4308 Register result = ToRegister(instr->result());
4183 NearLabel true_label; 4309 Label true_label;
4184 NearLabel false_label; 4310 Label done;
4185 NearLabel done;
4186 4311
4187 EmitIsConstructCall(result); 4312 EmitIsConstructCall(result);
4188 __ j(equal, &true_label); 4313 __ j(equal, &true_label, Label::kNear);
4189 4314
4190 __ mov(result, factory()->false_value()); 4315 __ mov(result, factory()->false_value());
4191 __ jmp(&done); 4316 __ jmp(&done, Label::kNear);
4192 4317
4193 __ bind(&true_label); 4318 __ bind(&true_label);
4194 __ mov(result, factory()->true_value()); 4319 __ mov(result, factory()->true_value());
4195 4320
4196 __ bind(&done); 4321 __ bind(&done);
4197 } 4322 }
4198 4323
4199 4324
4200 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 4325 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
4201 Register temp = ToRegister(instr->TempAt(0)); 4326 Register temp = ToRegister(instr->TempAt(0));
4202 int true_block = chunk_->LookupDestination(instr->true_block_id()); 4327 int true_block = chunk_->LookupDestination(instr->true_block_id());
4203 int false_block = chunk_->LookupDestination(instr->false_block_id()); 4328 int false_block = chunk_->LookupDestination(instr->false_block_id());
4204 4329
4205 EmitIsConstructCall(temp); 4330 EmitIsConstructCall(temp);
4206 EmitBranch(true_block, false_block, equal); 4331 EmitBranch(true_block, false_block, equal);
4207 } 4332 }
4208 4333
4209 4334
4210 void LCodeGen::EmitIsConstructCall(Register temp) { 4335 void LCodeGen::EmitIsConstructCall(Register temp) {
4211 // Get the frame pointer for the calling frame. 4336 // Get the frame pointer for the calling frame.
4212 __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 4337 __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
4213 4338
4214 // Skip the arguments adaptor frame if it exists. 4339 // Skip the arguments adaptor frame if it exists.
4215 NearLabel check_frame_marker; 4340 Label check_frame_marker;
4216 __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), 4341 __ cmp(Operand(temp, StandardFrameConstants::kContextOffset),
4217 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 4342 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
4218 __ j(not_equal, &check_frame_marker); 4343 __ j(not_equal, &check_frame_marker, Label::kNear);
4219 __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); 4344 __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset));
4220 4345
4221 // Check the marker in the calling frame. 4346 // Check the marker in the calling frame.
4222 __ bind(&check_frame_marker); 4347 __ bind(&check_frame_marker);
4223 __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), 4348 __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset),
4224 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); 4349 Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
4225 } 4350 }
4226 4351
4227 4352
4228 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { 4353 void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
(...skipping 28 matching lines...) Expand all
4257 pointers, 4382 pointers,
4258 env->deoptimization_index()); 4383 env->deoptimization_index());
4259 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 4384 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4260 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); 4385 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
4261 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator); 4386 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, safepoint_generator);
4262 } 4387 }
4263 4388
4264 4389
4265 void LCodeGen::DoStackCheck(LStackCheck* instr) { 4390 void LCodeGen::DoStackCheck(LStackCheck* instr) {
4266 // Perform stack overflow check. 4391 // Perform stack overflow check.
4267 NearLabel done; 4392 Label done;
4268 ExternalReference stack_limit = 4393 ExternalReference stack_limit =
4269 ExternalReference::address_of_stack_limit(isolate()); 4394 ExternalReference::address_of_stack_limit(isolate());
4270 __ cmp(esp, Operand::StaticVariable(stack_limit)); 4395 __ cmp(esp, Operand::StaticVariable(stack_limit));
4271 __ j(above_equal, &done); 4396 __ j(above_equal, &done, Label::kNear);
4272 4397
4273 StackCheckStub stub; 4398 StackCheckStub stub;
4274 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT); 4399 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, RESTORE_CONTEXT);
4275 __ bind(&done); 4400 __ bind(&done);
4276 } 4401 }
4277 4402
4278 4403
4279 void LCodeGen::DoOsrEntry(LOsrEntry* instr) { 4404 void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
4280 // This is a pseudo-instruction that ensures that the environment here is 4405 // This is a pseudo-instruction that ensures that the environment here is
4281 // properly registered for deoptimization and records the assembler's PC 4406 // properly registered for deoptimization and records the assembler's PC
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
4320 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 4445 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4321 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); 4446 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator);
4322 } 4447 }
4323 4448
4324 4449
4325 #undef __ 4450 #undef __
4326 4451
4327 } } // namespace v8::internal 4452 } } // namespace v8::internal
4328 4453
4329 #endif // V8_TARGET_ARCH_IA32 4454 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698