OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 1386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1397 __ SmiToInteger32(kScratchRegister, rax); | 1397 __ SmiToInteger32(kScratchRegister, rax); |
1398 __ cvtlsi2sd(xmm1, kScratchRegister); | 1398 __ cvtlsi2sd(xmm1, kScratchRegister); |
1399 __ bind(&done); | 1399 __ bind(&done); |
1400 } | 1400 } |
1401 | 1401 |
1402 | 1402 |
1403 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { | 1403 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { |
1404 Label slow, done; | 1404 Label slow, done; |
1405 | 1405 |
1406 if (op_ == Token::SUB) { | 1406 if (op_ == Token::SUB) { |
1407 // Check whether the value is a smi. | 1407 if (include_smi_code_) { |
1408 Label try_float; | 1408 // Check whether the value is a smi. |
1409 __ JumpIfNotSmi(rax, &try_float); | 1409 Label try_float; |
| 1410 __ JumpIfNotSmi(rax, &try_float); |
| 1411 if (negative_zero_ == kIgnoreNegativeZero) { |
| 1412 __ SmiCompare(rax, Smi::FromInt(0)); |
| 1413 __ j(equal, &done); |
| 1414 } |
| 1415 __ SmiNeg(rax, rax, &done); |
1410 | 1416 |
1411 if (negative_zero_ == kIgnoreNegativeZero) { | 1417 // Either zero or Smi::kMinValue, neither of which become a smi when |
1412 __ SmiCompare(rax, Smi::FromInt(0)); | 1418 // negated. We handle negative zero here if required. We always enter |
1413 __ j(equal, &done); | 1419 // the runtime system if we have Smi::kMinValue. |
| 1420 if (negative_zero_ == kStrictNegativeZero) { |
| 1421 __ SmiCompare(rax, Smi::FromInt(0)); |
| 1422 __ j(not_equal, &slow); |
| 1423 __ Move(rax, Factory::minus_zero_value()); |
| 1424 __ jmp(&done); |
| 1425 } else { |
| 1426 __ SmiCompare(rax, Smi::FromInt(Smi::kMinValue)); |
| 1427 __ j(equal, &slow); |
| 1428 __ jmp(&done); |
| 1429 } |
| 1430 // Try floating point case. |
| 1431 __ bind(&try_float); |
| 1432 } else if (FLAG_debug_code) { |
| 1433 __ AbortIfSmi(rax); |
1414 } | 1434 } |
1415 | 1435 |
1416 // Enter runtime system if the value of the smi is zero | |
1417 // to make sure that we switch between 0 and -0. | |
1418 // Also enter it if the value of the smi is Smi::kMinValue. | |
1419 __ SmiNeg(rax, rax, &done); | |
1420 | |
1421 // Either zero or Smi::kMinValue, neither of which become a smi when | |
1422 // negated. | |
1423 if (negative_zero_ == kStrictNegativeZero) { | |
1424 __ SmiCompare(rax, Smi::FromInt(0)); | |
1425 __ j(not_equal, &slow); | |
1426 __ Move(rax, Factory::minus_zero_value()); | |
1427 __ jmp(&done); | |
1428 } else { | |
1429 __ jmp(&slow); | |
1430 } | |
1431 | |
1432 // Try floating point case. | |
1433 __ bind(&try_float); | |
1434 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); | 1436 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); |
1435 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); | 1437 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); |
1436 __ j(not_equal, &slow); | 1438 __ j(not_equal, &slow); |
1437 // Operand is a float, negate its value by flipping sign bit. | 1439 // Operand is a float, negate its value by flipping sign bit. |
1438 __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset)); | 1440 __ movq(rdx, FieldOperand(rax, HeapNumber::kValueOffset)); |
1439 __ movq(kScratchRegister, Immediate(0x01)); | 1441 __ movq(kScratchRegister, Immediate(0x01)); |
1440 __ shl(kScratchRegister, Immediate(63)); | 1442 __ shl(kScratchRegister, Immediate(63)); |
1441 __ xor_(rdx, kScratchRegister); // Flip sign. | 1443 __ xor_(rdx, kScratchRegister); // Flip sign. |
1442 // rdx is value to store. | 1444 // rdx is value to store. |
1443 if (overwrite_ == UNARY_OVERWRITE) { | 1445 if (overwrite_ == UNARY_OVERWRITE) { |
1444 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rdx); | 1446 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rdx); |
1445 } else { | 1447 } else { |
1446 __ AllocateHeapNumber(rcx, rbx, &slow); | 1448 __ AllocateHeapNumber(rcx, rbx, &slow); |
1447 // rcx: allocated 'empty' number | 1449 // rcx: allocated 'empty' number |
1448 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx); | 1450 __ movq(FieldOperand(rcx, HeapNumber::kValueOffset), rdx); |
1449 __ movq(rax, rcx); | 1451 __ movq(rax, rcx); |
1450 } | 1452 } |
1451 } else if (op_ == Token::BIT_NOT) { | 1453 } else if (op_ == Token::BIT_NOT) { |
| 1454 if (include_smi_code_) { |
| 1455 Label try_float; |
| 1456 __ JumpIfNotSmi(rax, &try_float); |
| 1457 __ SmiNot(rax, rax); |
| 1458 __ jmp(&done); |
| 1459 // Try floating point case. |
| 1460 __ bind(&try_float); |
| 1461 } else if (FLAG_debug_code) { |
| 1462 __ AbortIfSmi(rax); |
| 1463 } |
| 1464 |
1452 // Check if the operand is a heap number. | 1465 // Check if the operand is a heap number. |
1453 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); | 1466 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); |
1454 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); | 1467 __ CompareRoot(rdx, Heap::kHeapNumberMapRootIndex); |
1455 __ j(not_equal, &slow); | 1468 __ j(not_equal, &slow); |
1456 | 1469 |
1457 // Convert the heap number in rax to an untagged integer in rcx. | 1470 // Convert the heap number in rax to an untagged integer in rcx. |
1458 IntegerConvert(masm, rax, rax); | 1471 IntegerConvert(masm, rax, rax); |
1459 | 1472 |
1460 // Do the bitwise operation and smi tag the result. | 1473 // Do the bitwise operation and smi tag the result. |
1461 __ notl(rax); | 1474 __ notl(rax); |
(...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2108 ASSERT((cc == less) || (cc == less_equal) | 2121 ASSERT((cc == less) || (cc == less_equal) |
2109 || (cc == greater) || (cc == greater_equal)); | 2122 || (cc == greater) || (cc == greater_equal)); |
2110 return (cc == greater || cc == greater_equal) ? LESS : GREATER; | 2123 return (cc == greater || cc == greater_equal) ? LESS : GREATER; |
2111 } | 2124 } |
2112 | 2125 |
2113 | 2126 |
2114 void CompareStub::Generate(MacroAssembler* masm) { | 2127 void CompareStub::Generate(MacroAssembler* masm) { |
2115 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); | 2128 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); |
2116 | 2129 |
2117 Label check_unequal_objects, done; | 2130 Label check_unequal_objects, done; |
| 2131 |
| 2132 // Compare two smis if required. |
| 2133 if (include_smi_compare_) { |
| 2134 Label non_smi, smi_done; |
| 2135 __ JumpIfNotBothSmi(rax, rdx, &non_smi); |
| 2136 __ subq(rdx, rax); |
| 2137 __ j(no_overflow, &smi_done); |
| 2138 __ neg(rdx); // Correct sign in case of overflow. |
| 2139 __ bind(&smi_done); |
| 2140 __ movq(rax, rdx); |
| 2141 __ ret(0); |
| 2142 __ bind(&non_smi); |
| 2143 } else if (FLAG_debug_code) { |
| 2144 Label ok; |
| 2145 __ JumpIfNotSmi(rdx, &ok); |
| 2146 __ JumpIfNotSmi(rax, &ok); |
| 2147 __ Abort("CompareStub: smi operands"); |
| 2148 __ bind(&ok); |
| 2149 } |
| 2150 |
2118 // The compare stub returns a positive, negative, or zero 64-bit integer | 2151 // The compare stub returns a positive, negative, or zero 64-bit integer |
2119 // value in rax, corresponding to result of comparing the two inputs. | 2152 // value in rax, corresponding to result of comparing the two inputs. |
2120 // NOTICE! This code is only reached after a smi-fast-case check, so | 2153 // NOTICE! This code is only reached after a smi-fast-case check, so |
2121 // it is certain that at least one operand isn't a smi. | 2154 // it is certain that at least one operand isn't a smi. |
2122 | 2155 |
2123 // Two identical objects are equal unless they are both NaN or undefined. | 2156 // Two identical objects are equal unless they are both NaN or undefined. |
2124 { | 2157 { |
2125 Label not_identical; | 2158 Label not_identical; |
2126 __ cmpq(rax, rdx); | 2159 __ cmpq(rax, rdx); |
2127 __ j(not_equal, ¬_identical); | 2160 __ j(not_equal, ¬_identical); |
(...skipping 866 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2994 int CompareStub::MinorKey() { | 3027 int CompareStub::MinorKey() { |
2995 // Encode the three parameters in a unique 16 bit value. To avoid duplicate | 3028 // Encode the three parameters in a unique 16 bit value. To avoid duplicate |
2996 // stubs the never NaN NaN condition is only taken into account if the | 3029 // stubs the never NaN NaN condition is only taken into account if the |
2997 // condition is equals. | 3030 // condition is equals. |
2998 ASSERT(static_cast<unsigned>(cc_) < (1 << 12)); | 3031 ASSERT(static_cast<unsigned>(cc_) < (1 << 12)); |
2999 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); | 3032 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); |
3000 return ConditionField::encode(static_cast<unsigned>(cc_)) | 3033 return ConditionField::encode(static_cast<unsigned>(cc_)) |
3001 | RegisterField::encode(false) // lhs_ and rhs_ are not used | 3034 | RegisterField::encode(false) // lhs_ and rhs_ are not used |
3002 | StrictField::encode(strict_) | 3035 | StrictField::encode(strict_) |
3003 | NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false) | 3036 | NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false) |
3004 | IncludeNumberCompareField::encode(include_number_compare_); | 3037 | IncludeNumberCompareField::encode(include_number_compare_) |
| 3038 | IncludeSmiCompareField::encode(include_smi_compare_); |
3005 } | 3039 } |
3006 | 3040 |
3007 | 3041 |
3008 // Unfortunately you have to run without snapshots to see most of these | 3042 // Unfortunately you have to run without snapshots to see most of these |
3009 // names in the profile since most compare stubs end up in the snapshot. | 3043 // names in the profile since most compare stubs end up in the snapshot. |
3010 const char* CompareStub::GetName() { | 3044 const char* CompareStub::GetName() { |
3011 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); | 3045 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); |
3012 | 3046 |
3013 if (name_ != NULL) return name_; | 3047 if (name_ != NULL) return name_; |
3014 const int kMaxNameLength = 100; | 3048 const int kMaxNameLength = 100; |
(...skipping 19 matching lines...) Expand all Loading... |
3034 const char* never_nan_nan_name = ""; | 3068 const char* never_nan_nan_name = ""; |
3035 if (never_nan_nan_ && (cc_ == equal || cc_ == not_equal)) { | 3069 if (never_nan_nan_ && (cc_ == equal || cc_ == not_equal)) { |
3036 never_nan_nan_name = "_NO_NAN"; | 3070 never_nan_nan_name = "_NO_NAN"; |
3037 } | 3071 } |
3038 | 3072 |
3039 const char* include_number_compare_name = ""; | 3073 const char* include_number_compare_name = ""; |
3040 if (!include_number_compare_) { | 3074 if (!include_number_compare_) { |
3041 include_number_compare_name = "_NO_NUMBER"; | 3075 include_number_compare_name = "_NO_NUMBER"; |
3042 } | 3076 } |
3043 | 3077 |
| 3078 const char* include_smi_compare_name = ""; |
| 3079 if (!include_smi_compare_) { |
| 3080 include_smi_compare_name = "_NO_SMI"; |
| 3081 } |
| 3082 |
3044 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), | 3083 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), |
3045 "CompareStub_%s%s%s%s", | 3084 "CompareStub_%s%s%s%s", |
3046 cc_name, | 3085 cc_name, |
3047 strict_name, | 3086 strict_name, |
3048 never_nan_nan_name, | 3087 never_nan_nan_name, |
3049 include_number_compare_name); | 3088 include_number_compare_name, |
| 3089 include_smi_compare_name); |
3050 return name_; | 3090 return name_; |
3051 } | 3091 } |
3052 | 3092 |
3053 | 3093 |
3054 // ------------------------------------------------------------------------- | 3094 // ------------------------------------------------------------------------- |
3055 // StringCharCodeAtGenerator | 3095 // StringCharCodeAtGenerator |
3056 | 3096 |
3057 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 3097 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
3058 Label flat_string; | 3098 Label flat_string; |
3059 Label ascii_string; | 3099 Label ascii_string; |
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4006 // tagged as a small integer. | 4046 // tagged as a small integer. |
4007 __ bind(&runtime); | 4047 __ bind(&runtime); |
4008 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 4048 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
4009 } | 4049 } |
4010 | 4050 |
4011 #undef __ | 4051 #undef __ |
4012 | 4052 |
4013 } } // namespace v8::internal | 4053 } } // namespace v8::internal |
4014 | 4054 |
4015 #endif // V8_TARGET_ARCH_X64 | 4055 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |