OLD | NEW |
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 Loading... |
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, ¬_smis, not_taken); | 1021 __ j(not_zero, ¬_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, ¬_smis, not_taken); | 1143 __ j(zero, ¬_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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, ¬_js_object, not_taken); | 4420 __ j(zero, ¬_js_object); |
4421 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); | 4421 __ IsObjectJSObjectType(object, map, scratch, ¬_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 Loading... |
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(¬_js_object); | 4534 __ bind(¬_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |