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

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 7001025: Remove support for branch hints from the IA32 and X64 assembler. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
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/builtins-ia32.cc ('k') | src/ia32/full-codegen-ia32.cc » ('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 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after
1011 combined = right; 1011 combined = right;
1012 break; 1012 break;
1013 1013
1014 default: 1014 default:
1015 break; 1015 break;
1016 } 1016 }
1017 1017
1018 // 3. Perform the smi check of the operands. 1018 // 3. Perform the smi check of the operands.
1019 STATIC_ASSERT(kSmiTag == 0); // Adjust zero check if not the case. 1019 STATIC_ASSERT(kSmiTag == 0); // Adjust zero check if not the case.
1020 __ test(combined, Immediate(kSmiTagMask)); 1020 __ test(combined, Immediate(kSmiTagMask));
1021 __ j(not_zero, &not_smis, not_taken); 1021 __ j(not_zero, &not_smis);
1022 1022
1023 // 4. Operands are both smis, perform the operation leaving the result in 1023 // 4. Operands are both smis, perform the operation leaving the result in
1024 // eax and check the result if necessary. 1024 // eax and check the result if necessary.
1025 Comment perform_smi(masm, "-- Perform smi operation"); 1025 Comment perform_smi(masm, "-- Perform smi operation");
1026 Label use_fp_on_smis; 1026 Label use_fp_on_smis;
1027 switch (op_) { 1027 switch (op_) {
1028 case Token::BIT_OR: 1028 case Token::BIT_OR:
1029 // Nothing to do. 1029 // Nothing to do.
1030 break; 1030 break;
1031 1031
1032 case Token::BIT_XOR: 1032 case Token::BIT_XOR:
1033 ASSERT(right.is(eax)); 1033 ASSERT(right.is(eax));
1034 __ xor_(right, Operand(left)); // Bitwise xor is commutative. 1034 __ xor_(right, Operand(left)); // Bitwise xor is commutative.
1035 break; 1035 break;
1036 1036
1037 case Token::BIT_AND: 1037 case Token::BIT_AND:
1038 ASSERT(right.is(eax)); 1038 ASSERT(right.is(eax));
1039 __ and_(right, Operand(left)); // Bitwise and is commutative. 1039 __ and_(right, Operand(left)); // Bitwise and is commutative.
1040 break; 1040 break;
1041 1041
1042 case Token::SHL: 1042 case Token::SHL:
1043 // Remove tags from operands (but keep sign). 1043 // Remove tags from operands (but keep sign).
1044 __ SmiUntag(left); 1044 __ SmiUntag(left);
1045 __ SmiUntag(ecx); 1045 __ SmiUntag(ecx);
1046 // Perform the operation. 1046 // Perform the operation.
1047 __ shl_cl(left); 1047 __ shl_cl(left);
1048 // Check that the *signed* result fits in a smi. 1048 // Check that the *signed* result fits in a smi.
1049 __ cmp(left, 0xc0000000); 1049 __ cmp(left, 0xc0000000);
1050 __ j(sign, &use_fp_on_smis, not_taken); 1050 __ j(sign, &use_fp_on_smis);
1051 // Tag the result and store it in register eax. 1051 // Tag the result and store it in register eax.
1052 __ SmiTag(left); 1052 __ SmiTag(left);
1053 __ mov(eax, left); 1053 __ mov(eax, left);
1054 break; 1054 break;
1055 1055
1056 case Token::SAR: 1056 case Token::SAR:
1057 // Remove tags from operands (but keep sign). 1057 // Remove tags from operands (but keep sign).
1058 __ SmiUntag(left); 1058 __ SmiUntag(left);
1059 __ SmiUntag(ecx); 1059 __ SmiUntag(ecx);
1060 // Perform the operation. 1060 // Perform the operation.
1061 __ sar_cl(left); 1061 __ sar_cl(left);
1062 // Tag the result and store it in register eax. 1062 // Tag the result and store it in register eax.
1063 __ SmiTag(left); 1063 __ SmiTag(left);
1064 __ mov(eax, left); 1064 __ mov(eax, left);
1065 break; 1065 break;
1066 1066
1067 case Token::SHR: 1067 case Token::SHR:
1068 // Remove tags from operands (but keep sign). 1068 // Remove tags from operands (but keep sign).
1069 __ SmiUntag(left); 1069 __ SmiUntag(left);
1070 __ SmiUntag(ecx); 1070 __ SmiUntag(ecx);
1071 // Perform the operation. 1071 // Perform the operation.
1072 __ shr_cl(left); 1072 __ shr_cl(left);
1073 // Check that the *unsigned* result fits in a smi. 1073 // Check that the *unsigned* result fits in a smi.
1074 // Neither of the two high-order bits can be set: 1074 // Neither of the two high-order bits can be set:
1075 // - 0x80000000: high bit would be lost when smi tagging. 1075 // - 0x80000000: high bit would be lost when smi tagging.
1076 // - 0x40000000: this number would convert to negative when 1076 // - 0x40000000: this number would convert to negative when
1077 // Smi tagging these two cases can only happen with shifts 1077 // Smi tagging these two cases can only happen with shifts
1078 // by 0 or 1 when handed a valid smi. 1078 // by 0 or 1 when handed a valid smi.
1079 __ test(left, Immediate(0xc0000000)); 1079 __ test(left, Immediate(0xc0000000));
1080 __ j(not_zero, slow, not_taken); 1080 __ j(not_zero, slow);
1081 // Tag the result and store it in register eax. 1081 // Tag the result and store it in register eax.
1082 __ SmiTag(left); 1082 __ SmiTag(left);
1083 __ mov(eax, left); 1083 __ mov(eax, left);
1084 break; 1084 break;
1085 1085
1086 case Token::ADD: 1086 case Token::ADD:
1087 ASSERT(right.is(eax)); 1087 ASSERT(right.is(eax));
1088 __ add(right, Operand(left)); // Addition is commutative. 1088 __ add(right, Operand(left)); // Addition is commutative.
1089 __ j(overflow, &use_fp_on_smis, not_taken); 1089 __ j(overflow, &use_fp_on_smis);
1090 break; 1090 break;
1091 1091
1092 case Token::SUB: 1092 case Token::SUB:
1093 __ sub(left, Operand(right)); 1093 __ sub(left, Operand(right));
1094 __ j(overflow, &use_fp_on_smis, not_taken); 1094 __ j(overflow, &use_fp_on_smis);
1095 __ mov(eax, left); 1095 __ mov(eax, left);
1096 break; 1096 break;
1097 1097
1098 case Token::MUL: 1098 case Token::MUL:
1099 // If the smi tag is 0 we can just leave the tag on one operand. 1099 // If the smi tag is 0 we can just leave the tag on one operand.
1100 STATIC_ASSERT(kSmiTag == 0); // Adjust code below if not the case. 1100 STATIC_ASSERT(kSmiTag == 0); // Adjust code below if not the case.
1101 // We can't revert the multiplication if the result is not a smi 1101 // We can't revert the multiplication if the result is not a smi
1102 // so save the right operand. 1102 // so save the right operand.
1103 __ mov(ebx, right); 1103 __ mov(ebx, right);
1104 // Remove tag from one of the operands (but keep sign). 1104 // Remove tag from one of the operands (but keep sign).
1105 __ SmiUntag(right); 1105 __ SmiUntag(right);
1106 // Do multiplication. 1106 // Do multiplication.
1107 __ imul(right, Operand(left)); // Multiplication is commutative. 1107 __ imul(right, Operand(left)); // Multiplication is commutative.
1108 __ j(overflow, &use_fp_on_smis, not_taken); 1108 __ j(overflow, &use_fp_on_smis);
1109 // Check for negative zero result. Use combined = left | right. 1109 // Check for negative zero result. Use combined = left | right.
1110 __ NegativeZeroTest(right, combined, &use_fp_on_smis); 1110 __ NegativeZeroTest(right, combined, &use_fp_on_smis);
1111 break; 1111 break;
1112 1112
1113 case Token::DIV: 1113 case Token::DIV:
1114 // We can't revert the division if the result is not a smi so 1114 // We can't revert the division if the result is not a smi so
1115 // save the left operand. 1115 // save the left operand.
1116 __ mov(edi, left); 1116 __ mov(edi, left);
1117 // Check for 0 divisor. 1117 // Check for 0 divisor.
1118 __ test(right, Operand(right)); 1118 __ test(right, Operand(right));
1119 __ j(zero, &use_fp_on_smis, not_taken); 1119 __ j(zero, &use_fp_on_smis);
1120 // Sign extend left into edx:eax. 1120 // Sign extend left into edx:eax.
1121 ASSERT(left.is(eax)); 1121 ASSERT(left.is(eax));
1122 __ cdq(); 1122 __ cdq();
1123 // Divide edx:eax by right. 1123 // Divide edx:eax by right.
1124 __ idiv(right); 1124 __ idiv(right);
1125 // Check for the corner case of dividing the most negative smi by 1125 // Check for the corner case of dividing the most negative smi by
1126 // -1. We cannot use the overflow flag, since it is not set by idiv 1126 // -1. We cannot use the overflow flag, since it is not set by idiv
1127 // instruction. 1127 // instruction.
1128 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 1128 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
1129 __ cmp(eax, 0x40000000); 1129 __ cmp(eax, 0x40000000);
1130 __ j(equal, &use_fp_on_smis); 1130 __ j(equal, &use_fp_on_smis);
1131 // Check for negative zero result. Use combined = left | right. 1131 // Check for negative zero result. Use combined = left | right.
1132 __ NegativeZeroTest(eax, combined, &use_fp_on_smis); 1132 __ NegativeZeroTest(eax, combined, &use_fp_on_smis);
1133 // Check that the remainder is zero. 1133 // Check that the remainder is zero.
1134 __ test(edx, Operand(edx)); 1134 __ test(edx, Operand(edx));
1135 __ j(not_zero, &use_fp_on_smis); 1135 __ j(not_zero, &use_fp_on_smis);
1136 // Tag the result and store it in register eax. 1136 // Tag the result and store it in register eax.
1137 __ SmiTag(eax); 1137 __ SmiTag(eax);
1138 break; 1138 break;
1139 1139
1140 case Token::MOD: 1140 case Token::MOD:
1141 // Check for 0 divisor. 1141 // Check for 0 divisor.
1142 __ test(right, Operand(right)); 1142 __ test(right, Operand(right));
1143 __ j(zero, &not_smis, not_taken); 1143 __ j(zero, &not_smis);
1144 1144
1145 // Sign extend left into edx:eax. 1145 // Sign extend left into edx:eax.
1146 ASSERT(left.is(eax)); 1146 ASSERT(left.is(eax));
1147 __ cdq(); 1147 __ cdq();
1148 // Divide edx:eax by right. 1148 // Divide edx:eax by right.
1149 __ idiv(right); 1149 __ idiv(right);
1150 // Check for negative zero result. Use combined = left | right. 1150 // Check for negative zero result. Use combined = left | right.
1151 __ NegativeZeroTest(edx, combined, slow); 1151 __ NegativeZeroTest(edx, combined, slow);
1152 // Move remainder to register eax. 1152 // Move remainder to register eax.
1153 __ mov(eax, edx); 1153 __ mov(eax, edx);
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
1534 __ mov(ebx, Operand(eax)); // ebx: result 1534 __ mov(ebx, Operand(eax)); // ebx: result
1535 Label skip_allocation; 1535 Label skip_allocation;
1536 switch (mode_) { 1536 switch (mode_) {
1537 case OVERWRITE_LEFT: 1537 case OVERWRITE_LEFT:
1538 case OVERWRITE_RIGHT: 1538 case OVERWRITE_RIGHT:
1539 // If the operand was an object, we skip the 1539 // If the operand was an object, we skip the
1540 // allocation of a heap number. 1540 // allocation of a heap number.
1541 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? 1541 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ?
1542 1 * kPointerSize : 2 * kPointerSize)); 1542 1 * kPointerSize : 2 * kPointerSize));
1543 __ test(eax, Immediate(kSmiTagMask)); 1543 __ test(eax, Immediate(kSmiTagMask));
1544 __ j(not_zero, &skip_allocation, not_taken, Label::kNear); 1544 __ j(not_zero, &skip_allocation, Label::kNear);
1545 // Fall through! 1545 // Fall through!
1546 case NO_OVERWRITE: 1546 case NO_OVERWRITE:
1547 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); 1547 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
1548 __ bind(&skip_allocation); 1548 __ bind(&skip_allocation);
1549 break; 1549 break;
1550 default: UNREACHABLE(); 1550 default: UNREACHABLE();
1551 } 1551 }
1552 // Store the result in the HeapNumber and return. 1552 // Store the result in the HeapNumber and return.
1553 if (CpuFeatures::IsSupported(SSE2)) { 1553 if (CpuFeatures::IsSupported(SSE2)) {
1554 CpuFeatures::Scope use_sse2(SSE2); 1554 CpuFeatures::Scope use_sse2(SSE2);
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1749 __ mov(ebx, Operand(eax)); // ebx: result 1749 __ mov(ebx, Operand(eax)); // ebx: result
1750 Label skip_allocation; 1750 Label skip_allocation;
1751 switch (mode_) { 1751 switch (mode_) {
1752 case OVERWRITE_LEFT: 1752 case OVERWRITE_LEFT:
1753 case OVERWRITE_RIGHT: 1753 case OVERWRITE_RIGHT:
1754 // If the operand was an object, we skip the 1754 // If the operand was an object, we skip the
1755 // allocation of a heap number. 1755 // allocation of a heap number.
1756 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? 1756 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ?
1757 1 * kPointerSize : 2 * kPointerSize)); 1757 1 * kPointerSize : 2 * kPointerSize));
1758 __ test(eax, Immediate(kSmiTagMask)); 1758 __ test(eax, Immediate(kSmiTagMask));
1759 __ j(not_zero, &skip_allocation, not_taken, Label::kNear); 1759 __ j(not_zero, &skip_allocation, Label::kNear);
1760 // Fall through! 1760 // Fall through!
1761 case NO_OVERWRITE: 1761 case NO_OVERWRITE:
1762 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); 1762 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
1763 __ bind(&skip_allocation); 1763 __ bind(&skip_allocation);
1764 break; 1764 break;
1765 default: UNREACHABLE(); 1765 default: UNREACHABLE();
1766 } 1766 }
1767 // Store the result in the HeapNumber and return. 1767 // Store the result in the HeapNumber and return.
1768 if (CpuFeatures::IsSupported(SSE2)) { 1768 if (CpuFeatures::IsSupported(SSE2)) {
1769 CpuFeatures::Scope use_sse2(SSE2); 1769 CpuFeatures::Scope use_sse2(SSE2);
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
1949 __ mov(ebx, Operand(eax)); // ebx: result 1949 __ mov(ebx, Operand(eax)); // ebx: result
1950 Label skip_allocation; 1950 Label skip_allocation;
1951 switch (mode_) { 1951 switch (mode_) {
1952 case OVERWRITE_LEFT: 1952 case OVERWRITE_LEFT:
1953 case OVERWRITE_RIGHT: 1953 case OVERWRITE_RIGHT:
1954 // If the operand was an object, we skip the 1954 // If the operand was an object, we skip the
1955 // allocation of a heap number. 1955 // allocation of a heap number.
1956 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? 1956 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ?
1957 1 * kPointerSize : 2 * kPointerSize)); 1957 1 * kPointerSize : 2 * kPointerSize));
1958 __ test(eax, Immediate(kSmiTagMask)); 1958 __ test(eax, Immediate(kSmiTagMask));
1959 __ j(not_zero, &skip_allocation, not_taken, Label::kNear); 1959 __ j(not_zero, &skip_allocation, Label::kNear);
1960 // Fall through! 1960 // Fall through!
1961 case NO_OVERWRITE: 1961 case NO_OVERWRITE:
1962 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); 1962 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
1963 __ bind(&skip_allocation); 1963 __ bind(&skip_allocation);
1964 break; 1964 break;
1965 default: UNREACHABLE(); 1965 default: UNREACHABLE();
1966 } 1966 }
1967 // Store the result in the HeapNumber and return. 1967 // Store the result in the HeapNumber and return.
1968 if (CpuFeatures::IsSupported(SSE2)) { 1968 if (CpuFeatures::IsSupported(SSE2)) {
1969 CpuFeatures::Scope use_sse2(SSE2); 1969 CpuFeatures::Scope use_sse2(SSE2);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
2067 void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation( 2067 void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation(
2068 MacroAssembler* masm, 2068 MacroAssembler* masm,
2069 Label* alloc_failure) { 2069 Label* alloc_failure) {
2070 Label skip_allocation; 2070 Label skip_allocation;
2071 OverwriteMode mode = mode_; 2071 OverwriteMode mode = mode_;
2072 switch (mode) { 2072 switch (mode) {
2073 case OVERWRITE_LEFT: { 2073 case OVERWRITE_LEFT: {
2074 // If the argument in edx is already an object, we skip the 2074 // If the argument in edx is already an object, we skip the
2075 // allocation of a heap number. 2075 // allocation of a heap number.
2076 __ test(edx, Immediate(kSmiTagMask)); 2076 __ test(edx, Immediate(kSmiTagMask));
2077 __ j(not_zero, &skip_allocation, not_taken); 2077 __ j(not_zero, &skip_allocation);
2078 // Allocate a heap number for the result. Keep eax and edx intact 2078 // Allocate a heap number for the result. Keep eax and edx intact
2079 // for the possible runtime call. 2079 // for the possible runtime call.
2080 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure); 2080 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure);
2081 // Now edx can be overwritten losing one of the arguments as we are 2081 // Now edx can be overwritten losing one of the arguments as we are
2082 // now done and will not need it any more. 2082 // now done and will not need it any more.
2083 __ mov(edx, Operand(ebx)); 2083 __ mov(edx, Operand(ebx));
2084 __ bind(&skip_allocation); 2084 __ bind(&skip_allocation);
2085 // Use object in edx as a result holder 2085 // Use object in edx as a result holder
2086 __ mov(eax, Operand(edx)); 2086 __ mov(eax, Operand(edx));
2087 break; 2087 break;
2088 } 2088 }
2089 case OVERWRITE_RIGHT: 2089 case OVERWRITE_RIGHT:
2090 // If the argument in eax is already an object, we skip the 2090 // If the argument in eax is already an object, we skip the
2091 // allocation of a heap number. 2091 // allocation of a heap number.
2092 __ test(eax, Immediate(kSmiTagMask)); 2092 __ test(eax, Immediate(kSmiTagMask));
2093 __ j(not_zero, &skip_allocation, not_taken); 2093 __ j(not_zero, &skip_allocation);
2094 // Fall through! 2094 // Fall through!
2095 case NO_OVERWRITE: 2095 case NO_OVERWRITE:
2096 // Allocate a heap number for the result. Keep eax and edx intact 2096 // Allocate a heap number for the result. Keep eax and edx intact
2097 // for the possible runtime call. 2097 // for the possible runtime call.
2098 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure); 2098 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure);
2099 // Now eax can be overwritten losing one of the arguments as we are 2099 // Now eax can be overwritten losing one of the arguments as we are
2100 // now done and will not need it any more. 2100 // now done and will not need it any more.
2101 __ mov(eax, ebx); 2101 __ mov(eax, ebx);
2102 __ bind(&skip_allocation); 2102 __ bind(&skip_allocation);
2103 break; 2103 break;
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
2326 // return NaN for infinities and NaN. They can share all code except 2326 // return NaN for infinities and NaN. They can share all code except
2327 // the actual fsin/fcos operation. 2327 // the actual fsin/fcos operation.
2328 Label in_range, done; 2328 Label in_range, done;
2329 // If argument is outside the range -2^63..2^63, fsin/cos doesn't 2329 // If argument is outside the range -2^63..2^63, fsin/cos doesn't
2330 // work. We must reduce it to the appropriate range. 2330 // work. We must reduce it to the appropriate range.
2331 __ mov(edi, edx); 2331 __ mov(edi, edx);
2332 __ and_(Operand(edi), Immediate(0x7ff00000)); // Exponent only. 2332 __ and_(Operand(edi), Immediate(0x7ff00000)); // Exponent only.
2333 int supported_exponent_limit = 2333 int supported_exponent_limit =
2334 (63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift; 2334 (63 + HeapNumber::kExponentBias) << HeapNumber::kExponentShift;
2335 __ cmp(Operand(edi), Immediate(supported_exponent_limit)); 2335 __ cmp(Operand(edi), Immediate(supported_exponent_limit));
2336 __ j(below, &in_range, taken, Label::kNear); 2336 __ j(below, &in_range, Label::kNear);
2337 // Check for infinity and NaN. Both return NaN for sin. 2337 // Check for infinity and NaN. Both return NaN for sin.
2338 __ cmp(Operand(edi), Immediate(0x7ff00000)); 2338 __ cmp(Operand(edi), Immediate(0x7ff00000));
2339 Label non_nan_result; 2339 Label non_nan_result;
2340 __ j(not_equal, &non_nan_result, taken, Label::kNear); 2340 __ j(not_equal, &non_nan_result, Label::kNear);
2341 // Input is +/-Infinity or NaN. Result is NaN. 2341 // Input is +/-Infinity or NaN. Result is NaN.
2342 __ fstp(0); 2342 __ fstp(0);
2343 // NaN is represented by 0x7ff8000000000000. 2343 // NaN is represented by 0x7ff8000000000000.
2344 __ push(Immediate(0x7ff80000)); 2344 __ push(Immediate(0x7ff80000));
2345 __ push(Immediate(0)); 2345 __ push(Immediate(0));
2346 __ fld_d(Operand(esp, 0)); 2346 __ fld_d(Operand(esp, 0));
2347 __ add(Operand(esp), Immediate(2 * kPointerSize)); 2347 __ add(Operand(esp), Immediate(2 * kPointerSize));
2348 __ jmp(&done, Label::kNear); 2348 __ jmp(&done, Label::kNear);
2349 2349
2350 __ bind(&non_nan_result); 2350 __ bind(&non_nan_result);
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
2546 Label* not_int32) { 2546 Label* not_int32) {
2547 return; 2547 return;
2548 } 2548 }
2549 2549
2550 2550
2551 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm, 2551 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
2552 Register number) { 2552 Register number) {
2553 Label load_smi, done; 2553 Label load_smi, done;
2554 2554
2555 __ test(number, Immediate(kSmiTagMask)); 2555 __ test(number, Immediate(kSmiTagMask));
2556 __ j(zero, &load_smi, not_taken, Label::kNear); 2556 __ j(zero, &load_smi, Label::kNear);
2557 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset)); 2557 __ fld_d(FieldOperand(number, HeapNumber::kValueOffset));
2558 __ jmp(&done, Label::kNear); 2558 __ jmp(&done, Label::kNear);
2559 2559
2560 __ bind(&load_smi); 2560 __ bind(&load_smi);
2561 __ SmiUntag(number); 2561 __ SmiUntag(number);
2562 __ push(number); 2562 __ push(number);
2563 __ fild_s(Operand(esp, 0)); 2563 __ fild_s(Operand(esp, 0));
2564 __ pop(number); 2564 __ pop(number);
2565 2565
2566 __ bind(&done); 2566 __ bind(&done);
2567 } 2567 }
2568 2568
2569 2569
2570 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm) { 2570 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm) {
2571 Label load_smi_edx, load_eax, load_smi_eax, done; 2571 Label load_smi_edx, load_eax, load_smi_eax, done;
2572 // Load operand in edx into xmm0. 2572 // Load operand in edx into xmm0.
2573 __ test(edx, Immediate(kSmiTagMask)); 2573 __ test(edx, Immediate(kSmiTagMask));
2574 // Argument in edx is a smi. 2574 // Argument in edx is a smi.
2575 __ j(zero, &load_smi_edx, not_taken, Label::kNear); 2575 __ j(zero, &load_smi_edx, Label::kNear);
2576 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); 2576 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
2577 2577
2578 __ bind(&load_eax); 2578 __ bind(&load_eax);
2579 // Load operand in eax into xmm1. 2579 // Load operand in eax into xmm1.
2580 __ test(eax, Immediate(kSmiTagMask)); 2580 __ test(eax, Immediate(kSmiTagMask));
2581 // Argument in eax is a smi. 2581 // Argument in eax is a smi.
2582 __ j(zero, &load_smi_eax, not_taken, Label::kNear); 2582 __ j(zero, &load_smi_eax, Label::kNear);
2583 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); 2583 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
2584 __ jmp(&done, Label::kNear); 2584 __ jmp(&done, Label::kNear);
2585 2585
2586 __ bind(&load_smi_edx); 2586 __ bind(&load_smi_edx);
2587 __ SmiUntag(edx); // Untag smi before converting to float. 2587 __ SmiUntag(edx); // Untag smi before converting to float.
2588 __ cvtsi2sd(xmm0, Operand(edx)); 2588 __ cvtsi2sd(xmm0, Operand(edx));
2589 __ SmiTag(edx); // Retag smi for heap number overwriting test. 2589 __ SmiTag(edx); // Retag smi for heap number overwriting test.
2590 __ jmp(&load_eax); 2590 __ jmp(&load_eax);
2591 2591
2592 __ bind(&load_smi_eax); 2592 __ bind(&load_smi_eax);
2593 __ SmiUntag(eax); // Untag smi before converting to float. 2593 __ SmiUntag(eax); // Untag smi before converting to float.
2594 __ cvtsi2sd(xmm1, Operand(eax)); 2594 __ cvtsi2sd(xmm1, Operand(eax));
2595 __ SmiTag(eax); // Retag smi for heap number overwriting test. 2595 __ SmiTag(eax); // Retag smi for heap number overwriting test.
2596 2596
2597 __ bind(&done); 2597 __ bind(&done);
2598 } 2598 }
2599 2599
2600 2600
2601 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm, 2601 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm,
2602 Label* not_numbers) { 2602 Label* not_numbers) {
2603 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done; 2603 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done;
2604 // Load operand in edx into xmm0, or branch to not_numbers. 2604 // Load operand in edx into xmm0, or branch to not_numbers.
2605 __ test(edx, Immediate(kSmiTagMask)); 2605 __ test(edx, Immediate(kSmiTagMask));
2606 // Argument in edx is a smi. 2606 // Argument in edx is a smi.
2607 __ j(zero, &load_smi_edx, not_taken, Label::kNear); 2607 __ j(zero, &load_smi_edx, Label::kNear);
2608 Factory* factory = masm->isolate()->factory(); 2608 Factory* factory = masm->isolate()->factory();
2609 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), factory->heap_number_map()); 2609 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), factory->heap_number_map());
2610 __ j(not_equal, not_numbers); // Argument in edx is not a number. 2610 __ j(not_equal, not_numbers); // Argument in edx is not a number.
2611 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); 2611 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
2612 __ bind(&load_eax); 2612 __ bind(&load_eax);
2613 // Load operand in eax into xmm1, or branch to not_numbers. 2613 // Load operand in eax into xmm1, or branch to not_numbers.
2614 __ test(eax, Immediate(kSmiTagMask)); 2614 __ test(eax, Immediate(kSmiTagMask));
2615 // Argument in eax is a smi. 2615 // Argument in eax is a smi.
2616 __ j(zero, &load_smi_eax, not_taken, Label::kNear); 2616 __ j(zero, &load_smi_eax, Label::kNear);
2617 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map()); 2617 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), factory->heap_number_map());
2618 __ j(equal, &load_float_eax, Label::kNear); 2618 __ j(equal, &load_float_eax, Label::kNear);
2619 __ jmp(not_numbers); // Argument in eax is not a number. 2619 __ jmp(not_numbers); // Argument in eax is not a number.
2620 __ bind(&load_smi_edx); 2620 __ bind(&load_smi_edx);
2621 __ SmiUntag(edx); // Untag smi before converting to float. 2621 __ SmiUntag(edx); // Untag smi before converting to float.
2622 __ cvtsi2sd(xmm0, Operand(edx)); 2622 __ cvtsi2sd(xmm0, Operand(edx));
2623 __ SmiTag(edx); // Retag smi for heap number overwriting test. 2623 __ SmiTag(edx); // Retag smi for heap number overwriting test.
2624 __ jmp(&load_eax); 2624 __ jmp(&load_eax);
2625 __ bind(&load_smi_eax); 2625 __ bind(&load_smi_eax);
2626 __ SmiUntag(eax); // Untag smi before converting to float. 2626 __ SmiUntag(eax); // Untag smi before converting to float.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2667 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, 2667 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
2668 Register scratch, 2668 Register scratch,
2669 ArgLocation arg_location) { 2669 ArgLocation arg_location) {
2670 Label load_smi_1, load_smi_2, done_load_1, done; 2670 Label load_smi_1, load_smi_2, done_load_1, done;
2671 if (arg_location == ARGS_IN_REGISTERS) { 2671 if (arg_location == ARGS_IN_REGISTERS) {
2672 __ mov(scratch, edx); 2672 __ mov(scratch, edx);
2673 } else { 2673 } else {
2674 __ mov(scratch, Operand(esp, 2 * kPointerSize)); 2674 __ mov(scratch, Operand(esp, 2 * kPointerSize));
2675 } 2675 }
2676 __ test(scratch, Immediate(kSmiTagMask)); 2676 __ test(scratch, Immediate(kSmiTagMask));
2677 __ j(zero, &load_smi_1, not_taken, Label::kNear); 2677 __ j(zero, &load_smi_1, Label::kNear);
2678 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); 2678 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset));
2679 __ bind(&done_load_1); 2679 __ bind(&done_load_1);
2680 2680
2681 if (arg_location == ARGS_IN_REGISTERS) { 2681 if (arg_location == ARGS_IN_REGISTERS) {
2682 __ mov(scratch, eax); 2682 __ mov(scratch, eax);
2683 } else { 2683 } else {
2684 __ mov(scratch, Operand(esp, 1 * kPointerSize)); 2684 __ mov(scratch, Operand(esp, 1 * kPointerSize));
2685 } 2685 }
2686 __ test(scratch, Immediate(kSmiTagMask)); 2686 __ test(scratch, Immediate(kSmiTagMask));
2687 __ j(zero, &load_smi_2, not_taken, Label::kNear); 2687 __ j(zero, &load_smi_2, Label::kNear);
2688 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset)); 2688 __ fld_d(FieldOperand(scratch, HeapNumber::kValueOffset));
2689 __ jmp(&done, Label::kNear); 2689 __ jmp(&done, Label::kNear);
2690 2690
2691 __ bind(&load_smi_1); 2691 __ bind(&load_smi_1);
2692 __ SmiUntag(scratch); 2692 __ SmiUntag(scratch);
2693 __ push(scratch); 2693 __ push(scratch);
2694 __ fild_s(Operand(esp, 0)); 2694 __ fild_s(Operand(esp, 0));
2695 __ pop(scratch); 2695 __ pop(scratch);
2696 __ jmp(&done_load_1); 2696 __ jmp(&done_load_1);
2697 2697
(...skipping 25 matching lines...) Expand all
2723 } 2723 }
2724 2724
2725 2725
2726 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm, 2726 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm,
2727 Label* non_float, 2727 Label* non_float,
2728 Register scratch) { 2728 Register scratch) {
2729 Label test_other, done; 2729 Label test_other, done;
2730 // Test if both operands are floats or smi -> scratch=k_is_float; 2730 // Test if both operands are floats or smi -> scratch=k_is_float;
2731 // Otherwise scratch = k_not_float. 2731 // Otherwise scratch = k_not_float.
2732 __ test(edx, Immediate(kSmiTagMask)); 2732 __ test(edx, Immediate(kSmiTagMask));
2733 __ j(zero, &test_other, not_taken, Label::kNear); // argument in edx is OK 2733 __ j(zero, &test_other, Label::kNear); // argument in edx is OK
2734 __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset)); 2734 __ mov(scratch, FieldOperand(edx, HeapObject::kMapOffset));
2735 Factory* factory = masm->isolate()->factory(); 2735 Factory* factory = masm->isolate()->factory();
2736 __ cmp(scratch, factory->heap_number_map()); 2736 __ cmp(scratch, factory->heap_number_map());
2737 __ j(not_equal, non_float); // argument in edx is not a number -> NaN 2737 __ j(not_equal, non_float); // argument in edx is not a number -> NaN
2738 2738
2739 __ bind(&test_other); 2739 __ bind(&test_other);
2740 __ test(eax, Immediate(kSmiTagMask)); 2740 __ test(eax, Immediate(kSmiTagMask));
2741 __ j(zero, &done, Label::kNear); // argument in eax is OK 2741 __ j(zero, &done, Label::kNear); // argument in eax is OK
2742 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); 2742 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset));
2743 __ cmp(scratch, factory->heap_number_map()); 2743 __ cmp(scratch, factory->heap_number_map());
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
2916 // The key is in edx and the parameter count is in eax. 2916 // The key is in edx and the parameter count is in eax.
2917 2917
2918 // The displacement is used for skipping the frame pointer on the 2918 // The displacement is used for skipping the frame pointer on the
2919 // stack. It is the offset of the last parameter (if any) relative 2919 // stack. It is the offset of the last parameter (if any) relative
2920 // to the frame pointer. 2920 // to the frame pointer.
2921 static const int kDisplacement = 1 * kPointerSize; 2921 static const int kDisplacement = 1 * kPointerSize;
2922 2922
2923 // Check that the key is a smi. 2923 // Check that the key is a smi.
2924 Label slow; 2924 Label slow;
2925 __ test(edx, Immediate(kSmiTagMask)); 2925 __ test(edx, Immediate(kSmiTagMask));
2926 __ j(not_zero, &slow, not_taken); 2926 __ j(not_zero, &slow);
2927 2927
2928 // Check if the calling frame is an arguments adaptor frame. 2928 // Check if the calling frame is an arguments adaptor frame.
2929 Label adaptor; 2929 Label adaptor;
2930 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); 2930 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
2931 __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset)); 2931 __ mov(ecx, Operand(ebx, StandardFrameConstants::kContextOffset));
2932 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2932 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2933 __ j(equal, &adaptor, Label::kNear); 2933 __ j(equal, &adaptor, Label::kNear);
2934 2934
2935 // Check index against formal parameters count limit passed in 2935 // Check index against formal parameters count limit passed in
2936 // through register eax. Use unsigned comparison to get negative 2936 // through register eax. Use unsigned comparison to get negative
2937 // check for free. 2937 // check for free.
2938 __ cmp(edx, Operand(eax)); 2938 __ cmp(edx, Operand(eax));
2939 __ j(above_equal, &slow, not_taken); 2939 __ j(above_equal, &slow);
2940 2940
2941 // Read the argument from the stack and return it. 2941 // Read the argument from the stack and return it.
2942 STATIC_ASSERT(kSmiTagSize == 1); 2942 STATIC_ASSERT(kSmiTagSize == 1);
2943 STATIC_ASSERT(kSmiTag == 0); // Shifting code depends on these. 2943 STATIC_ASSERT(kSmiTag == 0); // Shifting code depends on these.
2944 __ lea(ebx, Operand(ebp, eax, times_2, 0)); 2944 __ lea(ebx, Operand(ebp, eax, times_2, 0));
2945 __ neg(edx); 2945 __ neg(edx);
2946 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement)); 2946 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement));
2947 __ ret(0); 2947 __ ret(0);
2948 2948
2949 // Arguments adaptor case: Check index against actual arguments 2949 // Arguments adaptor case: Check index against actual arguments
2950 // limit found in the arguments adaptor frame. Use unsigned 2950 // limit found in the arguments adaptor frame. Use unsigned
2951 // comparison to get negative check for free. 2951 // comparison to get negative check for free.
2952 __ bind(&adaptor); 2952 __ bind(&adaptor);
2953 __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2953 __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset));
2954 __ cmp(edx, Operand(ecx)); 2954 __ cmp(edx, Operand(ecx));
2955 __ j(above_equal, &slow, not_taken); 2955 __ j(above_equal, &slow);
2956 2956
2957 // Read the argument from the stack and return it. 2957 // Read the argument from the stack and return it.
2958 STATIC_ASSERT(kSmiTagSize == 1); 2958 STATIC_ASSERT(kSmiTagSize == 1);
2959 STATIC_ASSERT(kSmiTag == 0); // Shifting code depends on these. 2959 STATIC_ASSERT(kSmiTag == 0); // Shifting code depends on these.
2960 __ lea(ebx, Operand(ebx, ecx, times_2, 0)); 2960 __ lea(ebx, Operand(ebx, ecx, times_2, 0));
2961 __ neg(edx); 2961 __ neg(edx);
2962 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement)); 2962 __ mov(eax, Operand(ebx, edx, times_2, kDisplacement));
2963 __ ret(0); 2963 __ ret(0);
2964 2964
2965 // Slow-case: Handle non-smi or out-of-bounds access to arguments 2965 // Slow-case: Handle non-smi or out-of-bounds access to arguments
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
3108 Label runtime, invoke_regexp; 3108 Label runtime, invoke_regexp;
3109 3109
3110 // Ensure that a RegExp stack is allocated. 3110 // Ensure that a RegExp stack is allocated.
3111 ExternalReference address_of_regexp_stack_memory_address = 3111 ExternalReference address_of_regexp_stack_memory_address =
3112 ExternalReference::address_of_regexp_stack_memory_address( 3112 ExternalReference::address_of_regexp_stack_memory_address(
3113 masm->isolate()); 3113 masm->isolate());
3114 ExternalReference address_of_regexp_stack_memory_size = 3114 ExternalReference address_of_regexp_stack_memory_size =
3115 ExternalReference::address_of_regexp_stack_memory_size(masm->isolate()); 3115 ExternalReference::address_of_regexp_stack_memory_size(masm->isolate());
3116 __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size)); 3116 __ mov(ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size));
3117 __ test(ebx, Operand(ebx)); 3117 __ test(ebx, Operand(ebx));
3118 __ j(zero, &runtime, not_taken); 3118 __ j(zero, &runtime);
3119 3119
3120 // Check that the first argument is a JSRegExp object. 3120 // Check that the first argument is a JSRegExp object.
3121 __ mov(eax, Operand(esp, kJSRegExpOffset)); 3121 __ mov(eax, Operand(esp, kJSRegExpOffset));
3122 STATIC_ASSERT(kSmiTag == 0); 3122 STATIC_ASSERT(kSmiTag == 0);
3123 __ test(eax, Immediate(kSmiTagMask)); 3123 __ test(eax, Immediate(kSmiTagMask));
3124 __ j(zero, &runtime); 3124 __ j(zero, &runtime);
3125 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx); 3125 __ CmpObjectType(eax, JS_REGEXP_TYPE, ecx);
3126 __ j(not_equal, &runtime); 3126 __ j(not_equal, &runtime);
3127 // Check that the RegExp has been compiled (data contains a fixed array). 3127 // Check that the RegExp has been compiled (data contains a fixed array).
3128 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset)); 3128 __ mov(ecx, FieldOperand(eax, JSRegExp::kDataOffset));
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
3329 // Locate the code entry and call it. 3329 // Locate the code entry and call it.
3330 __ add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag)); 3330 __ add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag));
3331 __ call(Operand(edx)); 3331 __ call(Operand(edx));
3332 3332
3333 // Drop arguments and come back to JS mode. 3333 // Drop arguments and come back to JS mode.
3334 __ LeaveApiExitFrame(); 3334 __ LeaveApiExitFrame();
3335 3335
3336 // Check the result. 3336 // Check the result.
3337 Label success; 3337 Label success;
3338 __ cmp(eax, NativeRegExpMacroAssembler::SUCCESS); 3338 __ cmp(eax, NativeRegExpMacroAssembler::SUCCESS);
3339 __ j(equal, &success, taken); 3339 __ j(equal, &success);
3340 Label failure; 3340 Label failure;
3341 __ cmp(eax, NativeRegExpMacroAssembler::FAILURE); 3341 __ cmp(eax, NativeRegExpMacroAssembler::FAILURE);
3342 __ j(equal, &failure, taken); 3342 __ j(equal, &failure);
3343 __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION); 3343 __ cmp(eax, NativeRegExpMacroAssembler::EXCEPTION);
3344 // If not exception it can only be retry. Handle that in the runtime system. 3344 // If not exception it can only be retry. Handle that in the runtime system.
3345 __ j(not_equal, &runtime); 3345 __ j(not_equal, &runtime);
3346 // Result must now be exception. If there is no pending exception already a 3346 // Result must now be exception. If there is no pending exception already a
3347 // stack overflow (on the backtrack stack) was detected in RegExp code but 3347 // stack overflow (on the backtrack stack) was detected in RegExp code but
3348 // haven't created the exception yet. Handle that in the runtime system. 3348 // haven't created the exception yet. Handle that in the runtime system.
3349 // TODO(592): Rerunning the RegExp to get the stack overflow exception. 3349 // TODO(592): Rerunning the RegExp to get the stack overflow exception.
3350 ExternalReference pending_exception(Isolate::k_pending_exception_address, 3350 ExternalReference pending_exception(Isolate::k_pending_exception_address,
3351 masm->isolate()); 3351 masm->isolate());
3352 __ mov(edx, 3352 __ mov(edx,
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
3651 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); 3651 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
3652 3652
3653 Label check_unequal_objects, done; 3653 Label check_unequal_objects, done;
3654 3654
3655 // Compare two smis if required. 3655 // Compare two smis if required.
3656 if (include_smi_compare_) { 3656 if (include_smi_compare_) {
3657 Label non_smi, smi_done; 3657 Label non_smi, smi_done;
3658 __ mov(ecx, Operand(edx)); 3658 __ mov(ecx, Operand(edx));
3659 __ or_(ecx, Operand(eax)); 3659 __ or_(ecx, Operand(eax));
3660 __ test(ecx, Immediate(kSmiTagMask)); 3660 __ test(ecx, Immediate(kSmiTagMask));
3661 __ j(not_zero, &non_smi, not_taken); 3661 __ j(not_zero, &non_smi);
3662 __ sub(edx, Operand(eax)); // Return on the result of the subtraction. 3662 __ sub(edx, Operand(eax)); // Return on the result of the subtraction.
3663 __ j(no_overflow, &smi_done); 3663 __ j(no_overflow, &smi_done);
3664 __ not_(edx); // Correct sign in case of overflow. edx is never 0 here. 3664 __ not_(edx); // Correct sign in case of overflow. edx is never 0 here.
3665 __ bind(&smi_done); 3665 __ bind(&smi_done);
3666 __ mov(eax, edx); 3666 __ mov(eax, edx);
3667 __ ret(0); 3667 __ ret(0);
3668 __ bind(&non_smi); 3668 __ bind(&non_smi);
3669 } else if (FLAG_debug_code) { 3669 } else if (FLAG_debug_code) {
3670 __ mov(ecx, Operand(edx)); 3670 __ mov(ecx, Operand(edx));
3671 __ or_(ecx, Operand(eax)); 3671 __ or_(ecx, Operand(eax));
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
3826 Label non_number_comparison; 3826 Label non_number_comparison;
3827 Label unordered; 3827 Label unordered;
3828 if (CpuFeatures::IsSupported(SSE2)) { 3828 if (CpuFeatures::IsSupported(SSE2)) {
3829 CpuFeatures::Scope use_sse2(SSE2); 3829 CpuFeatures::Scope use_sse2(SSE2);
3830 CpuFeatures::Scope use_cmov(CMOV); 3830 CpuFeatures::Scope use_cmov(CMOV);
3831 3831
3832 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison); 3832 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison);
3833 __ ucomisd(xmm0, xmm1); 3833 __ ucomisd(xmm0, xmm1);
3834 3834
3835 // Don't base result on EFLAGS when a NaN is involved. 3835 // Don't base result on EFLAGS when a NaN is involved.
3836 __ j(parity_even, &unordered, not_taken); 3836 __ j(parity_even, &unordered);
3837 // Return a result of -1, 0, or 1, based on EFLAGS. 3837 // Return a result of -1, 0, or 1, based on EFLAGS.
3838 __ mov(eax, 0); // equal 3838 __ mov(eax, 0); // equal
3839 __ mov(ecx, Immediate(Smi::FromInt(1))); 3839 __ mov(ecx, Immediate(Smi::FromInt(1)));
3840 __ cmov(above, eax, Operand(ecx)); 3840 __ cmov(above, eax, Operand(ecx));
3841 __ mov(ecx, Immediate(Smi::FromInt(-1))); 3841 __ mov(ecx, Immediate(Smi::FromInt(-1)));
3842 __ cmov(below, eax, Operand(ecx)); 3842 __ cmov(below, eax, Operand(ecx));
3843 __ ret(0); 3843 __ ret(0);
3844 } else { 3844 } else {
3845 FloatingPointHelper::CheckFloatOperands( 3845 FloatingPointHelper::CheckFloatOperands(
3846 masm, &non_number_comparison, ebx); 3846 masm, &non_number_comparison, ebx);
3847 FloatingPointHelper::LoadFloatOperand(masm, eax); 3847 FloatingPointHelper::LoadFloatOperand(masm, eax);
3848 FloatingPointHelper::LoadFloatOperand(masm, edx); 3848 FloatingPointHelper::LoadFloatOperand(masm, edx);
3849 __ FCmp(); 3849 __ FCmp();
3850 3850
3851 // Don't base result on EFLAGS when a NaN is involved. 3851 // Don't base result on EFLAGS when a NaN is involved.
3852 __ j(parity_even, &unordered, not_taken); 3852 __ j(parity_even, &unordered);
3853 3853
3854 Label below_label, above_label; 3854 Label below_label, above_label;
3855 // Return a result of -1, 0, or 1, based on EFLAGS. 3855 // Return a result of -1, 0, or 1, based on EFLAGS.
3856 __ j(below, &below_label, not_taken); 3856 __ j(below, &below_label);
3857 __ j(above, &above_label, not_taken); 3857 __ j(above, &above_label);
3858 3858
3859 __ Set(eax, Immediate(0)); 3859 __ Set(eax, Immediate(0));
3860 __ ret(0); 3860 __ ret(0);
3861 3861
3862 __ bind(&below_label); 3862 __ bind(&below_label);
3863 __ mov(eax, Immediate(Smi::FromInt(-1))); 3863 __ mov(eax, Immediate(Smi::FromInt(-1)));
3864 __ ret(0); 3864 __ ret(0);
3865 3865
3866 __ bind(&above_label); 3866 __ bind(&above_label);
3867 __ mov(eax, Immediate(Smi::FromInt(1))); 3867 __ mov(eax, Immediate(Smi::FromInt(1)));
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
4005 // If the receiver might be a value (string, number or boolean) check for this 4005 // If the receiver might be a value (string, number or boolean) check for this
4006 // and box it if it is. 4006 // and box it if it is.
4007 if (ReceiverMightBeValue()) { 4007 if (ReceiverMightBeValue()) {
4008 // Get the receiver from the stack. 4008 // Get the receiver from the stack.
4009 // +1 ~ return address 4009 // +1 ~ return address
4010 Label receiver_is_value, receiver_is_js_object; 4010 Label receiver_is_value, receiver_is_js_object;
4011 __ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize)); 4011 __ mov(eax, Operand(esp, (argc_ + 1) * kPointerSize));
4012 4012
4013 // Check if receiver is a smi (which is a number value). 4013 // Check if receiver is a smi (which is a number value).
4014 __ test(eax, Immediate(kSmiTagMask)); 4014 __ test(eax, Immediate(kSmiTagMask));
4015 __ j(zero, &receiver_is_value, not_taken); 4015 __ j(zero, &receiver_is_value);
4016 4016
4017 // Check if the receiver is a valid JS object. 4017 // Check if the receiver is a valid JS object.
4018 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, edi); 4018 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, edi);
4019 __ j(above_equal, &receiver_is_js_object); 4019 __ j(above_equal, &receiver_is_js_object);
4020 4020
4021 // Call the runtime to box the value. 4021 // Call the runtime to box the value.
4022 __ bind(&receiver_is_value); 4022 __ bind(&receiver_is_value);
4023 __ EnterInternalFrame(); 4023 __ EnterInternalFrame();
4024 __ push(eax); 4024 __ push(eax);
4025 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 4025 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
4026 __ LeaveInternalFrame(); 4026 __ LeaveInternalFrame();
4027 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), eax); 4027 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), eax);
4028 4028
4029 __ bind(&receiver_is_js_object); 4029 __ bind(&receiver_is_js_object);
4030 } 4030 }
4031 4031
4032 // Get the function to call from the stack. 4032 // Get the function to call from the stack.
4033 // +2 ~ receiver, return address 4033 // +2 ~ receiver, return address
4034 __ mov(edi, Operand(esp, (argc_ + 2) * kPointerSize)); 4034 __ mov(edi, Operand(esp, (argc_ + 2) * kPointerSize));
4035 4035
4036 // Check that the function really is a JavaScript function. 4036 // Check that the function really is a JavaScript function.
4037 __ test(edi, Immediate(kSmiTagMask)); 4037 __ test(edi, Immediate(kSmiTagMask));
4038 __ j(zero, &slow, not_taken); 4038 __ j(zero, &slow);
4039 // Goto slow case if we do not have a function. 4039 // Goto slow case if we do not have a function.
4040 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); 4040 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
4041 __ j(not_equal, &slow, not_taken); 4041 __ j(not_equal, &slow);
4042 4042
4043 // Fast-case: Just invoke the function. 4043 // Fast-case: Just invoke the function.
4044 ParameterCount actual(argc_); 4044 ParameterCount actual(argc_);
4045 __ InvokeFunction(edi, actual, JUMP_FUNCTION); 4045 __ InvokeFunction(edi, actual, JUMP_FUNCTION);
4046 4046
4047 // Slow-case: Non-function called. 4047 // Slow-case: Non-function called.
4048 __ bind(&slow); 4048 __ bind(&slow);
4049 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead 4049 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
4050 // of the original receiver from the call site). 4050 // of the original receiver from the call site).
4051 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi); 4051 __ mov(Operand(esp, (argc_ + 1) * kPointerSize), edi);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
4125 __ int3(); 4125 __ int3();
4126 __ bind(&okay); 4126 __ bind(&okay);
4127 } 4127 }
4128 4128
4129 // Check for failure result. 4129 // Check for failure result.
4130 Label failure_returned; 4130 Label failure_returned;
4131 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); 4131 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
4132 __ lea(ecx, Operand(eax, 1)); 4132 __ lea(ecx, Operand(eax, 1));
4133 // Lower 2 bits of ecx are 0 iff eax has failure tag. 4133 // Lower 2 bits of ecx are 0 iff eax has failure tag.
4134 __ test(ecx, Immediate(kFailureTagMask)); 4134 __ test(ecx, Immediate(kFailureTagMask));
4135 __ j(zero, &failure_returned, not_taken); 4135 __ j(zero, &failure_returned);
4136 4136
4137 ExternalReference pending_exception_address( 4137 ExternalReference pending_exception_address(
4138 Isolate::k_pending_exception_address, masm->isolate()); 4138 Isolate::k_pending_exception_address, masm->isolate());
4139 4139
4140 // Check that there is no pending exception, otherwise we 4140 // Check that there is no pending exception, otherwise we
4141 // should have returned some failure value. 4141 // should have returned some failure value.
4142 if (FLAG_debug_code) { 4142 if (FLAG_debug_code) {
4143 __ push(edx); 4143 __ push(edx);
4144 __ mov(edx, Operand::StaticVariable( 4144 __ mov(edx, Operand::StaticVariable(
4145 ExternalReference::the_hole_value_location(masm->isolate()))); 4145 ExternalReference::the_hole_value_location(masm->isolate())));
(...skipping 10 matching lines...) Expand all
4156 __ LeaveExitFrame(save_doubles_); 4156 __ LeaveExitFrame(save_doubles_);
4157 __ ret(0); 4157 __ ret(0);
4158 4158
4159 // Handling of failure. 4159 // Handling of failure.
4160 __ bind(&failure_returned); 4160 __ bind(&failure_returned);
4161 4161
4162 Label retry; 4162 Label retry;
4163 // If the returned exception is RETRY_AFTER_GC continue at retry label 4163 // If the returned exception is RETRY_AFTER_GC continue at retry label
4164 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); 4164 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0);
4165 __ test(eax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); 4165 __ test(eax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
4166 __ j(zero, &retry, taken); 4166 __ j(zero, &retry);
4167 4167
4168 // Special handling of out of memory exceptions. 4168 // Special handling of out of memory exceptions.
4169 __ cmp(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException())); 4169 __ cmp(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
4170 __ j(equal, throw_out_of_memory_exception); 4170 __ j(equal, throw_out_of_memory_exception);
4171 4171
4172 // Retrieve the pending exception and clear the variable. 4172 // Retrieve the pending exception and clear the variable.
4173 ExternalReference the_hole_location = 4173 ExternalReference the_hole_location =
4174 ExternalReference::the_hole_value_location(masm->isolate()); 4174 ExternalReference::the_hole_value_location(masm->isolate());
4175 __ mov(eax, Operand::StaticVariable(pending_exception_address)); 4175 __ mov(eax, Operand::StaticVariable(pending_exception_address));
4176 __ mov(edx, Operand::StaticVariable(the_hole_location)); 4176 __ mov(edx, Operand::StaticVariable(the_hole_location));
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
4410 4410
4411 // Get the object and function - they are always both needed. 4411 // Get the object and function - they are always both needed.
4412 Label slow, not_js_object; 4412 Label slow, not_js_object;
4413 if (!HasArgsInRegisters()) { 4413 if (!HasArgsInRegisters()) {
4414 __ mov(object, Operand(esp, 2 * kPointerSize)); 4414 __ mov(object, Operand(esp, 2 * kPointerSize));
4415 __ mov(function, Operand(esp, 1 * kPointerSize)); 4415 __ mov(function, Operand(esp, 1 * kPointerSize));
4416 } 4416 }
4417 4417
4418 // Check that the left hand is a JS object. 4418 // Check that the left hand is a JS object.
4419 __ test(object, Immediate(kSmiTagMask)); 4419 __ test(object, Immediate(kSmiTagMask));
4420 __ j(zero, &not_js_object, not_taken); 4420 __ j(zero, &not_js_object);
4421 __ IsObjectJSObjectType(object, map, scratch, &not_js_object); 4421 __ IsObjectJSObjectType(object, map, scratch, &not_js_object);
4422 4422
4423 // If there is a call site cache don't look in the global cache, but do the 4423 // If there is a call site cache don't look in the global cache, but do the
4424 // real lookup and update the call site cache. 4424 // real lookup and update the call site cache.
4425 if (!HasCallSiteInlineCheck()) { 4425 if (!HasCallSiteInlineCheck()) {
4426 // Look up the function and the map in the instanceof cache. 4426 // Look up the function and the map in the instanceof cache.
4427 Label miss; 4427 Label miss;
4428 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); 4428 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
4429 __ cmp(function, 4429 __ cmp(function,
4430 Operand::StaticArray(scratch, times_pointer_size, roots_address)); 4430 Operand::StaticArray(scratch, times_pointer_size, roots_address));
4431 __ j(not_equal, &miss, Label::kNear); 4431 __ j(not_equal, &miss, Label::kNear);
4432 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); 4432 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex));
4433 __ cmp(map, Operand::StaticArray( 4433 __ cmp(map, Operand::StaticArray(
4434 scratch, times_pointer_size, roots_address)); 4434 scratch, times_pointer_size, roots_address));
4435 __ j(not_equal, &miss, Label::kNear); 4435 __ j(not_equal, &miss, Label::kNear);
4436 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); 4436 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
4437 __ mov(eax, Operand::StaticArray( 4437 __ mov(eax, Operand::StaticArray(
4438 scratch, times_pointer_size, roots_address)); 4438 scratch, times_pointer_size, roots_address));
4439 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 4439 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
4440 __ bind(&miss); 4440 __ bind(&miss);
4441 } 4441 }
4442 4442
4443 // Get the prototype of the function. 4443 // Get the prototype of the function.
4444 __ TryGetFunctionPrototype(function, prototype, scratch, &slow); 4444 __ TryGetFunctionPrototype(function, prototype, scratch, &slow);
4445 4445
4446 // Check that the function prototype is a JS object. 4446 // Check that the function prototype is a JS object.
4447 __ test(prototype, Immediate(kSmiTagMask)); 4447 __ test(prototype, Immediate(kSmiTagMask));
4448 __ j(zero, &slow, not_taken); 4448 __ j(zero, &slow);
4449 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow); 4449 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
4450 4450
4451 // Update the global instanceof or call site inlined cache with the current 4451 // Update the global instanceof or call site inlined cache with the current
4452 // map and function. The cached answer will be set when it is known below. 4452 // map and function. The cached answer will be set when it is known below.
4453 if (!HasCallSiteInlineCheck()) { 4453 if (!HasCallSiteInlineCheck()) {
4454 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); 4454 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex));
4455 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), map); 4455 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), map);
4456 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); 4456 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
4457 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address), 4457 __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_address),
4458 function); 4458 function);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
4528 __ Set(eax, Immediate(Smi::FromInt(1))); 4528 __ Set(eax, Immediate(Smi::FromInt(1)));
4529 } 4529 }
4530 } 4530 }
4531 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 4531 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
4532 4532
4533 Label object_not_null, object_not_null_or_smi; 4533 Label object_not_null, object_not_null_or_smi;
4534 __ bind(&not_js_object); 4534 __ bind(&not_js_object);
4535 // Before null, smi and string value checks, check that the rhs is a function 4535 // Before null, smi and string value checks, check that the rhs is a function
4536 // as for a non-function rhs an exception needs to be thrown. 4536 // as for a non-function rhs an exception needs to be thrown.
4537 __ test(function, Immediate(kSmiTagMask)); 4537 __ test(function, Immediate(kSmiTagMask));
4538 __ j(zero, &slow, not_taken); 4538 __ j(zero, &slow);
4539 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); 4539 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
4540 __ j(not_equal, &slow, not_taken); 4540 __ j(not_equal, &slow);
4541 4541
4542 // Null is not instance of anything. 4542 // Null is not instance of anything.
4543 __ cmp(object, factory->null_value()); 4543 __ cmp(object, factory->null_value());
4544 __ j(not_equal, &object_not_null); 4544 __ j(not_equal, &object_not_null);
4545 __ Set(eax, Immediate(Smi::FromInt(1))); 4545 __ Set(eax, Immediate(Smi::FromInt(1)));
4546 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 4546 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
4547 4547
4548 __ bind(&object_not_null); 4548 __ bind(&object_not_null);
4549 // Smi values is not instance of anything. 4549 // Smi values is not instance of anything.
4550 __ test(object, Immediate(kSmiTagMask)); 4550 __ test(object, Immediate(kSmiTagMask));
4551 __ j(not_zero, &object_not_null_or_smi, not_taken); 4551 __ j(not_zero, &object_not_null_or_smi);
4552 __ Set(eax, Immediate(Smi::FromInt(1))); 4552 __ Set(eax, Immediate(Smi::FromInt(1)));
4553 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 4553 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
4554 4554
4555 __ bind(&object_not_null_or_smi); 4555 __ bind(&object_not_null_or_smi);
4556 // String values is not instance of anything. 4556 // String values is not instance of anything.
4557 Condition is_string = masm->IsObjectStringType(object, scratch, scratch); 4557 Condition is_string = masm->IsObjectStringType(object, scratch, scratch);
4558 __ j(NegateCondition(is_string), &slow); 4558 __ j(NegateCondition(is_string), &slow);
4559 __ Set(eax, Immediate(Smi::FromInt(1))); 4559 __ Set(eax, Immediate(Smi::FromInt(1)));
4560 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); 4560 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
4561 4561
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
4813 // StringCharFromCodeGenerator 4813 // StringCharFromCodeGenerator
4814 4814
4815 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) { 4815 void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
4816 // Fast case of Heap::LookupSingleCharacterStringFromCode. 4816 // Fast case of Heap::LookupSingleCharacterStringFromCode.
4817 STATIC_ASSERT(kSmiTag == 0); 4817 STATIC_ASSERT(kSmiTag == 0);
4818 STATIC_ASSERT(kSmiShiftSize == 0); 4818 STATIC_ASSERT(kSmiShiftSize == 0);
4819 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1)); 4819 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1));
4820 __ test(code_, 4820 __ test(code_,
4821 Immediate(kSmiTagMask | 4821 Immediate(kSmiTagMask |
4822 ((~String::kMaxAsciiCharCode) << kSmiTagSize))); 4822 ((~String::kMaxAsciiCharCode) << kSmiTagSize)));
4823 __ j(not_zero, &slow_case_, not_taken); 4823 __ j(not_zero, &slow_case_);
4824 4824
4825 Factory* factory = masm->isolate()->factory(); 4825 Factory* factory = masm->isolate()->factory();
4826 __ Set(result_, Immediate(factory->single_character_string_cache())); 4826 __ Set(result_, Immediate(factory->single_character_string_cache()));
4827 STATIC_ASSERT(kSmiTag == 0); 4827 STATIC_ASSERT(kSmiTag == 0);
4828 STATIC_ASSERT(kSmiTagSize == 1); 4828 STATIC_ASSERT(kSmiTagSize == 1);
4829 STATIC_ASSERT(kSmiShiftSize == 0); 4829 STATIC_ASSERT(kSmiShiftSize == 0);
4830 // At this point code register contains smi tagged ascii char code. 4830 // At this point code register contains smi tagged ascii char code.
4831 __ mov(result_, FieldOperand(result_, 4831 __ mov(result_, FieldOperand(result_,
4832 code_, times_half_pointer_size, 4832 code_, times_half_pointer_size,
4833 FixedArray::kHeaderSize)); 4833 FixedArray::kHeaderSize));
4834 __ cmp(result_, factory->undefined_value()); 4834 __ cmp(result_, factory->undefined_value());
4835 __ j(equal, &slow_case_, not_taken); 4835 __ j(equal, &slow_case_);
4836 __ bind(&exit_); 4836 __ bind(&exit_);
4837 } 4837 }
4838 4838
4839 4839
4840 void StringCharFromCodeGenerator::GenerateSlow( 4840 void StringCharFromCodeGenerator::GenerateSlow(
4841 MacroAssembler* masm, const RuntimeCallHelper& call_helper) { 4841 MacroAssembler* masm, const RuntimeCallHelper& call_helper) {
4842 __ Abort("Unexpected fallthrough to CharFromCode slow case"); 4842 __ Abort("Unexpected fallthrough to CharFromCode slow case");
4843 4843
4844 __ bind(&slow_case_); 4844 __ bind(&slow_case_);
4845 call_helper.BeforeCall(masm); 4845 call_helper.BeforeCall(masm);
(...skipping 928 matching lines...) Expand 10 before | Expand all | Expand 10 after
5774 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 5774 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
5775 } 5775 }
5776 5776
5777 5777
5778 void ICCompareStub::GenerateSmis(MacroAssembler* masm) { 5778 void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
5779 ASSERT(state_ == CompareIC::SMIS); 5779 ASSERT(state_ == CompareIC::SMIS);
5780 Label miss; 5780 Label miss;
5781 __ mov(ecx, Operand(edx)); 5781 __ mov(ecx, Operand(edx));
5782 __ or_(ecx, Operand(eax)); 5782 __ or_(ecx, Operand(eax));
5783 __ test(ecx, Immediate(kSmiTagMask)); 5783 __ test(ecx, Immediate(kSmiTagMask));
5784 __ j(not_zero, &miss, not_taken, Label::kNear); 5784 __ j(not_zero, &miss, Label::kNear);
5785 5785
5786 if (GetCondition() == equal) { 5786 if (GetCondition() == equal) {
5787 // For equality we do not care about the sign of the result. 5787 // For equality we do not care about the sign of the result.
5788 __ sub(eax, Operand(edx)); 5788 __ sub(eax, Operand(edx));
5789 } else { 5789 } else {
5790 Label done; 5790 Label done;
5791 __ sub(edx, Operand(eax)); 5791 __ sub(edx, Operand(eax));
5792 __ j(no_overflow, &done, Label::kNear); 5792 __ j(no_overflow, &done, Label::kNear);
5793 // Correct sign of result in case of overflow. 5793 // Correct sign of result in case of overflow.
5794 __ not_(edx); 5794 __ not_(edx);
5795 __ bind(&done); 5795 __ bind(&done);
5796 __ mov(eax, edx); 5796 __ mov(eax, edx);
5797 } 5797 }
5798 __ ret(0); 5798 __ ret(0);
5799 5799
5800 __ bind(&miss); 5800 __ bind(&miss);
5801 GenerateMiss(masm); 5801 GenerateMiss(masm);
5802 } 5802 }
5803 5803
5804 5804
5805 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) { 5805 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
5806 ASSERT(state_ == CompareIC::HEAP_NUMBERS); 5806 ASSERT(state_ == CompareIC::HEAP_NUMBERS);
5807 5807
5808 Label generic_stub; 5808 Label generic_stub;
5809 Label unordered; 5809 Label unordered;
5810 Label miss; 5810 Label miss;
5811 __ mov(ecx, Operand(edx)); 5811 __ mov(ecx, Operand(edx));
5812 __ and_(ecx, Operand(eax)); 5812 __ and_(ecx, Operand(eax));
5813 __ test(ecx, Immediate(kSmiTagMask)); 5813 __ test(ecx, Immediate(kSmiTagMask));
5814 __ j(zero, &generic_stub, not_taken, Label::kNear); 5814 __ j(zero, &generic_stub, Label::kNear);
5815 5815
5816 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx); 5816 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx);
5817 __ j(not_equal, &miss, not_taken, Label::kNear); 5817 __ j(not_equal, &miss, Label::kNear);
5818 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx); 5818 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ecx);
5819 __ j(not_equal, &miss, not_taken, Label::kNear); 5819 __ j(not_equal, &miss, Label::kNear);
5820 5820
5821 // Inlining the double comparison and falling back to the general compare 5821 // Inlining the double comparison and falling back to the general compare
5822 // stub if NaN is involved or SS2 or CMOV is unsupported. 5822 // stub if NaN is involved or SS2 or CMOV is unsupported.
5823 if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) { 5823 if (CpuFeatures::IsSupported(SSE2) && CpuFeatures::IsSupported(CMOV)) {
5824 CpuFeatures::Scope scope1(SSE2); 5824 CpuFeatures::Scope scope1(SSE2);
5825 CpuFeatures::Scope scope2(CMOV); 5825 CpuFeatures::Scope scope2(CMOV);
5826 5826
5827 // Load left and right operand 5827 // Load left and right operand
5828 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); 5828 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
5829 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); 5829 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
5830 5830
5831 // Compare operands 5831 // Compare operands
5832 __ ucomisd(xmm0, xmm1); 5832 __ ucomisd(xmm0, xmm1);
5833 5833
5834 // Don't base result on EFLAGS when a NaN is involved. 5834 // Don't base result on EFLAGS when a NaN is involved.
5835 __ j(parity_even, &unordered, not_taken, Label::kNear); 5835 __ j(parity_even, &unordered, Label::kNear);
5836 5836
5837 // Return a result of -1, 0, or 1, based on EFLAGS. 5837 // Return a result of -1, 0, or 1, based on EFLAGS.
5838 // Performing mov, because xor would destroy the flag register. 5838 // Performing mov, because xor would destroy the flag register.
5839 __ mov(eax, 0); // equal 5839 __ mov(eax, 0); // equal
5840 __ mov(ecx, Immediate(Smi::FromInt(1))); 5840 __ mov(ecx, Immediate(Smi::FromInt(1)));
5841 __ cmov(above, eax, Operand(ecx)); 5841 __ cmov(above, eax, Operand(ecx));
5842 __ mov(ecx, Immediate(Smi::FromInt(-1))); 5842 __ mov(ecx, Immediate(Smi::FromInt(-1)));
5843 __ cmov(below, eax, Operand(ecx)); 5843 __ cmov(below, eax, Operand(ecx));
5844 __ ret(0); 5844 __ ret(0);
5845 5845
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
5977 GenerateMiss(masm); 5977 GenerateMiss(masm);
5978 } 5978 }
5979 5979
5980 5980
5981 void ICCompareStub::GenerateObjects(MacroAssembler* masm) { 5981 void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
5982 ASSERT(state_ == CompareIC::OBJECTS); 5982 ASSERT(state_ == CompareIC::OBJECTS);
5983 Label miss; 5983 Label miss;
5984 __ mov(ecx, Operand(edx)); 5984 __ mov(ecx, Operand(edx));
5985 __ and_(ecx, Operand(eax)); 5985 __ and_(ecx, Operand(eax));
5986 __ test(ecx, Immediate(kSmiTagMask)); 5986 __ test(ecx, Immediate(kSmiTagMask));
5987 __ j(zero, &miss, not_taken, Label::kNear); 5987 __ j(zero, &miss, Label::kNear);
5988 5988
5989 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); 5989 __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx);
5990 __ j(not_equal, &miss, not_taken, Label::kNear); 5990 __ j(not_equal, &miss, Label::kNear);
5991 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); 5991 __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx);
5992 __ j(not_equal, &miss, not_taken, Label::kNear); 5992 __ j(not_equal, &miss, Label::kNear);
5993 5993
5994 ASSERT(GetCondition() == equal); 5994 ASSERT(GetCondition() == equal);
5995 __ sub(eax, Operand(edx)); 5995 __ sub(eax, Operand(edx));
5996 __ ret(0); 5996 __ ret(0);
5997 5997
5998 __ bind(&miss); 5998 __ bind(&miss);
5999 GenerateMiss(masm); 5999 GenerateMiss(masm);
6000 } 6000 }
6001 6001
6002 6002
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
6062 6062
6063 // Scale the index by multiplying by the entry size. 6063 // Scale the index by multiplying by the entry size.
6064 ASSERT(StringDictionary::kEntrySize == 3); 6064 ASSERT(StringDictionary::kEntrySize == 3);
6065 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. 6065 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3.
6066 Register entity_name = r0; 6066 Register entity_name = r0;
6067 // Having undefined at this place means the name is not contained. 6067 // Having undefined at this place means the name is not contained.
6068 ASSERT_EQ(kSmiTagSize, 1); 6068 ASSERT_EQ(kSmiTagSize, 1);
6069 __ mov(entity_name, Operand(properties, index, times_half_pointer_size, 6069 __ mov(entity_name, Operand(properties, index, times_half_pointer_size,
6070 kElementsStartOffset - kHeapObjectTag)); 6070 kElementsStartOffset - kHeapObjectTag));
6071 __ cmp(entity_name, masm->isolate()->factory()->undefined_value()); 6071 __ cmp(entity_name, masm->isolate()->factory()->undefined_value());
6072 __ j(equal, done, taken); 6072 __ j(equal, done);
6073 6073
6074 // Stop if found the property. 6074 // Stop if found the property.
6075 __ cmp(entity_name, Handle<String>(name)); 6075 __ cmp(entity_name, Handle<String>(name));
6076 __ j(equal, miss, not_taken); 6076 __ j(equal, miss);
6077 6077
6078 // Check if the entry name is not a symbol. 6078 // Check if the entry name is not a symbol.
6079 __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); 6079 __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
6080 __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset), 6080 __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset),
6081 kIsSymbolMask); 6081 kIsSymbolMask);
6082 __ j(zero, miss, not_taken); 6082 __ j(zero, miss);
6083 } 6083 }
6084 6084
6085 StringDictionaryLookupStub stub(properties, 6085 StringDictionaryLookupStub stub(properties,
6086 r0, 6086 r0,
6087 r0, 6087 r0,
6088 StringDictionaryLookupStub::NEGATIVE_LOOKUP); 6088 StringDictionaryLookupStub::NEGATIVE_LOOKUP);
6089 __ push(Immediate(Handle<Object>(name))); 6089 __ push(Immediate(Handle<Object>(name)));
6090 __ push(Immediate(name->Hash())); 6090 __ push(Immediate(name->Hash()));
6091 MaybeObject* result = masm->TryCallStub(&stub); 6091 MaybeObject* result = masm->TryCallStub(&stub);
6092 if (result->IsFailure()) return result; 6092 if (result->IsFailure()) return result;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
6129 6129
6130 // Scale the index by multiplying by the entry size. 6130 // Scale the index by multiplying by the entry size.
6131 ASSERT(StringDictionary::kEntrySize == 3); 6131 ASSERT(StringDictionary::kEntrySize == 3);
6132 __ lea(r0, Operand(r0, r0, times_2, 0)); // r0 = r0 * 3 6132 __ lea(r0, Operand(r0, r0, times_2, 0)); // r0 = r0 * 3
6133 6133
6134 // Check if the key is identical to the name. 6134 // Check if the key is identical to the name.
6135 __ cmp(name, Operand(elements, 6135 __ cmp(name, Operand(elements,
6136 r0, 6136 r0,
6137 times_4, 6137 times_4,
6138 kElementsStartOffset - kHeapObjectTag)); 6138 kElementsStartOffset - kHeapObjectTag));
6139 __ j(equal, done, taken); 6139 __ j(equal, done);
6140 } 6140 }
6141 6141
6142 StringDictionaryLookupStub stub(elements, 6142 StringDictionaryLookupStub stub(elements,
6143 r1, 6143 r1,
6144 r0, 6144 r0,
6145 POSITIVE_LOOKUP); 6145 POSITIVE_LOOKUP);
6146 __ push(name); 6146 __ push(name);
6147 __ mov(r0, FieldOperand(name, String::kHashFieldOffset)); 6147 __ mov(r0, FieldOperand(name, String::kHashFieldOffset));
6148 __ shr(r0, String::kHashShift); 6148 __ shr(r0, String::kHashShift);
6149 __ push(r0); 6149 __ push(r0);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
6241 __ Drop(1); 6241 __ Drop(1);
6242 __ ret(2 * kPointerSize); 6242 __ ret(2 * kPointerSize);
6243 } 6243 }
6244 6244
6245 6245
6246 #undef __ 6246 #undef __
6247 6247
6248 } } // namespace v8::internal 6248 } } // namespace v8::internal
6249 6249
6250 #endif // V8_TARGET_ARCH_IA32 6250 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/builtins-ia32.cc ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698