Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 3388005: Make the CompareStub and the UnaryOpStub accept smi inputs.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: x64 and ARM port Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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, &not_identical); 2661 __ j(not_equal, &not_identical);
2625 2662
(...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW
« src/flag-definitions.h ('K') | « src/full-codegen.cc ('k') | src/ia32/codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698