Update V8 to r5091 as required by WebKit r63859.
Change-Id: I8e35d765e6f6c7f89eccff900e1cabe2d5dd6110
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index fa6efcd..0b2081b 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -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();
@@ -4343,9 +4343,7 @@
__ bind(&powi);
// Load 1.0 into d0.
- __ mov(scratch2, Operand(0x3ff00000));
- __ mov(scratch1, Operand(0));
- __ vmov(d0, scratch1, scratch2);
+ __ vmov(d0, 1.0);
// Get the absolute untagged value of the exponent and use that for the
// calculation.
@@ -4405,9 +4403,7 @@
AVOID_NANS_AND_INFINITIES);
// Load 1.0 into d2.
- __ mov(scratch2, Operand(0x3ff00000));
- __ mov(scratch1, Operand(0));
- __ vmov(d2, scratch1, scratch2);
+ __ vmov(d2, 1.0);
// Calculate the reciprocal of the square root. 1/sqrt(x) = sqrt(1/x).
__ vdiv(d0, d2, d0);
@@ -4764,6 +4760,24 @@
}
+void CodeGenerator::GenerateIsSpecObject(ZoneList<Expression*>* args) {
+ // This generates a fast version of:
+ // (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp' ||
+ // typeof(arg) == function).
+ // It includes undetectable objects (as opposed to IsObject).
+ ASSERT(args->length() == 1);
+ Load(args->at(0));
+ Register value = frame_->PopToRegister();
+ __ tst(value, Operand(kSmiTagMask));
+ false_target()->Branch(eq);
+ // Check that this is an object.
+ __ ldr(value, FieldMemOperand(value, HeapObject::kMapOffset));
+ __ ldrb(value, FieldMemOperand(value, Map::kInstanceTypeOffset));
+ __ cmp(value, Operand(FIRST_JS_OBJECT_TYPE));
+ cc_reg_ = ge;
+}
+
+
void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
// This generates a fast version of:
// (%_ClassOf(arg) === 'Function')
@@ -4874,12 +4888,8 @@
__ jmp(&heapnumber_allocated);
__ bind(&slow_allocate_heapnumber);
- // To allocate a heap number, and ensure that it is not a smi, we
- // call the runtime function FUnaryMinus on 0, returning the double
- // -0.0. A new, distinct heap number is returned each time.
- __ mov(r0, Operand(Smi::FromInt(0)));
- __ push(r0);
- __ CallRuntime(Runtime::kNumberUnaryMinus, 1);
+ // Allocate a heap number.
+ __ CallRuntime(Runtime::kNumberAlloc, 0);
__ mov(r4, Operand(r0));
__ bind(&heapnumber_allocated);
@@ -6976,7 +6986,7 @@
// undefined >= undefined should fail.
__ mov(r0, Operand(LESS));
}
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret();
}
}
}
@@ -6990,7 +7000,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
@@ -7022,14 +7032,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.
}
@@ -7040,43 +7050,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);
}
@@ -7086,34 +7103,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);
@@ -7167,7 +7185,7 @@
} else {
__ mov(r0, Operand(LESS));
}
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret();
__ bind(&neither_is_nan);
}
@@ -7188,11 +7206,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
@@ -7202,11 +7220,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.
@@ -7219,7 +7237,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.
@@ -7227,20 +7250,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.
@@ -7259,12 +7282,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.
@@ -7272,13 +7300,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);
}
@@ -7286,9 +7314,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);
@@ -7296,31 +7329,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();
}
@@ -7442,10 +7475,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;
@@ -7460,7 +7496,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:
@@ -7472,7 +7508,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
@@ -7489,7 +7525,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
@@ -7500,7 +7536,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.
@@ -7512,11 +7548,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;
@@ -7524,8 +7560,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);
@@ -7536,20 +7574,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,
@@ -7558,7 +7596,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) {
@@ -10059,6 +10097,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);
@@ -10075,6 +10116,9 @@
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)) {
strict_name = "_STRICT";
@@ -10091,8 +10135,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);
@@ -10104,8 +10150,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_);