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 1861 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1872 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); | 1872 __ mov(scratch, FieldOperand(eax, HeapObject::kMapOffset)); |
1873 __ cmp(scratch, Factory::heap_number_map()); | 1873 __ cmp(scratch, Factory::heap_number_map()); |
1874 __ j(not_equal, non_float); // argument in eax is not a number -> NaN | 1874 __ j(not_equal, non_float); // argument in eax is not a number -> NaN |
1875 | 1875 |
1876 // Fall-through: Both operands are numbers. | 1876 // Fall-through: Both operands are numbers. |
1877 __ bind(&done); | 1877 __ bind(&done); |
1878 } | 1878 } |
1879 | 1879 |
1880 | 1880 |
1881 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { | 1881 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { |
1882 Label slow, done; | 1882 Label slow, done, undo; |
1883 | 1883 |
1884 if (op_ == Token::SUB) { | 1884 if (op_ == Token::SUB) { |
1885 // Check whether the value is a smi. | 1885 if (include_smi_code_) { |
1886 Label try_float; | 1886 // Check whether the value is a smi. |
1887 __ test(eax, Immediate(kSmiTagMask)); | 1887 Label try_float; |
1888 __ j(not_zero, &try_float, not_taken); | 1888 __ test(eax, Immediate(kSmiTagMask)); |
| 1889 __ j(not_zero, &try_float, not_taken); |
1889 | 1890 |
1890 if (negative_zero_ == kStrictNegativeZero) { | 1891 if (negative_zero_ == kStrictNegativeZero) { |
1891 // Go slow case if the value of the expression is zero | 1892 // Go slow case if the value of the expression is zero |
1892 // to make sure that we switch between 0 and -0. | 1893 // to make sure that we switch between 0 and -0. |
1893 __ test(eax, Operand(eax)); | 1894 __ test(eax, Operand(eax)); |
1894 __ j(zero, &slow, not_taken); | 1895 __ j(zero, &slow, not_taken); |
| 1896 } |
| 1897 |
| 1898 // The value of the expression is a smi that is not zero. Try |
| 1899 // optimistic subtraction '0 - value'. |
| 1900 __ mov(edx, Operand(eax)); |
| 1901 __ Set(eax, Immediate(0)); |
| 1902 __ sub(eax, Operand(edx)); |
| 1903 __ j(overflow, &undo, not_taken); |
| 1904 __ StubReturn(1); |
| 1905 |
| 1906 // Try floating point case. |
| 1907 __ bind(&try_float); |
| 1908 } else if (FLAG_debug_code) { |
| 1909 __ AbortIfSmi(eax); |
1895 } | 1910 } |
1896 | 1911 |
1897 // The value of the expression is a smi that is not zero. Try | |
1898 // optimistic subtraction '0 - value'. | |
1899 Label undo; | |
1900 __ mov(edx, Operand(eax)); | |
1901 __ Set(eax, Immediate(0)); | |
1902 __ sub(eax, Operand(edx)); | |
1903 __ j(no_overflow, &done, taken); | |
1904 | |
1905 // Restore eax and go slow case. | |
1906 __ bind(&undo); | |
1907 __ mov(eax, Operand(edx)); | |
1908 __ jmp(&slow); | |
1909 | |
1910 // Try floating point case. | |
1911 __ bind(&try_float); | |
1912 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 1912 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
1913 __ cmp(edx, Factory::heap_number_map()); | 1913 __ cmp(edx, Factory::heap_number_map()); |
1914 __ j(not_equal, &slow); | 1914 __ j(not_equal, &slow); |
1915 if (overwrite_ == UNARY_OVERWRITE) { | 1915 if (overwrite_ == UNARY_OVERWRITE) { |
1916 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); | 1916 __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset)); |
1917 __ xor_(edx, HeapNumber::kSignMask); // Flip sign. | 1917 __ xor_(edx, HeapNumber::kSignMask); // Flip sign. |
1918 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), edx); | 1918 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), edx); |
1919 } else { | 1919 } else { |
1920 __ mov(edx, Operand(eax)); | 1920 __ mov(edx, Operand(eax)); |
1921 // edx: operand | 1921 // edx: operand |
1922 __ AllocateHeapNumber(eax, ebx, ecx, &undo); | 1922 __ AllocateHeapNumber(eax, ebx, ecx, &undo); |
1923 // eax: allocated 'empty' number | 1923 // eax: allocated 'empty' number |
1924 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); | 1924 __ mov(ecx, FieldOperand(edx, HeapNumber::kExponentOffset)); |
1925 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. | 1925 __ xor_(ecx, HeapNumber::kSignMask); // Flip sign. |
1926 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ecx); | 1926 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ecx); |
1927 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset)); | 1927 __ mov(ecx, FieldOperand(edx, HeapNumber::kMantissaOffset)); |
1928 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); | 1928 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); |
1929 } | 1929 } |
1930 } else if (op_ == Token::BIT_NOT) { | 1930 } else if (op_ == Token::BIT_NOT) { |
| 1931 if (include_smi_code_) { |
| 1932 Label non_smi; |
| 1933 __ test(eax, Immediate(kSmiTagMask)); |
| 1934 __ j(not_zero, &non_smi); |
| 1935 __ not_(eax); |
| 1936 __ and_(eax, ~kSmiTagMask); // Remove inverted smi-tag. |
| 1937 __ ret(0); |
| 1938 __ bind(&non_smi); |
| 1939 } else if (FLAG_debug_code) { |
| 1940 __ AbortIfSmi(eax); |
| 1941 } |
| 1942 |
1931 // Check if the operand is a heap number. | 1943 // Check if the operand is a heap number. |
1932 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); | 1944 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); |
1933 __ cmp(edx, Factory::heap_number_map()); | 1945 __ cmp(edx, Factory::heap_number_map()); |
1934 __ j(not_equal, &slow, not_taken); | 1946 __ j(not_equal, &slow, not_taken); |
1935 | 1947 |
1936 // Convert the heap number in eax to an untagged integer in ecx. | 1948 // Convert the heap number in eax to an untagged integer in ecx. |
1937 IntegerConvert(masm, | 1949 IntegerConvert(masm, |
1938 eax, | 1950 eax, |
1939 TypeInfo::Unknown(), | 1951 TypeInfo::Unknown(), |
1940 CpuFeatures::IsSupported(SSE3), | 1952 CpuFeatures::IsSupported(SSE3), |
(...skipping 30 matching lines...) Expand all Loading... |
1971 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1983 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
1972 } | 1984 } |
1973 } else { | 1985 } else { |
1974 UNIMPLEMENTED(); | 1986 UNIMPLEMENTED(); |
1975 } | 1987 } |
1976 | 1988 |
1977 // Return from the stub. | 1989 // Return from the stub. |
1978 __ bind(&done); | 1990 __ bind(&done); |
1979 __ StubReturn(1); | 1991 __ StubReturn(1); |
1980 | 1992 |
| 1993 // Restore eax and go slow case. |
| 1994 __ bind(&undo); |
| 1995 __ mov(eax, Operand(edx)); |
| 1996 |
1981 // Handle the slow case by jumping to the JavaScript builtin. | 1997 // Handle the slow case by jumping to the JavaScript builtin. |
1982 __ bind(&slow); | 1998 __ bind(&slow); |
1983 __ pop(ecx); // pop return address. | 1999 __ pop(ecx); // pop return address. |
1984 __ push(eax); | 2000 __ push(eax); |
1985 __ push(ecx); // push return address | 2001 __ push(ecx); // push return address |
1986 switch (op_) { | 2002 switch (op_) { |
1987 case Token::SUB: | 2003 case Token::SUB: |
1988 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); | 2004 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); |
1989 break; | 2005 break; |
1990 case Token::BIT_NOT: | 2006 case Token::BIT_NOT: |
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2606 ASSERT((cc == less) || (cc == less_equal) | 2622 ASSERT((cc == less) || (cc == less_equal) |
2607 || (cc == greater) || (cc == greater_equal)); | 2623 || (cc == greater) || (cc == greater_equal)); |
2608 return (cc == greater || cc == greater_equal) ? LESS : GREATER; | 2624 return (cc == greater || cc == greater_equal) ? LESS : GREATER; |
2609 } | 2625 } |
2610 | 2626 |
2611 void CompareStub::Generate(MacroAssembler* masm) { | 2627 void CompareStub::Generate(MacroAssembler* masm) { |
2612 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); | 2628 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); |
2613 | 2629 |
2614 Label check_unequal_objects, done; | 2630 Label check_unequal_objects, done; |
2615 | 2631 |
| 2632 // Compare two smis if required. |
| 2633 if (include_smi_compare_) { |
| 2634 Label non_smi, smi_done; |
| 2635 __ mov(ecx, Operand(edx)); |
| 2636 __ or_(ecx, Operand(eax)); |
| 2637 __ test(ecx, Immediate(kSmiTagMask)); |
| 2638 __ j(not_zero, &non_smi, not_taken); |
| 2639 __ sub(edx, Operand(eax)); // Return on the result of the subtraction. |
| 2640 __ j(no_overflow, &smi_done); |
| 2641 __ neg(edx); // Correct sign in case of overflow. |
| 2642 __ bind(&smi_done); |
| 2643 __ mov(eax, edx); |
| 2644 __ ret(0); |
| 2645 __ bind(&non_smi); |
| 2646 } else if (FLAG_debug_code) { |
| 2647 __ mov(ecx, Operand(edx)); |
| 2648 __ or_(ecx, Operand(eax)); |
| 2649 __ test(ecx, Immediate(kSmiTagMask)); |
| 2650 __ Assert(not_zero, "Unexpected smi operands."); |
| 2651 } |
| 2652 |
2616 // NOTICE! This code is only reached after a smi-fast-case check, so | 2653 // NOTICE! This code is only reached after a smi-fast-case check, so |
2617 // it is certain that at least one operand isn't a smi. | 2654 // it is certain that at least one operand isn't a smi. |
2618 | 2655 |
2619 // Identical objects can be compared fast, but there are some tricky cases | 2656 // Identical objects can be compared fast, but there are some tricky cases |
2620 // for NaN and undefined. | 2657 // for NaN and undefined. |
2621 { | 2658 { |
2622 Label not_identical; | 2659 Label not_identical; |
2623 __ cmp(eax, Operand(edx)); | 2660 __ cmp(eax, Operand(edx)); |
2624 __ j(not_equal, ¬_identical); | 2661 __ j(not_equal, ¬_identical); |
2625 | 2662 |
(...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3494 int CompareStub::MinorKey() { | 3531 int CompareStub::MinorKey() { |
3495 // Encode the three parameters in a unique 16 bit value. To avoid duplicate | 3532 // Encode the three parameters in a unique 16 bit value. To avoid duplicate |
3496 // stubs the never NaN NaN condition is only taken into account if the | 3533 // stubs the never NaN NaN condition is only taken into account if the |
3497 // condition is equals. | 3534 // condition is equals. |
3498 ASSERT(static_cast<unsigned>(cc_) < (1 << 12)); | 3535 ASSERT(static_cast<unsigned>(cc_) < (1 << 12)); |
3499 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); | 3536 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); |
3500 return ConditionField::encode(static_cast<unsigned>(cc_)) | 3537 return ConditionField::encode(static_cast<unsigned>(cc_)) |
3501 | RegisterField::encode(false) // lhs_ and rhs_ are not used | 3538 | RegisterField::encode(false) // lhs_ and rhs_ are not used |
3502 | StrictField::encode(strict_) | 3539 | StrictField::encode(strict_) |
3503 | NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false) | 3540 | NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false) |
3504 | IncludeNumberCompareField::encode(include_number_compare_); | 3541 | IncludeNumberCompareField::encode(include_number_compare_) |
| 3542 | IncludeSmiCompareField::encode(include_smi_compare_); |
3505 } | 3543 } |
3506 | 3544 |
3507 | 3545 |
3508 // Unfortunately you have to run without snapshots to see most of these | 3546 // Unfortunately you have to run without snapshots to see most of these |
3509 // names in the profile since most compare stubs end up in the snapshot. | 3547 // names in the profile since most compare stubs end up in the snapshot. |
3510 const char* CompareStub::GetName() { | 3548 const char* CompareStub::GetName() { |
3511 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); | 3549 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); |
3512 | 3550 |
3513 if (name_ != NULL) return name_; | 3551 if (name_ != NULL) return name_; |
3514 const int kMaxNameLength = 100; | 3552 const int kMaxNameLength = 100; |
(...skipping 19 matching lines...) Expand all Loading... |
3534 const char* never_nan_nan_name = ""; | 3572 const char* never_nan_nan_name = ""; |
3535 if (never_nan_nan_ && (cc_ == equal || cc_ == not_equal)) { | 3573 if (never_nan_nan_ && (cc_ == equal || cc_ == not_equal)) { |
3536 never_nan_nan_name = "_NO_NAN"; | 3574 never_nan_nan_name = "_NO_NAN"; |
3537 } | 3575 } |
3538 | 3576 |
3539 const char* include_number_compare_name = ""; | 3577 const char* include_number_compare_name = ""; |
3540 if (!include_number_compare_) { | 3578 if (!include_number_compare_) { |
3541 include_number_compare_name = "_NO_NUMBER"; | 3579 include_number_compare_name = "_NO_NUMBER"; |
3542 } | 3580 } |
3543 | 3581 |
| 3582 const char* include_smi_compare_name = ""; |
| 3583 if (!include_smi_compare_) { |
| 3584 include_smi_compare_name = "_NO_SMI"; |
| 3585 } |
| 3586 |
3544 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), | 3587 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), |
3545 "CompareStub_%s%s%s%s", | 3588 "CompareStub_%s%s%s%s%s", |
3546 cc_name, | 3589 cc_name, |
3547 strict_name, | 3590 strict_name, |
3548 never_nan_nan_name, | 3591 never_nan_nan_name, |
3549 include_number_compare_name); | 3592 include_number_compare_name, |
| 3593 include_smi_compare_name); |
3550 return name_; | 3594 return name_; |
3551 } | 3595 } |
3552 | 3596 |
3553 | 3597 |
3554 // ------------------------------------------------------------------------- | 3598 // ------------------------------------------------------------------------- |
3555 // StringCharCodeAtGenerator | 3599 // StringCharCodeAtGenerator |
3556 | 3600 |
3557 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 3601 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
3558 Label flat_string; | 3602 Label flat_string; |
3559 Label ascii_string; | 3603 Label ascii_string; |
(...skipping 1046 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4606 // tagged as a small integer. | 4650 // tagged as a small integer. |
4607 __ bind(&runtime); | 4651 __ bind(&runtime); |
4608 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 4652 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
4609 } | 4653 } |
4610 | 4654 |
4611 #undef __ | 4655 #undef __ |
4612 | 4656 |
4613 } } // namespace v8::internal | 4657 } } // namespace v8::internal |
4614 | 4658 |
4615 #endif // V8_TARGET_ARCH_IA32 | 4659 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |