Author: [EMAIL PROTECTED]
Date: Thu Oct 9 23:26:35 2008
New Revision: 481
Modified:
branches/bleeding_edge/src/codegen-ia32.cc
branches/bleeding_edge/src/runtime.js
Log:
Make strict equality checks faster on IA32 by doing
more work in the CompareStub. I'll port this to ARM
once I'm satisfied with the performance improvements.
Review URL: http://codereview.chromium.org/7014
Modified: branches/bleeding_edge/src/codegen-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/codegen-ia32.cc (original)
+++ branches/bleeding_edge/src/codegen-ia32.cc Thu Oct 9 23:26:35 2008
@@ -1127,9 +1127,8 @@
__ pop(edx);
}
+ // Check for the smi case.
Label is_smi, done;
- CompareStub stub(cc, strict);
-
__ mov(ecx, Operand(eax));
__ or_(ecx, Operand(edx));
__ test(ecx, Immediate(kSmiTagMask));
@@ -1137,8 +1136,13 @@
// When non-smi, call out to the compare stub. "parameters" setup by
// calling code in edx and eax and "result" is returned in the flags.
+ CompareStub stub(cc, strict);
__ CallStub(&stub);
- __ cmp(eax, 0);
+ if (cc == equal) {
+ __ test(eax, Operand(eax));
+ } else {
+ __ cmp(eax, 0);
+ }
__ jmp(&done);
// Test smi equality by pointer comparison.
@@ -4484,6 +4488,73 @@
void CompareStub::Generate(MacroAssembler* masm) {
Label call_builtin, done;
+
+ // If we're doing a strict equality comparison, we generate code
+ // to do fast comparison for objects and oddballs. Numbers and
+ // strings still go through the usual slow-case code.
+ if (strict_) {
+ Label slow;
+ __ test(eax, Immediate(kSmiTagMask));
+ __ j(zero, &slow);
+
+ // Get the type of the first operand.
+ __ mov(ecx, FieldOperand(eax, HeapObject::kMapOffset));
+ __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+
+ // If the first object is an object, we do pointer comparison.
+ ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
+ Label non_object;
+ __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
+ __ j(less, &non_object);
+ __ sub(eax, Operand(edx));
+ __ ret(0);
+
+ // Check for oddballs: true, false, null, undefined.
+ __ bind(&non_object);
+ __ cmp(ecx, ODDBALL_TYPE);
+ __ j(not_equal, &slow);
+
+ // If the oddball isn't undefined, we do pointer comparison. For
+ // the undefined value, we have to be careful and check for
+ // 'undetectable' objects too.
+ Label undefined;
+ __ cmp(Operand(eax), Immediate(Factory::undefined_value()));
+ __ j(equal, &undefined);
+ __ sub(eax, Operand(edx));
+ __ ret(0);
+
+ // Undefined case: If the other operand isn't undefined too, we
+ // have to check if it's 'undetectable'.
+ Label check_undetectable;
+ __ bind(&undefined);
+ __ cmp(Operand(edx), Immediate(Factory::undefined_value()));
+ __ j(not_equal, &check_undetectable);
+ __ Set(eax, Immediate(0));
+ __ ret(0);
+
+ // Check for undetectability of the other operand.
+ Label not_strictly_equal;
+ __ bind(&check_undetectable);
+ __ test(edx, Immediate(kSmiTagMask));
+ __ j(zero, ¬_strictly_equal);
+ __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
+ __ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset));
+ __ and_(ecx, 1 << Map::kIsUndetectable);
+ __ cmp(ecx, 1 << Map::kIsUndetectable);
+ __ j(not_equal, ¬_strictly_equal);
+ __ Set(eax, Immediate(0));
+ __ ret(0);
+
+ // No cigar: Objects aren't strictly equal. Register eax contains
+ // a non-smi value so it can't be 0. Just return.
+ ASSERT(kHeapTag != 0);
+ __ bind(¬_strictly_equal);
+ __ ret(0);
+
+ // Fall through to the general case.
+ __ bind(&slow);
+ }
+
// Save the return address (and get it off the stack).
__ pop(ecx);
Modified: branches/bleeding_edge/src/runtime.js
==============================================================================
--- branches/bleeding_edge/src/runtime.js (original)
+++ branches/bleeding_edge/src/runtime.js Thu Oct 9 23:26:35 2008
@@ -91,26 +91,23 @@
// ECMA-262, section 11.9.4, page 56.
function STRICT_EQUALS(x) {
- if (IS_NUMBER(this)) {
- if (!IS_NUMBER(x)) return 1; // not equal
- return %NumberEquals(this, x);
- }
-
if (IS_STRING(this)) {
if (!IS_STRING(x)) return 1; // not equal
return %StringEquals(this, x);
- }
+ }
- if (IS_BOOLEAN(this)) {
- if (!IS_BOOLEAN(x)) return 1; // not equal
- if (this) return x ? 0 : 1;
- else return x ? 1 : 0;
- }
+ if (IS_NUMBER(this)) {
+ if (!IS_NUMBER(x)) return 1; // not equal
+ return %NumberEquals(this, x);
+ }
- if (IS_UNDEFINED(this)) { // both undefined and undetectable
+ if (IS_UNDEFINED(this)) {
+ // Both undefined and undetectable.
return IS_UNDEFINED(x) ? 0 : 1;
}
+ // Objects, null, booleans and functions are all that's left.
+ // They can all be compared with a simple identity check.
return %_ObjectEquals(this, x) ? 0 : 1;
}
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---