| 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 |