Revision: 5075
Author: [email protected]
Date: Thu Jul 15 02:58:47 2010
Log: Merge fix of negative dictionary probing to 2.2 branch.
The code used to assume that only symbol keys are in
dictionaries. That is not the case.
Also merge in change that got accidentally left out of the 2.2.24
version.
Review URL: http://codereview.chromium.org/3016002
http://code.google.com/p/v8/source/detail?r=5075
Modified:
/branches/2.2/src/arm/codegen-arm.cc
/branches/2.2/src/arm/full-codegen-arm.cc
/branches/2.2/src/arm/stub-cache-arm.cc
/branches/2.2/src/codegen.h
/branches/2.2/src/ia32/codegen-ia32.cc
/branches/2.2/src/ia32/stub-cache-ia32.cc
/branches/2.2/src/version.cc
/branches/2.2/src/x64/codegen-x64.cc
/branches/2.2/src/x64/stub-cache-x64.cc
/branches/2.2/test/mjsunit/call-stub.js
=======================================
--- /branches/2.2/src/arm/codegen-arm.cc Tue Jul 13 13:58:03 2010
+++ /branches/2.2/src/arm/codegen-arm.cc Thu Jul 15 02:58:47 2010
@@ -54,11 +54,15 @@
Condition cc,
bool never_nan_nan);
static void EmitSmiNonsmiComparison(MacroAssembler* masm,
+ Register lhs,
+ Register rhs,
Label* lhs_not_nan,
Label* slow,
bool strict);
static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition
cc);
-static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm);
+static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
+ Register lhs,
+ Register rhs);
static void MultiplyByKnownInt(MacroAssembler* masm,
Register source,
Register destination,
@@ -1404,11 +1408,7 @@
// Perform non-smi comparison by stub.
// CompareStub takes arguments in r0 and r1, returns <0, >0 or 0 in r0.
// We call with 0 args because there are 0 on the stack.
- if (!rhs.is(r0)) {
- __ Swap(rhs, lhs, ip);
- }
-
- CompareStub stub(cc, strict);
+ CompareStub stub(cc, strict, kBothCouldBeNaN, true, lhs, rhs);
frame_->CallStub(&stub, 0);
__ cmp(r0, Operand(0));
exit.Jump();
@@ -6968,7 +6968,7 @@
// undefined >= undefined should fail.
__ mov(r0, Operand(LESS));
}
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret();
}
}
}
@@ -6982,7 +6982,7 @@
} else {
__ mov(r0, Operand(EQUAL)); // Things are <=, >=, ==, ===
themselves.
}
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret();
if (cc != eq || !never_nan_nan) {
// For less and greater we don't have to check for NaN since the
result of
@@ -7014,14 +7014,14 @@
// value if it's a NaN.
if (cc != eq) {
// All-zero means Infinity means equal.
- __ mov(pc, Operand(lr), LeaveCC, eq); // Return equal
+ __ Ret(eq);
if (cc == le) {
__ mov(r0, Operand(GREATER)); // NaN <= NaN should fail.
} else {
__ mov(r0, Operand(LESS)); // NaN >= NaN should fail.
}
}
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret();
}
// No fall through here.
}
@@ -7032,43 +7032,50 @@
// See comment at call site.
static void EmitSmiNonsmiComparison(MacroAssembler* masm,
+ Register lhs,
+ Register rhs,
Label* lhs_not_nan,
Label* slow,
bool strict) {
+ ASSERT((lhs.is(r0) && rhs.is(r1)) ||
+ (lhs.is(r1) && rhs.is(r0)));
+
Label rhs_is_smi;
- __ tst(r0, Operand(kSmiTagMask));
+ __ tst(rhs, Operand(kSmiTagMask));
__ b(eq, &rhs_is_smi);
// Lhs is a Smi. Check whether the rhs is a heap number.
- __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE);
+ __ CompareObjectType(rhs, r4, r4, HEAP_NUMBER_TYPE);
if (strict) {
// If rhs is not a number and lhs is a Smi then strict equality cannot
- // succeed. Return non-equal (r0 is already not zero)
- __ mov(pc, Operand(lr), LeaveCC, ne); // Return.
+ // succeed. Return non-equal
+ // If rhs is r0 then there is already a non zero value in it.
+ if (!rhs.is(r0)) {
+ __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne);
+ }
+ __ Ret(ne);
} else {
// Smi compared non-strictly with a non-Smi non-heap-number. Call
// the runtime.
__ b(ne, slow);
}
- // Lhs (r1) is a smi, rhs (r0) is a number.
+ // Lhs is a smi, rhs is a number.
if (CpuFeatures::IsSupported(VFP3)) {
- // Convert lhs to a double in d7 .
+ // Convert lhs to a double in d7.
CpuFeatures::Scope scope(VFP3);
- __ mov(r7, Operand(r1, ASR, kSmiTagSize));
- __ vmov(s15, r7);
- __ vcvt_f64_s32(d7, s15);
+ __ SmiToDoubleVFPRegister(lhs, d7, r7, s15);
// Load the double from rhs, tagged HeapNumber r0, to d6.
- __ sub(r7, r0, Operand(kHeapObjectTag));
+ __ sub(r7, rhs, Operand(kHeapObjectTag));
__ vldr(d6, r7, HeapNumber::kValueOffset);
} else {
__ push(lr);
// Convert lhs to a double in r2, r3.
- __ mov(r7, Operand(r1));
+ __ mov(r7, Operand(lhs));
ConvertToDoubleStub stub1(r3, r2, r7, r6);
__ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
// Load rhs to a double in r0, r1.
- __ Ldrd(r0, r1, FieldMemOperand(r0, HeapNumber::kValueOffset));
+ __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset));
__ pop(lr);
}
@@ -7078,34 +7085,35 @@
__ bind(&rhs_is_smi);
// Rhs is a smi. Check whether the non-smi lhs is a heap number.
- __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE);
+ __ CompareObjectType(lhs, r4, r4, HEAP_NUMBER_TYPE);
if (strict) {
// If lhs is not a number and rhs is a smi then strict equality cannot
// succeed. Return non-equal.
- __ mov(r0, Operand(1), LeaveCC, ne); // Non-zero indicates not equal.
- __ mov(pc, Operand(lr), LeaveCC, ne); // Return.
+ // If lhs is r0 then there is already a non zero value in it.
+ if (!lhs.is(r0)) {
+ __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne);
+ }
+ __ Ret(ne);
} else {
// Smi compared non-strictly with a non-smi non-heap-number. Call
// the runtime.
__ b(ne, slow);
}
- // Rhs (r0) is a smi, lhs (r1) is a heap number.
+ // Rhs is a smi, lhs is a heap number.
if (CpuFeatures::IsSupported(VFP3)) {
- // Convert rhs to a double in d6 .
CpuFeatures::Scope scope(VFP3);
// Load the double from lhs, tagged HeapNumber r1, to d7.
- __ sub(r7, r1, Operand(kHeapObjectTag));
+ __ sub(r7, lhs, Operand(kHeapObjectTag));
__ vldr(d7, r7, HeapNumber::kValueOffset);
- __ mov(r7, Operand(r0, ASR, kSmiTagSize));
- __ vmov(s13, r7);
- __ vcvt_f64_s32(d6, s13);
+ // Convert rhs to a double in d6 .
+ __ SmiToDoubleVFPRegister(rhs, d6, r7, s13);
} else {
__ push(lr);
// Load lhs to a double in r2, r3.
- __ Ldrd(r2, r3, FieldMemOperand(r1, HeapNumber::kValueOffset));
+ __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset));
// Convert rhs to a double in r0, r1.
- __ mov(r7, Operand(r0));
+ __ mov(r7, Operand(rhs));
ConvertToDoubleStub stub2(r1, r0, r7, r6);
__ Call(stub2.GetCode(), RelocInfo::CODE_TARGET);
__ pop(lr);
@@ -7159,7 +7167,7 @@
} else {
__ mov(r0, Operand(LESS));
}
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret();
__ bind(&neither_is_nan);
}
@@ -7180,11 +7188,11 @@
__ cmp(rhs_mantissa, Operand(lhs_mantissa));
__ orr(r0, rhs_mantissa, Operand(lhs_mantissa), LeaveCC, ne);
// Return non-zero if the numbers are unequal.
- __ mov(pc, Operand(lr), LeaveCC, ne);
+ __ Ret(ne);
__ sub(r0, rhs_exponent, Operand(lhs_exponent), SetCC);
// If exponents are equal then return 0.
- __ mov(pc, Operand(lr), LeaveCC, eq);
+ __ Ret(eq);
// Exponents are unequal. The only way we can return that the numbers
// are equal is if one is -0 and the other is 0. We already dealt
@@ -7194,11 +7202,11 @@
// equal.
__ orr(r4, lhs_mantissa, Operand(lhs_exponent, LSL, kSmiTagSize),
SetCC);
__ mov(r0, Operand(r4), LeaveCC, ne);
- __ mov(pc, Operand(lr), LeaveCC, ne); // Return conditionally.
+ __ Ret(ne);
// Now they are equal if and only if the lhs exponent is zero in its
// low 31 bits.
__ mov(r0, Operand(rhs_exponent, LSL, kSmiTagSize));
- __ mov(pc, Operand(lr));
+ __ Ret();
} else {
// Call a native function to do a comparison between two non-NaNs.
// Call C routine that may not cause GC or other trouble.
@@ -7211,7 +7219,12 @@
// See comment at call site.
-static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm) {
+static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
+ Register lhs,
+ Register rhs) {
+ ASSERT((lhs.is(r0) && rhs.is(r1)) ||
+ (lhs.is(r1) && rhs.is(r0)));
+
// If either operand is a JSObject or an oddball value, then they are
// not equal since their pointers are different.
// There is no test for undetectability in strict equality.
@@ -7219,20 +7232,20 @@
Label first_non_object;
// Get the type of the first operand into r2 and compare it with
// FIRST_JS_OBJECT_TYPE.
- __ CompareObjectType(r0, r2, r2, FIRST_JS_OBJECT_TYPE);
+ __ CompareObjectType(rhs, r2, r2, FIRST_JS_OBJECT_TYPE);
__ b(lt, &first_non_object);
// Return non-zero (r0 is not zero)
Label return_not_equal;
__ bind(&return_not_equal);
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret();
__ bind(&first_non_object);
// Check for oddballs: true, false, null, undefined.
__ cmp(r2, Operand(ODDBALL_TYPE));
__ b(eq, &return_not_equal);
- __ CompareObjectType(r1, r3, r3, FIRST_JS_OBJECT_TYPE);
+ __ CompareObjectType(lhs, r3, r3, FIRST_JS_OBJECT_TYPE);
__ b(ge, &return_not_equal);
// Check for oddballs: true, false, null, undefined.
@@ -7251,12 +7264,17 @@
// See comment at call site.
static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
+ Register lhs,
+ Register rhs,
Label* both_loaded_as_doubles,
Label* not_heap_numbers,
Label* slow) {
- __ CompareObjectType(r0, r3, r2, HEAP_NUMBER_TYPE);
+ ASSERT((lhs.is(r0) && rhs.is(r1)) ||
+ (lhs.is(r1) && rhs.is(r0)));
+
+ __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE);
__ b(ne, not_heap_numbers);
- __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+ __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset));
__ cmp(r2, r3);
__ b(ne, slow); // First was a heap number, second wasn't. Go slow
case.
@@ -7264,13 +7282,13 @@
// for that.
if (CpuFeatures::IsSupported(VFP3)) {
CpuFeatures::Scope scope(VFP3);
- __ sub(r7, r0, Operand(kHeapObjectTag));
+ __ sub(r7, rhs, Operand(kHeapObjectTag));
__ vldr(d6, r7, HeapNumber::kValueOffset);
- __ sub(r7, r1, Operand(kHeapObjectTag));
+ __ sub(r7, lhs, Operand(kHeapObjectTag));
__ vldr(d7, r7, HeapNumber::kValueOffset);
} else {
- __ Ldrd(r2, r3, FieldMemOperand(r1, HeapNumber::kValueOffset));
- __ Ldrd(r0, r1, FieldMemOperand(r0, HeapNumber::kValueOffset));
+ __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset));
+ __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset));
}
__ jmp(both_loaded_as_doubles);
}
@@ -7278,9 +7296,14 @@
// Fast negative check for symbol-to-symbol equality.
static void EmitCheckForSymbolsOrObjects(MacroAssembler* masm,
+ Register lhs,
+ Register rhs,
Label* possible_strings,
Label* not_both_strings) {
- // r2 is object type of r0.
+ ASSERT((lhs.is(r0) && rhs.is(r1)) ||
+ (lhs.is(r1) && rhs.is(r0)));
+
+ // r2 is object type of rhs.
// Ensure that no non-strings have the symbol bit set.
Label object_test;
ASSERT(kSymbolTag != 0);
@@ -7288,31 +7311,31 @@
__ b(ne, &object_test);
__ tst(r2, Operand(kIsSymbolMask));
__ b(eq, possible_strings);
- __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
+ __ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE);
__ b(ge, not_both_strings);
__ tst(r3, Operand(kIsSymbolMask));
__ b(eq, possible_strings);
// Both are symbols. We already checked they weren't the same pointer
// so they are not equal.
- __ mov(r0, Operand(1)); // Non-zero indicates not equal.
- __ mov(pc, Operand(lr)); // Return.
+ __ mov(r0, Operand(NOT_EQUAL));
+ __ Ret();
__ bind(&object_test);
__ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE));
__ b(lt, not_both_strings);
- __ CompareObjectType(r1, r2, r3, FIRST_JS_OBJECT_TYPE);
+ __ CompareObjectType(lhs, r2, r3, FIRST_JS_OBJECT_TYPE);
__ b(lt, not_both_strings);
- // If both objects are undetectable, they are equal. Otherwise, they
+ // If both objects are undetectable, they are equal. Otherwise, they
// are not equal, since they are different objects and an object is not
// equal to undefined.
- __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
+ __ ldr(r3, FieldMemOperand(rhs, HeapObject::kMapOffset));
__ ldrb(r2, FieldMemOperand(r2, Map::kBitFieldOffset));
__ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
__ and_(r0, r2, Operand(r3));
__ and_(r0, r0, Operand(1 << Map::kIsUndetectable));
__ eor(r0, r0, Operand(1 << Map::kIsUndetectable));
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret();
}
@@ -7434,10 +7457,13 @@
}
-// On entry r0 (rhs) and r1 (lhs) are the values to be compared.
+// On entry lhs_ and rhs_ are the values to be compared.
// On exit r0 is 0, positive or negative to indicate the result of
// the comparison.
void CompareStub::Generate(MacroAssembler* masm) {
+ ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
+ (lhs_.is(r1) && rhs_.is(r0)));
+
Label slow; // Call builtin.
Label not_smis, both_loaded_as_doubles, lhs_not_nan;
@@ -7452,7 +7478,7 @@
// be strictly equal if the other is a HeapNumber.
ASSERT_EQ(0, kSmiTag);
ASSERT_EQ(0, Smi::FromInt(0));
- __ and_(r2, r0, Operand(r1));
+ __ and_(r2, lhs_, Operand(rhs_));
__ tst(r2, Operand(kSmiTagMask));
__ b(ne, ¬_smis);
// One operand is a smi. EmitSmiNonsmiComparison generates code that
can:
@@ -7464,7 +7490,7 @@
// comparison. If VFP3 is supported the double values of the numbers
have
// been loaded into d7 and d6. Otherwise, the double values have been
loaded
// into r0, r1, r2, and r3.
- EmitSmiNonsmiComparison(masm, &lhs_not_nan, &slow, strict_);
+ EmitSmiNonsmiComparison(masm, lhs_, rhs_, &lhs_not_nan, &slow, strict_);
__ bind(&both_loaded_as_doubles);
// The arguments have been converted to doubles and stored in d6 and d7,
if
@@ -7481,7 +7507,7 @@
__ mov(r0, Operand(EQUAL), LeaveCC, eq);
__ mov(r0, Operand(LESS), LeaveCC, lt);
__ mov(r0, Operand(GREATER), LeaveCC, gt);
- __ mov(pc, Operand(lr));
+ __ Ret();
__ bind(&nan);
// If one of the sides was a NaN then the v flag is set. Load r0 with
@@ -7492,7 +7518,7 @@
} else {
__ mov(r0, Operand(LESS));
}
- __ mov(pc, Operand(lr));
+ __ Ret();
} else {
// Checks for NaN in the doubles we have loaded. Can return the
answer or
// fall through if neither is a NaN. Also binds lhs_not_nan.
@@ -7504,11 +7530,11 @@
__ bind(¬_smis);
// At this point we know we are dealing with two different objects,
- // and neither of them is a Smi. The objects are in r0 and r1.
+ // and neither of them is a Smi. The objects are in rhs_ and lhs_.
if (strict_) {
// This returns non-equal for some object types, or falls through if it
// was not lucky.
- EmitStrictTwoHeapObjectCompare(masm);
+ EmitStrictTwoHeapObjectCompare(masm, lhs_, rhs_);
}
Label check_for_symbols;
@@ -7516,8 +7542,10 @@
// Check for heap-number-heap-number comparison. Can jump to slow case,
// or load both doubles into r0, r1, r2, r3 and jump to the code that
handles
// that case. If the inputs are not doubles then jumps to
check_for_symbols.
- // In this case r2 will contain the type of r0. Never falls through.
+ // In this case r2 will contain the type of rhs_. Never falls through.
EmitCheckForTwoHeapNumbers(masm,
+ lhs_,
+ rhs_,
&both_loaded_as_doubles,
&check_for_symbols,
&flat_string_check);
@@ -7528,20 +7556,20 @@
if (cc_ == eq && !strict_) {
// Returns an answer for two symbols or two detectable objects.
// Otherwise jumps to string case or not both strings case.
- // Assumes that r2 is the type of r0 on entry.
- EmitCheckForSymbolsOrObjects(masm, &flat_string_check, &slow);
+ // Assumes that r2 is the type of rhs_ on entry.
+ EmitCheckForSymbolsOrObjects(masm, lhs_, rhs_, &flat_string_check,
&slow);
}
// Check for both being sequential ASCII strings, and inline if that is
the
// case.
__ bind(&flat_string_check);
- __ JumpIfNonSmisNotBothSequentialAsciiStrings(r0, r1, r2, r3, &slow);
+ __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs_, rhs_, r2, r3, &slow);
__ IncrementCounter(&Counters::string_compare_native, 1, r2, r3);
StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
- r1,
- r0,
+ lhs_,
+ rhs_,
r2,
r3,
r4,
@@ -7550,7 +7578,7 @@
__ bind(&slow);
- __ Push(r1, r0);
+ __ Push(lhs_, rhs_);
// Figure out which native to call and setup the arguments.
Builtins::JavaScript native;
if (cc_ == eq) {
@@ -10051,6 +10079,9 @@
// Unfortunately you have to run without snapshots to see most of these
// names in the profile since most compare stubs end up in the snapshot.
const char* CompareStub::GetName() {
+ ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
+ (lhs_.is(r1) && rhs_.is(r0)));
+
if (name_ != NULL) return name_;
const int kMaxNameLength = 100;
name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
@@ -10066,6 +10097,9 @@
case ne: cc_name = "NE"; break;
default: cc_name = "UnknownCondition"; break;
}
+
+ const char* lhs_name = lhs_.is(r0) ? "_r0" : "_r1";
+ const char* rhs_name = rhs_.is(r0) ? "_r0" : "_r1";
const char* strict_name = "";
if (strict_ && (cc_ == eq || cc_ == ne)) {
@@ -10083,8 +10117,10 @@
}
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
- "CompareStub_%s%s%s%s",
+ "CompareStub_%s%s%s%s%s%s",
cc_name,
+ lhs_name,
+ rhs_name,
strict_name,
never_nan_nan_name,
include_number_compare_name);
@@ -10096,8 +10132,11 @@
// Encode the three parameters in a unique 16 bit value. To avoid
duplicate
// stubs the never NaN NaN condition is only taken into account if the
// condition is equals.
- ASSERT((static_cast<unsigned>(cc_) >> 28) < (1 << 13));
+ ASSERT((static_cast<unsigned>(cc_) >> 28) < (1 << 12));
+ ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
+ (lhs_.is(r1) && rhs_.is(r0)));
return ConditionField::encode(static_cast<unsigned>(cc_) >> 28)
+ | RegisterField::encode(lhs_.is(r0))
| StrictField::encode(strict_)
| NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false)
| IncludeNumberCompareField::encode(include_number_compare_);
=======================================
--- /branches/2.2/src/arm/full-codegen-arm.cc Tue Jul 13 13:58:03 2010
+++ /branches/2.2/src/arm/full-codegen-arm.cc Thu Jul 15 02:58:47 2010
@@ -822,8 +822,7 @@
// the smi vs. smi case to be handled before it is called.
Label slow_case;
__ ldr(r1, MemOperand(sp, 0)); // Switch value.
- __ mov(r2, r1);
- __ orr(r2, r2, r0);
+ __ orr(r2, r1, r0);
__ tst(r2, Operand(kSmiTagMask));
__ b(ne, &slow_case);
__ cmp(r1, r0);
@@ -832,9 +831,9 @@
__ b(clause->body_target()->entry_label());
__ bind(&slow_case);
- CompareStub stub(eq, true);
+ CompareStub stub(eq, true, kBothCouldBeNaN, true, r1, r0);
__ CallStub(&stub);
- __ tst(r0, r0);
+ __ cmp(r0, Operand(0));
__ b(ne, &next_test);
__ Drop(1); // Switch value is no longer needed.
__ b(clause->body_target()->entry_label());
@@ -3088,7 +3087,7 @@
__ jmp(if_false);
__ bind(&slow_case);
- CompareStub stub(cc, strict);
+ CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0);
__ CallStub(&stub);
__ cmp(r0, Operand(0));
__ b(cc, if_true);
=======================================
--- /branches/2.2/src/arm/stub-cache-arm.cc Tue Jul 13 13:58:03 2010
+++ /branches/2.2/src/arm/stub-cache-arm.cc Thu Jul 15 02:58:47 2010
@@ -176,6 +176,13 @@
__ cmp(entity_name, Operand(Handle<String>(name)));
__ b(eq, miss_label);
+ // Check if the entry name is not a symbol.
+ __ ldr(entity_name, FieldMemOperand(entity_name,
HeapObject::kMapOffset));
+ __ ldrb(entity_name,
+ FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
+ __ tst(entity_name, Operand(kIsSymbolMask));
+ __ b(eq, miss_label);
+
// Restore the properties.
__ ldr(properties,
FieldMemOperand(receiver, JSObject::kPropertiesOffset));
=======================================
--- /branches/2.2/src/codegen.h Wed Jul 7 05:22:46 2010
+++ /branches/2.2/src/codegen.h Thu Jul 15 02:58:47 2010
@@ -461,11 +461,15 @@
CompareStub(Condition cc,
bool strict,
NaNInformation nan_info = kBothCouldBeNaN,
- bool include_number_compare = true) :
+ bool include_number_compare = true,
+ Register lhs = no_reg,
+ Register rhs = no_reg) :
cc_(cc),
strict_(strict),
never_nan_nan_(nan_info == kCantBothBeNaN),
include_number_compare_(include_number_compare),
+ lhs_(lhs),
+ rhs_(rhs),
name_(NULL) { }
void Generate(MacroAssembler* masm);
@@ -483,12 +487,19 @@
// comparison code is used when the number comparison has been inlined,
and
// the stub will be called if one of the operands is not a number.
bool include_number_compare_;
-
- // Encoding of the minor key CCCCCCCCCCCCCCNS.
+ // Register holding the left hand side of the comparison if the stub
gives
+ // a choice, no_reg otherwise.
+ Register lhs_;
+ // Register holding the right hand side of the comparison if the stub
gives
+ // a choice, no_reg otherwise.
+ Register rhs_;
+
+ // Encoding of the minor key CCCCCCCCCCCCRCNS.
class StrictField: public BitField<bool, 0, 1> {};
class NeverNanNanField: public BitField<bool, 1, 1> {};
class IncludeNumberCompareField: public BitField<bool, 2, 1> {};
- class ConditionField: public BitField<int, 3, 13> {};
+ class RegisterField: public BitField<bool, 3, 1> {};
+ class ConditionField: public BitField<int, 4, 12> {};
Major MajorKey() { return Compare; }
@@ -507,11 +518,17 @@
#ifdef DEBUG
void Print() {
PrintF("CompareStub (cc %d), (strict %s), "
- "(never_nan_nan %s), (number_compare %s)\n",
+ "(never_nan_nan %s), (number_compare %s) ",
static_cast<int>(cc_),
strict_ ? "true" : "false",
never_nan_nan_ ? "true" : "false",
include_number_compare_ ? "included" : "not included");
+
+ if (!lhs_.is(no_reg) && !rhs_.is(no_reg)) {
+ PrintF("(lhs r%d), (rhs r%d)\n", lhs_.code(), rhs_.code());
+ } else {
+ PrintF("\n");
+ }
}
#endif
};
=======================================
--- /branches/2.2/src/ia32/codegen-ia32.cc Tue Jul 13 13:58:03 2010
+++ /branches/2.2/src/ia32/codegen-ia32.cc Thu Jul 15 02:58:47 2010
@@ -11635,6 +11635,8 @@
void CompareStub::Generate(MacroAssembler* masm) {
+ ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
+
Label check_unequal_objects, done;
// NOTICE! This code is only reached after a smi-fast-case check, so
@@ -12528,8 +12530,10 @@
// Encode the three parameters in a unique 16 bit value. To avoid
duplicate
// stubs the never NaN NaN condition is only taken into account if the
// condition is equals.
- ASSERT(static_cast<unsigned>(cc_) < (1 << 13));
+ ASSERT(static_cast<unsigned>(cc_) < (1 << 12));
+ ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
return ConditionField::encode(static_cast<unsigned>(cc_))
+ | RegisterField::encode(false) // lhs_ and rhs_ are not used
| StrictField::encode(strict_)
| NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false)
| IncludeNumberCompareField::encode(include_number_compare_);
@@ -12539,6 +12543,8 @@
// Unfortunately you have to run without snapshots to see most of these
// names in the profile since most compare stubs end up in the snapshot.
const char* CompareStub::GetName() {
+ ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
+
if (name_ != NULL) return name_;
const int kMaxNameLength = 100;
name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
=======================================
--- /branches/2.2/src/ia32/stub-cache-ia32.cc Tue Jul 13 13:58:03 2010
+++ /branches/2.2/src/ia32/stub-cache-ia32.cc Thu Jul 15 02:58:47 2010
@@ -184,6 +184,12 @@
// Stop if found the property.
__ cmp(entity_name, Handle<String>(name));
__ j(equal, miss_label, not_taken);
+
+ // Check if the entry name is not a symbol.
+ __ mov(entity_name, FieldOperand(entity_name,
HeapObject::kMapOffset));
+ __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset),
+ kIsSymbolMask);
+ __ j(zero, miss_label, not_taken);
} else {
// Give up probing if still not found the undefined value.
__ j(not_equal, miss_label, not_taken);
=======================================
--- /branches/2.2/src/version.cc Wed Jul 14 07:37:29 2010
+++ /branches/2.2/src/version.cc Thu Jul 15 02:58:47 2010
@@ -35,7 +35,7 @@
#define MAJOR_VERSION 2
#define MINOR_VERSION 2
#define BUILD_NUMBER 24
-#define PATCH_LEVEL 2
+#define PATCH_LEVEL 3
#define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the
=======================================
--- /branches/2.2/src/x64/codegen-x64.cc Wed Jul 14 07:37:29 2010
+++ /branches/2.2/src/x64/codegen-x64.cc Thu Jul 15 02:58:47 2010
@@ -10101,6 +10101,8 @@
void CompareStub::Generate(MacroAssembler* masm) {
+ ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
+
Label check_unequal_objects, done;
// The compare stub returns a positive, negative, or zero 64-bit integer
// value in rax, corresponding to result of comparing the two inputs.
@@ -10949,8 +10951,10 @@
// Encode the three parameters in a unique 16 bit value. To avoid
duplicate
// stubs the never NaN NaN condition is only taken into account if the
// condition is equals.
- ASSERT(static_cast<unsigned>(cc_) < (1 << 13));
+ ASSERT(static_cast<unsigned>(cc_) < (1 << 12));
+ ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
return ConditionField::encode(static_cast<unsigned>(cc_))
+ | RegisterField::encode(false) // lhs_ and rhs_ are not used
| StrictField::encode(strict_)
| NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false)
| IncludeNumberCompareField::encode(include_number_compare_);
@@ -10960,6 +10964,8 @@
// Unfortunately you have to run without snapshots to see most of these
// names in the profile since most compare stubs end up in the snapshot.
const char* CompareStub::GetName() {
+ ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
+
if (name_ != NULL) return name_;
const int kMaxNameLength = 100;
name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
=======================================
--- /branches/2.2/src/x64/stub-cache-x64.cc Tue Jul 13 13:58:03 2010
+++ /branches/2.2/src/x64/stub-cache-x64.cc Thu Jul 15 02:58:47 2010
@@ -164,6 +164,12 @@
// Stop if found the property.
__ Cmp(entity_name, Handle<String>(name));
__ j(equal, miss_label);
+
+ // Check if the entry name is not a symbol.
+ __ movq(entity_name, FieldOperand(entity_name,
HeapObject::kMapOffset));
+ __ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
+ Immediate(kIsSymbolMask));
+ __ j(zero, miss_label);
} else {
// Give up probing if still not found the undefined value.
__ j(not_equal, miss_label);
=======================================
--- /branches/2.2/test/mjsunit/call-stub.js Mon Jul 5 04:01:40 2010
+++ /branches/2.2/test/mjsunit/call-stub.js Thu Jul 15 02:58:47 2010
@@ -49,3 +49,18 @@
}
assertEquals(i < 50 || i >= 70 ? 1 : 2, h.m());
}
+
+
+var nonsymbol = 'wwwww '.split(' ')[0];
+Hash.prototype.wwwww = Hash.prototype.m;
+
+for (var i = 1; i < 100; i++) {
+ if (i == 50) {
+ h[nonsymbol] = function() {
+ return 2;
+ };
+ } else if (i == 70) {
+ delete h[nonsymbol];
+ }
+ assertEquals(i < 50 || i >= 70 ? 1 : 2, h.wwwww());
+}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev