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

Side by Side Diff: src/arm/codegen-arm.cc

Issue 524059: Speed up compares with characters ie single-character strings.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 11 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
« no previous file with comments | « no previous file | src/codegen.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 26 matching lines...) Expand all
37 #include "scopes.h" 37 #include "scopes.h"
38 38
39 39
40 namespace v8 { 40 namespace v8 {
41 namespace internal { 41 namespace internal {
42 42
43 #define __ ACCESS_MASM(masm_) 43 #define __ ACCESS_MASM(masm_)
44 44
45 static void EmitIdenticalObjectComparison(MacroAssembler* masm, 45 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
46 Label* slow, 46 Label* slow,
47 Condition cc); 47 Condition cc,
48 bool never_nan_nan);
48 static void EmitSmiNonsmiComparison(MacroAssembler* masm, 49 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
49 Label* rhs_not_nan, 50 Label* rhs_not_nan,
50 Label* slow, 51 Label* slow,
51 bool strict); 52 bool strict);
52 static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc); 53 static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc);
53 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm); 54 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm);
54 static void MultiplyByKnownInt(MacroAssembler* masm, 55 static void MultiplyByKnownInt(MacroAssembler* masm,
55 Register source, 56 Register source,
56 Register destination, 57 Register destination,
57 int known_int); 58 int known_int);
(...skipping 4533 matching lines...) Expand 10 before | Expand all | Expand 10 after
4591 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset)); 4592 __ str(ip, FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset));
4592 __ Ret(); 4593 __ Ret();
4593 } 4594 }
4594 4595
4595 4596
4596 // Handle the case where the lhs and rhs are the same object. 4597 // Handle the case where the lhs and rhs are the same object.
4597 // Equality is almost reflexive (everything but NaN), so this is a test 4598 // Equality is almost reflexive (everything but NaN), so this is a test
4598 // for "identity and not NaN". 4599 // for "identity and not NaN".
4599 static void EmitIdenticalObjectComparison(MacroAssembler* masm, 4600 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
4600 Label* slow, 4601 Label* slow,
4601 Condition cc) { 4602 Condition cc,
4603 bool never_nan_nan) {
4602 Label not_identical; 4604 Label not_identical;
4605 Label heap_number, return_equal;
4606 Register exp_mask_reg = r5;
4603 __ cmp(r0, Operand(r1)); 4607 __ cmp(r0, Operand(r1));
4604 __ b(ne, &not_identical); 4608 __ b(ne, &not_identical);
4605 4609
4606 Register exp_mask_reg = r5; 4610 // The two objects are identical. If we know that one of them isn't NaN then
4607 __ mov(exp_mask_reg, Operand(HeapNumber::kExponentMask)); 4611 // we now know they test equal.
4612 if (cc != eq || !never_nan_nan) {
4613 __ mov(exp_mask_reg, Operand(HeapNumber::kExponentMask));
4608 4614
4609 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), 4615 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(),
4610 // so we do the second best thing - test it ourselves. 4616 // so we do the second best thing - test it ourselves.
4611 Label heap_number, return_equal; 4617 // They are both equal and they are not both Smis so both of them are not
4612 // They are both equal and they are not both Smis so both of them are not 4618 // Smis. If it's not a heap number, then return equal.
4613 // Smis. If it's not a heap number, then return equal. 4619 if (cc == lt || cc == gt) {
4614 if (cc == lt || cc == gt) { 4620 __ CompareObjectType(r0, r4, r4, FIRST_JS_OBJECT_TYPE);
4615 __ CompareObjectType(r0, r4, r4, FIRST_JS_OBJECT_TYPE);
4616 __ b(ge, slow);
4617 } else {
4618 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE);
4619 __ b(eq, &heap_number);
4620 // Comparing JS objects with <=, >= is complicated.
4621 if (cc != eq) {
4622 __ cmp(r4, Operand(FIRST_JS_OBJECT_TYPE));
4623 __ b(ge, slow); 4621 __ b(ge, slow);
4624 // Normally here we fall through to return_equal, but undefined is 4622 } else {
4625 // special: (undefined == undefined) == true, but (undefined <= undefined) 4623 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE);
4626 // == false! See ECMAScript 11.8.5. 4624 __ b(eq, &heap_number);
4627 if (cc == le || cc == ge) { 4625 // Comparing JS objects with <=, >= is complicated.
4628 __ cmp(r4, Operand(ODDBALL_TYPE)); 4626 if (cc != eq) {
4629 __ b(ne, &return_equal); 4627 __ cmp(r4, Operand(FIRST_JS_OBJECT_TYPE));
4630 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 4628 __ b(ge, slow);
4631 __ cmp(r0, Operand(r2)); 4629 // Normally here we fall through to return_equal, but undefined is
4632 __ b(ne, &return_equal); 4630 // special: (undefined == undefined) == true, but
4633 if (cc == le) { 4631 // (undefined <= undefined) == false! See ECMAScript 11.8.5.
4634 __ mov(r0, Operand(GREATER)); // undefined <= undefined should fail. 4632 if (cc == le || cc == ge) {
4635 } else { 4633 __ cmp(r4, Operand(ODDBALL_TYPE));
4636 __ mov(r0, Operand(LESS)); // undefined >= undefined should fail. 4634 __ b(ne, &return_equal);
4635 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
4636 __ cmp(r0, Operand(r2));
4637 __ b(ne, &return_equal);
4638 if (cc == le) {
4639 // undefined <= undefined should fail.
4640 __ mov(r0, Operand(GREATER));
4641 } else {
4642 // undefined >= undefined should fail.
4643 __ mov(r0, Operand(LESS));
4644 }
4645 __ mov(pc, Operand(lr)); // Return.
4637 } 4646 }
4638 __ mov(pc, Operand(lr)); // Return.
4639 } 4647 }
4640 } 4648 }
4641 } 4649 }
4650
4642 __ bind(&return_equal); 4651 __ bind(&return_equal);
4643 if (cc == lt) { 4652 if (cc == lt) {
4644 __ mov(r0, Operand(GREATER)); // Things aren't less than themselves. 4653 __ mov(r0, Operand(GREATER)); // Things aren't less than themselves.
4645 } else if (cc == gt) { 4654 } else if (cc == gt) {
4646 __ mov(r0, Operand(LESS)); // Things aren't greater than themselves. 4655 __ mov(r0, Operand(LESS)); // Things aren't greater than themselves.
4647 } else { 4656 } else {
4648 __ mov(r0, Operand(0)); // Things are <=, >=, ==, === themselves. 4657 __ mov(r0, Operand(0)); // Things are <=, >=, ==, === themselves.
4649 } 4658 }
4650 __ mov(pc, Operand(lr)); // Return. 4659 __ mov(pc, Operand(lr)); // Return.
4651 4660
4652 // For less and greater we don't have to check for NaN since the result of 4661 if (cc != eq || !never_nan_nan) {
4653 // x < x is false regardless. For the others here is some code to check 4662 // For less and greater we don't have to check for NaN since the result of
4654 // for NaN. 4663 // x < x is false regardless. For the others here is some code to check
4655 if (cc != lt && cc != gt) { 4664 // for NaN.
4656 __ bind(&heap_number); 4665 if (cc != lt && cc != gt) {
4657 // It is a heap number, so return non-equal if it's NaN and equal if it's 4666 __ bind(&heap_number);
4658 // not NaN. 4667 // It is a heap number, so return non-equal if it's NaN and equal if it's
4659 // The representation of NaN values has all exponent bits (52..62) set, 4668 // not NaN.
4660 // and not all mantissa bits (0..51) clear. 4669 // The representation of NaN values has all exponent bits (52..62) set,
4661 // Read top bits of double representation (second word of value). 4670 // and not all mantissa bits (0..51) clear.
4662 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 4671 // Read top bits of double representation (second word of value).
4663 // Test that exponent bits are all set. 4672 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
4664 __ and_(r3, r2, Operand(exp_mask_reg)); 4673 // Test that exponent bits are all set.
4665 __ cmp(r3, Operand(exp_mask_reg)); 4674 __ and_(r3, r2, Operand(exp_mask_reg));
4666 __ b(ne, &return_equal); 4675 __ cmp(r3, Operand(exp_mask_reg));
4676 __ b(ne, &return_equal);
4667 4677
4668 // Shift out flag and all exponent bits, retaining only mantissa. 4678 // Shift out flag and all exponent bits, retaining only mantissa.
4669 __ mov(r2, Operand(r2, LSL, HeapNumber::kNonMantissaBitsInTopWord)); 4679 __ mov(r2, Operand(r2, LSL, HeapNumber::kNonMantissaBitsInTopWord));
4670 // Or with all low-bits of mantissa. 4680 // Or with all low-bits of mantissa.
4671 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 4681 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
4672 __ orr(r0, r3, Operand(r2), SetCC); 4682 __ orr(r0, r3, Operand(r2), SetCC);
4673 // For equal we already have the right value in r0: Return zero (equal) 4683 // For equal we already have the right value in r0: Return zero (equal)
4674 // if all bits in mantissa are zero (it's an Infinity) and non-zero if not 4684 // if all bits in mantissa are zero (it's an Infinity) and non-zero if not
4675 // (it's a NaN). For <= and >= we need to load r0 with the failing value 4685 // (it's a NaN). For <= and >= we need to load r0 with the failing value
4676 // if it's a NaN. 4686 // if it's a NaN.
4677 if (cc != eq) { 4687 if (cc != eq) {
4678 // All-zero means Infinity means equal. 4688 // All-zero means Infinity means equal.
4679 __ mov(pc, Operand(lr), LeaveCC, eq); // Return equal 4689 __ mov(pc, Operand(lr), LeaveCC, eq); // Return equal
4680 if (cc == le) { 4690 if (cc == le) {
4681 __ mov(r0, Operand(GREATER)); // NaN <= NaN should fail. 4691 __ mov(r0, Operand(GREATER)); // NaN <= NaN should fail.
4682 } else { 4692 } else {
4683 __ mov(r0, Operand(LESS)); // NaN >= NaN should fail. 4693 __ mov(r0, Operand(LESS)); // NaN >= NaN should fail.
4694 }
4684 } 4695 }
4696 __ mov(pc, Operand(lr)); // Return.
4685 } 4697 }
4686 __ mov(pc, Operand(lr)); // Return. 4698 // No fall through here.
4687 } 4699 }
4688 // No fall through here.
4689 4700
4690 __ bind(&not_identical); 4701 __ bind(&not_identical);
4691 } 4702 }
4692 4703
4693 4704
4694 // See comment at call site. 4705 // See comment at call site.
4695 static void EmitSmiNonsmiComparison(MacroAssembler* masm, 4706 static void EmitSmiNonsmiComparison(MacroAssembler* masm,
4696 Label* rhs_not_nan, 4707 Label* rhs_not_nan,
4697 Label* slow, 4708 Label* slow,
4698 bool strict) { 4709 bool strict) {
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
4904 __ ldr(r3, FieldMemOperand(r1, HeapNumber::kValueOffset + kPointerSize)); 4915 __ ldr(r3, FieldMemOperand(r1, HeapNumber::kValueOffset + kPointerSize));
4905 __ ldr(r1, FieldMemOperand(r0, HeapNumber::kValueOffset + kPointerSize)); 4916 __ ldr(r1, FieldMemOperand(r0, HeapNumber::kValueOffset + kPointerSize));
4906 __ ldr(r0, FieldMemOperand(r0, HeapNumber::kValueOffset)); 4917 __ ldr(r0, FieldMemOperand(r0, HeapNumber::kValueOffset));
4907 __ jmp(both_loaded_as_doubles); 4918 __ jmp(both_loaded_as_doubles);
4908 } 4919 }
4909 4920
4910 4921
4911 // Fast negative check for symbol-to-symbol equality. 4922 // Fast negative check for symbol-to-symbol equality.
4912 static void EmitCheckForSymbols(MacroAssembler* masm, Label* slow) { 4923 static void EmitCheckForSymbols(MacroAssembler* masm, Label* slow) {
4913 // r2 is object type of r0. 4924 // r2 is object type of r0.
4914 __ tst(r2, Operand(kIsNotStringMask)); 4925 // Ensure that no non-strings have the symbol bit set.
4915 __ b(ne, slow); 4926 ASSERT(kNotStringTag + kIsSymbolMask > LAST_TYPE);
4927 ASSERT(kSymbolTag != 0);
4916 __ tst(r2, Operand(kIsSymbolMask)); 4928 __ tst(r2, Operand(kIsSymbolMask));
4917 __ b(eq, slow); 4929 __ b(eq, slow);
4918 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); 4930 ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
4919 __ b(ge, slow); 4931 ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
4920 __ tst(r3, Operand(kIsSymbolMask)); 4932 __ tst(r3, Operand(kIsSymbolMask));
4921 __ b(eq, slow); 4933 __ b(eq, slow);
4922 4934
4923 // Both are symbols. We already checked they weren't the same pointer 4935 // Both are symbols. We already checked they weren't the same pointer
4924 // so they are not equal. 4936 // so they are not equal.
4925 __ mov(r0, Operand(1)); // Non-zero indicates not equal. 4937 __ mov(r0, Operand(1)); // Non-zero indicates not equal.
4926 __ mov(pc, Operand(lr)); // Return. 4938 __ mov(pc, Operand(lr)); // Return.
4927 } 4939 }
4928 4940
4929 4941
4930 // On entry r0 and r1 are the things to be compared. On exit r0 is 0, 4942 // On entry r0 and r1 are the things to be compared. On exit r0 is 0,
4931 // positive or negative to indicate the result of the comparison. 4943 // positive or negative to indicate the result of the comparison.
4932 void CompareStub::Generate(MacroAssembler* masm) { 4944 void CompareStub::Generate(MacroAssembler* masm) {
4933 Label slow; // Call builtin. 4945 Label slow; // Call builtin.
4934 Label not_smis, both_loaded_as_doubles, rhs_not_nan; 4946 Label not_smis, both_loaded_as_doubles, rhs_not_nan;
4935 4947
4936 // NOTICE! This code is only reached after a smi-fast-case check, so 4948 // NOTICE! This code is only reached after a smi-fast-case check, so
4937 // it is certain that at least one operand isn't a smi. 4949 // it is certain that at least one operand isn't a smi.
4938 4950
4939 // Handle the case where the objects are identical. Either returns the answer 4951 // Handle the case where the objects are identical. Either returns the answer
4940 // or goes to slow. Only falls through if the objects were not identical. 4952 // or goes to slow. Only falls through if the objects were not identical.
4941 EmitIdenticalObjectComparison(masm, &slow, cc_); 4953 EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_);
4942 4954
4943 // If either is a Smi (we know that not both are), then they can only 4955 // If either is a Smi (we know that not both are), then they can only
4944 // be strictly equal if the other is a HeapNumber. 4956 // be strictly equal if the other is a HeapNumber.
4945 ASSERT_EQ(0, kSmiTag); 4957 ASSERT_EQ(0, kSmiTag);
4946 ASSERT_EQ(0, Smi::FromInt(0)); 4958 ASSERT_EQ(0, Smi::FromInt(0));
4947 __ and_(r2, r0, Operand(r1)); 4959 __ and_(r2, r0, Operand(r1));
4948 __ tst(r2, Operand(kSmiTagMask)); 4960 __ tst(r2, Operand(kSmiTagMask));
4949 __ b(ne, &not_smis); 4961 __ b(ne, &not_smis);
4950 // One operand is a smi. EmitSmiNonsmiComparison generates code that can: 4962 // One operand is a smi. EmitSmiNonsmiComparison generates code that can:
4951 // 1) Return the answer. 4963 // 1) Return the answer.
(...skipping 1528 matching lines...) Expand 10 before | Expand all | Expand 10 after
6480 // Slow-case: Non-function called. 6492 // Slow-case: Non-function called.
6481 __ bind(&slow); 6493 __ bind(&slow);
6482 __ mov(r0, Operand(argc_)); // Setup the number of arguments. 6494 __ mov(r0, Operand(argc_)); // Setup the number of arguments.
6483 __ mov(r2, Operand(0)); 6495 __ mov(r2, Operand(0));
6484 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); 6496 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
6485 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), 6497 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)),
6486 RelocInfo::CODE_TARGET); 6498 RelocInfo::CODE_TARGET);
6487 } 6499 }
6488 6500
6489 6501
6502 const char* CompareStub::GetName() {
6503 switch(cc_) {
6504 case lt: return "CompareStub_LT";
6505 case gt: return "CompareStub_GT";
6506 case le: return "CompareStub_LE";
6507 case ge: return "CompareStub_GE";
6508 case ne: {
6509 if (strict_) {
6510 if (never_nan_nan_) {
6511 return "CompareStub_NE_STRICT_NO_NAN";
6512 } else {
6513 return "CompareStub_NE_STRICT";
6514 }
6515 } else {
6516 if (never_nan_nan_) {
6517 return "CompareStub_NE_NO_NAN";
6518 } else {
6519 return "CompareStub_NE";
6520 }
6521 }
6522 }
6523 case eq: {
6524 if (strict_) {
6525 if (never_nan_nan_) {
6526 return "CompareStub_EQ_STRICT_NO_NAN";
6527 } else {
6528 return "CompareStub_EQ_STRICT";
6529 }
6530 } else {
6531 if (never_nan_nan_) {
6532 return "CompareStub_EQ_NO_NAN";
6533 } else {
6534 return "CompareStub_EQ";
6535 }
6536 }
6537 }
6538 default: return "CompareStub";
6539 }
6540 }
6541
6542
6490 int CompareStub::MinorKey() { 6543 int CompareStub::MinorKey() {
6491 // Encode the two parameters in a unique 16 bit value. 6544 // Encode the three parameters in a unique 16 bit value.
6492 ASSERT(static_cast<unsigned>(cc_) >> 28 < (1 << 15)); 6545 ASSERT(static_cast<unsigned>(cc_) < (1 << 14));
6493 return (static_cast<unsigned>(cc_) >> 27) | (strict_ ? 1 : 0); 6546 int nnn_value = (never_nan_nan_ ? 2 : 0);
6547 if (cc_ != eq) nnn_value = 0; // Avoid duplicate stubs.
6548 return (static_cast<unsigned>(cc_) >> 26) | nnn_value | (strict_ ? 1 : 0);
6494 } 6549 }
6495 6550
6496 6551
6497 #undef __ 6552 #undef __
6498 6553
6499 } } // namespace v8::internal 6554 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/codegen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698