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