Version 3.19.12
Fixed arguments array access. (Chromium issue 247303)
Fixed bug in LookupForWrite. (Chromium issue 242332)
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@15040 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index 611c74f..06273ca 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -335,9 +335,9 @@
call_generic_code);
__ IncrementCounter(counters->array_function_native(), 1, a3, t0);
// Set up return value, remove receiver from stack and return.
- __ mov(v0, a2);
__ Addu(sp, sp, Operand(kPointerSize));
- __ Ret();
+ __ Ret(USE_DELAY_SLOT);
+ __ mov(v0, a2);
// Check for one argument. Bail out if argument is not smi or if it is
// negative.
@@ -378,9 +378,9 @@
__ IncrementCounter(counters->array_function_native(), 1, a2, t0);
// Set up return value, remove receiver and argument from stack and return.
- __ mov(v0, a3);
__ Addu(sp, sp, Operand(2 * kPointerSize));
- __ Ret();
+ __ Ret(USE_DELAY_SLOT);
+ __ mov(v0, a3);
// Handle construction of an array from a list of arguments.
__ bind(&argc_two_or_more);
@@ -434,8 +434,8 @@
// a3: JSArray
// sp[0]: receiver
__ Addu(sp, sp, Operand(kPointerSize));
+ __ Ret(USE_DELAY_SLOT);
__ mov(v0, a3);
- __ Ret();
__ bind(&has_non_smi_element);
// Double values are handled by the runtime.
@@ -1372,15 +1372,17 @@
Label with_tos_register, unknown_state;
__ Branch(&with_tos_register,
ne, t2, Operand(FullCodeGenerator::NO_REGISTERS));
+ __ Ret(USE_DELAY_SLOT);
+ // Safe to fill delay slot Addu will emit one instruction.
__ Addu(sp, sp, Operand(1 * kPointerSize)); // Remove state.
- __ Ret();
__ bind(&with_tos_register);
__ lw(v0, MemOperand(sp, 1 * kPointerSize));
__ Branch(&unknown_state, ne, t2, Operand(FullCodeGenerator::TOS_REG));
+ __ Ret(USE_DELAY_SLOT);
+ // Safe to fill delay slot Addu will emit one instruction.
__ Addu(sp, sp, Operand(2 * kPointerSize)); // Remove state.
- __ Ret();
__ bind(&unknown_state);
__ stop("no cases left");
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 1a00bc0..3d0577e 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -348,8 +348,8 @@
__ Addu(a3, a3, Operand(Code::kHeaderSize - kHeapObjectTag));
// Return result. The argument function info has been popped already.
+ __ Ret(USE_DELAY_SLOT);
__ sw(a3, FieldMemOperand(v0, JSFunction::kCodeEntryOffset));
- __ Ret();
__ bind(&check_optimized);
@@ -969,9 +969,9 @@
__ sw(scratch_, FieldMemOperand(the_heap_number_,
HeapNumber::kExponentOffset));
__ sll(scratch_, the_int_, 32 - shift_distance);
+ __ Ret(USE_DELAY_SLOT);
__ sw(scratch_, FieldMemOperand(the_heap_number_,
HeapNumber::kMantissaOffset));
- __ Ret();
__ bind(&max_negative_int);
// The max negative int32 is stored as a positive number in the mantissa of
@@ -983,9 +983,9 @@
__ sw(scratch_,
FieldMemOperand(the_heap_number_, HeapNumber::kExponentOffset));
__ mov(scratch_, zero_reg);
+ __ Ret(USE_DELAY_SLOT);
__ sw(scratch_,
FieldMemOperand(the_heap_number_, HeapNumber::kMantissaOffset));
- __ Ret();
}
@@ -1023,6 +1023,8 @@
__ Branch(&return_equal, ne, t4, Operand(ODDBALL_TYPE));
__ LoadRoot(t2, Heap::kUndefinedValueRootIndex);
__ Branch(&return_equal, ne, a0, Operand(t2));
+ ASSERT(is_int16(GREATER) && is_int16(LESS));
+ __ Ret(USE_DELAY_SLOT);
if (cc == le) {
// undefined <= undefined should fail.
__ li(v0, Operand(GREATER));
@@ -1030,13 +1032,13 @@
// undefined >= undefined should fail.
__ li(v0, Operand(LESS));
}
- __ Ret();
}
}
}
__ bind(&return_equal);
-
+ ASSERT(is_int16(GREATER) && is_int16(LESS));
+ __ Ret(USE_DELAY_SLOT);
if (cc == less) {
__ li(v0, Operand(GREATER)); // Things aren't less than themselves.
} else if (cc == greater) {
@@ -1044,7 +1046,6 @@
} else {
__ mov(v0, zero_reg); // Things are <=, >=, ==, === themselves.
}
- __ Ret();
// For less and greater we don't have to check for NaN since the result of
// x < x is false regardless. For the others here is some code to check
@@ -1075,13 +1076,14 @@
if (cc != eq) {
// All-zero means Infinity means equal.
__ Ret(eq, v0, Operand(zero_reg));
+ ASSERT(is_int16(GREATER) && is_int16(LESS));
+ __ Ret(USE_DELAY_SLOT);
if (cc == le) {
__ li(v0, Operand(GREATER)); // NaN <= NaN should fail.
} else {
__ li(v0, Operand(LESS)); // NaN >= NaN should fail.
}
}
- __ Ret();
}
// No fall through here.
@@ -1456,12 +1458,14 @@
__ bind(&nan);
// NaN comparisons always fail.
// Load whatever we need in v0 to make the comparison fail.
+ ASSERT(is_int16(GREATER) && is_int16(LESS));
+ __ Ret(USE_DELAY_SLOT);
if (cc == lt || cc == le) {
__ li(v0, Operand(GREATER));
} else {
__ li(v0, Operand(LESS));
}
- __ Ret();
+
__ bind(¬_smis);
// At this point we know we are dealing with two different objects,
@@ -1725,6 +1729,7 @@
if (mode_ == UNARY_OVERWRITE) {
__ lw(a2, FieldMemOperand(a0, HeapNumber::kExponentOffset));
__ Xor(a2, a2, Operand(HeapNumber::kSignMask)); // Flip sign.
+ __ Ret(USE_DELAY_SLOT);
__ sw(a2, FieldMemOperand(a0, HeapNumber::kExponentOffset));
} else {
Label slow_allocate_heapnumber, heapnumber_allocated;
@@ -1746,9 +1751,9 @@
__ sw(a3, FieldMemOperand(a1, HeapNumber::kMantissaOffset));
__ Xor(a2, a2, Operand(HeapNumber::kSignMask)); // Flip sign.
__ sw(a2, FieldMemOperand(a1, HeapNumber::kExponentOffset));
+ __ Ret(USE_DELAY_SLOT);
__ mov(v0, a1);
}
- __ Ret();
}
@@ -1768,8 +1773,8 @@
__ Branch(&try_float, lt, a2, Operand(zero_reg));
// Tag the result as a smi and we're done.
+ __ Ret(USE_DELAY_SLOT); // SmiTag emits one instruction in delay slot.
__ SmiTag(v0, a1);
- __ Ret();
// Try to store the result in a heap number.
__ bind(&try_float);
@@ -1968,8 +1973,8 @@
// Check that the signed result fits in a Smi.
__ Addu(scratch2, scratch1, Operand(0x40000000));
__ Branch(¬_smi_result, lt, scratch2, Operand(zero_reg));
+ __ Ret(USE_DELAY_SLOT); // SmiTag emits one instruction in delay slot.
__ SmiTag(v0, scratch1);
- __ Ret();
}
break;
case Token::MOD: {
@@ -1991,8 +1996,8 @@
// Check that the signed result fits in a Smi.
__ Addu(scratch1, scratch2, Operand(0x40000000));
__ Branch(¬_smi_result, lt, scratch1, Operand(zero_reg));
+ __ Ret(USE_DELAY_SLOT); // SmiTag emits one instruction in delay slot.
__ SmiTag(v0, scratch2);
- __ Ret();
}
break;
case Token::BIT_OR:
@@ -2026,8 +2031,8 @@
__ And(scratch1, v0, Operand(0xc0000000));
__ Branch(¬_smi_result, ne, scratch1, Operand(zero_reg));
// Smi tag result.
+ __ Ret(USE_DELAY_SLOT); // SmiTag emits one instruction in delay slot.
__ SmiTag(v0);
- __ Ret();
break;
case Token::SHL:
// Remove tags from operands.
@@ -2037,8 +2042,8 @@
// Check that the signed result fits in a Smi.
__ Addu(scratch2, scratch1, Operand(0x40000000));
__ Branch(¬_smi_result, lt, scratch2, Operand(zero_reg));
- __ SmiTag(v0, scratch1);
- __ Ret();
+ __ Ret(USE_DELAY_SLOT);
+ __ SmiTag(v0, scratch1); // SmiTag emits one instruction in delay slot.
break;
default:
UNREACHABLE();
@@ -2240,8 +2245,8 @@
// Check that the *signed* result fits in a smi.
__ Addu(a3, a2, Operand(0x40000000));
__ Branch(&result_not_a_smi, lt, a3, Operand(zero_reg));
+ __ Ret(USE_DELAY_SLOT); // SmiTag emits one instruction in delay slot.
__ SmiTag(v0, a2);
- __ Ret();
// Allocate new heap number for result.
__ bind(&result_not_a_smi);
@@ -2520,8 +2525,8 @@
__ bind(¬_zero);
// Tag the result and return.
- __ SmiTag(v0, scratch1);
- __ Ret();
+ __ Ret(USE_DELAY_SLOT);
+ __ SmiTag(v0, scratch1); // SmiTag emits one instruction.
} else {
// DIV just falls through to allocating a heap number.
}
@@ -2538,9 +2543,10 @@
scratch2,
&call_runtime,
mode_);
+ __ sdc1(f10,
+ FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
+ __ Ret(USE_DELAY_SLOT);
__ mov(v0, heap_number_result);
- __ sdc1(f10, FieldMemOperand(v0, HeapNumber::kValueOffset));
- __ Ret();
// A DIV operation expecting an integer result falls through
// to type transition.
@@ -2660,8 +2666,8 @@
// If not try to return a heap number. (We know the result is an int32.)
__ Branch(&return_heap_number, lt, scratch1, Operand(zero_reg));
// Tag the result and return.
+ __ Ret(USE_DELAY_SLOT); // SmiTag emits one instruction in delay slot.
__ SmiTag(v0, a2);
- __ Ret();
__ bind(&return_heap_number);
heap_number_result = t1;
@@ -2684,9 +2690,10 @@
}
// Store the result.
+ __ sdc1(double_scratch,
+ FieldMemOperand(heap_number_result, HeapNumber::kValueOffset));
+ __ Ret(USE_DELAY_SLOT);
__ mov(v0, heap_number_result);
- __ sdc1(double_scratch, FieldMemOperand(v0, HeapNumber::kValueOffset));
- __ Ret();
break;
}
@@ -4124,8 +4131,8 @@
__ subu(a3, a0, a1);
__ sll(t3, a3, kPointerSizeLog2 - kSmiTagSize);
__ Addu(a3, fp, Operand(t3));
+ __ Ret(USE_DELAY_SLOT);
__ lw(v0, MemOperand(a3, kDisplacement));
- __ Ret();
// Arguments adaptor case: Check index (a1) against actual arguments
// limit found in the arguments adaptor frame. Use unsigned
@@ -4138,8 +4145,8 @@
__ subu(a3, a0, a1);
__ sll(t3, a3, kPointerSizeLog2 - kSmiTagSize);
__ Addu(a3, a2, Operand(t3));
+ __ Ret(USE_DELAY_SLOT);
__ lw(v0, MemOperand(a3, kDisplacement));
- __ Ret();
// Slow-case: Handle non-smi or out-of-bounds access to arguments
// by calling the runtime system.
@@ -6002,16 +6009,18 @@
__ lw(scratch2, FieldMemOperand(right, String::kLengthOffset));
__ Branch(&check_zero_length, eq, length, Operand(scratch2));
__ bind(&strings_not_equal);
+ ASSERT(is_int16(NOT_EQUAL));
+ __ Ret(USE_DELAY_SLOT);
__ li(v0, Operand(Smi::FromInt(NOT_EQUAL)));
- __ Ret();
// Check if the length is zero.
Label compare_chars;
__ bind(&check_zero_length);
STATIC_ASSERT(kSmiTag == 0);
__ Branch(&compare_chars, ne, length, Operand(zero_reg));
+ ASSERT(is_int16(EQUAL));
+ __ Ret(USE_DELAY_SLOT);
__ li(v0, Operand(Smi::FromInt(EQUAL)));
- __ Ret();
// Compare characters.
__ bind(&compare_chars);
@@ -6021,8 +6030,8 @@
&strings_not_equal);
// Characters are equal.
+ __ Ret(USE_DELAY_SLOT);
__ li(v0, Operand(Smi::FromInt(EQUAL)));
- __ Ret();
}
@@ -6540,14 +6549,15 @@
if (GetCondition() == eq) {
// For equality we do not care about the sign of the result.
+ __ Ret(USE_DELAY_SLOT);
__ Subu(v0, a0, a1);
} else {
// Untag before subtracting to avoid handling overflow.
__ SmiUntag(a1);
__ SmiUntag(a0);
+ __ Ret(USE_DELAY_SLOT);
__ Subu(v0, a1, a0);
}
- __ Ret();
__ bind(&miss);
GenerateMiss(masm);
@@ -6608,16 +6618,17 @@
__ BranchF(&fpu_lt, NULL, lt, f0, f2);
// Otherwise it's greater, so just fall thru, and return.
+ ASSERT(is_int16(GREATER) && is_int16(EQUAL) && is_int16(LESS));
+ __ Ret(USE_DELAY_SLOT);
__ li(v0, Operand(GREATER));
- __ Ret();
__ bind(&fpu_eq);
+ __ Ret(USE_DELAY_SLOT);
__ li(v0, Operand(EQUAL));
- __ Ret();
__ bind(&fpu_lt);
+ __ Ret(USE_DELAY_SLOT);
__ li(v0, Operand(LESS));
- __ Ret();
__ bind(&unordered);
__ bind(&generic_stub);
@@ -6676,8 +6687,9 @@
__ mov(v0, right);
// Internalized strings are compared by identity.
__ Ret(ne, left, Operand(right));
+ ASSERT(is_int16(EQUAL));
+ __ Ret(USE_DELAY_SLOT);
__ li(v0, Operand(Smi::FromInt(EQUAL)));
- __ Ret();
__ bind(&miss);
GenerateMiss(masm);
@@ -7561,8 +7573,8 @@
}
masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE);
__ sll(a1, a1, kPointerSizeLog2);
+ __ Ret(USE_DELAY_SLOT);
__ Addu(sp, sp, a1);
- __ Ret();
}
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index fa97ee4..76b9663 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -88,17 +88,6 @@
}
PopulateDeoptimizationData(code);
info()->CommitDependentMaps(code);
-
- for (int i = 0 ; i < transition_maps_.length(); i++) {
- transition_maps_.at(i)->AddDependentCode(
- DependentCode::kTransitionGroup, code);
- }
- if (graph()->depends_on_empty_array_proto_elements()) {
- isolate()->initial_object_prototype()->map()->AddDependentCode(
- DependentCode::kElementsCantBeAddedGroup, code);
- isolate()->initial_array_prototype()->map()->AddDependentCode(
- DependentCode::kElementsCantBeAddedGroup, code);
- }
}
@@ -1143,59 +1132,74 @@
void LCodeGen::DoModI(LModI* instr) {
- Register scratch = scratch0();
- const Register left = ToRegister(instr->left());
- const Register result = ToRegister(instr->result());
+ HMod* hmod = instr->hydrogen();
+ HValue* left = hmod->left();
+ HValue* right = hmod->right();
+ if (hmod->HasPowerOf2Divisor()) {
+ const Register scratch = scratch0();
+ const Register left_reg = ToRegister(instr->left());
+ ASSERT(!left_reg.is(scratch));
+ const Register result_reg = ToRegister(instr->result());
- Label done;
+ // Note: The code below even works when right contains kMinInt.
+ int32_t divisor = Abs(right->GetInteger32Constant());
- if (instr->hydrogen()->HasPowerOf2Divisor()) {
- Register scratch = scratch0();
- ASSERT(!left.is(scratch));
- __ mov(scratch, left);
- int32_t p2constant = HConstant::cast(
- instr->hydrogen()->right())->Integer32Value();
- ASSERT(p2constant != 0);
- // Result always takes the sign of the dividend (left).
- p2constant = abs(p2constant);
+ __ mov(scratch, left_reg);
- Label positive_dividend;
- __ Branch(USE_DELAY_SLOT, &positive_dividend, ge, left, Operand(zero_reg));
- __ subu(result, zero_reg, left);
- __ And(result, result, p2constant - 1);
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
+ Label left_is_not_negative, done;
+ if (left->CanBeNegative()) {
+ __ Branch(USE_DELAY_SLOT, &left_is_not_negative,
+ ge, left_reg, Operand(zero_reg));
+ __ subu(result_reg, zero_reg, left_reg);
+ __ And(result_reg, result_reg, divisor - 1);
+ if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg));
+ }
+ __ Branch(USE_DELAY_SLOT, &done);
+ __ subu(result_reg, zero_reg, result_reg);
}
- __ Branch(USE_DELAY_SLOT, &done);
- __ subu(result, zero_reg, result);
- __ bind(&positive_dividend);
- __ And(result, scratch, p2constant - 1);
+
+ __ bind(&left_is_not_negative);
+ __ And(result_reg, scratch, divisor - 1);
+ __ bind(&done);
+
} else {
- // div runs in the background while we check for special cases.
- Register right = EmitLoadRegister(instr->right(), scratch);
- __ div(left, right);
+ // TODO(svenpanne) Add right->has_fixed_right_arg() case.
- // Check for x % 0.
- if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
- DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg));
+ const Register scratch = scratch0();
+ const Register left_reg = ToRegister(instr->left());
+ const Register result_reg = ToRegister(instr->result());
+
+ // div runs in the background while we check for special cases.
+ Register right_reg = EmitLoadRegister(instr->right(), scratch);
+ __ div(left_reg, right_reg);
+
+ Label done;
+ // Check for x % 0, we have to deopt in this case because we can't return a
+ // NaN.
+ if (right->CanBeZero()) {
+ DeoptimizeIf(eq, instr->environment(), right_reg, Operand(zero_reg));
}
- // Check for (kMinInt % -1).
- if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+ // Check for kMinInt % -1, we have to deopt if we care about -0, because we
+ // can't return that.
+ if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) {
Label left_not_min_int;
- __ Branch(&left_not_min_int, ne, left, Operand(kMinInt));
- DeoptimizeIf(eq, instr->environment(), right, Operand(-1));
+ __ Branch(&left_not_min_int, ne, left_reg, Operand(kMinInt));
+ // TODO(svenpanne) Don't deopt when we don't care about -0.
+ DeoptimizeIf(eq, instr->environment(), right_reg, Operand(-1));
__ bind(&left_not_min_int);
}
- __ Branch(USE_DELAY_SLOT, &done, ge, left, Operand(zero_reg));
- __ mfhi(result);
+ // TODO(svenpanne) Only emit the test/deopt if we have to.
+ __ Branch(USE_DELAY_SLOT, &done, ge, left_reg, Operand(zero_reg));
+ __ mfhi(result_reg);
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
- DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
+ if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg));
}
+ __ bind(&done);
}
- __ bind(&done);
}
@@ -3972,9 +3976,6 @@
}
if (!transition.is_null()) {
- if (transition->CanBeDeprecated()) {
- transition_maps_.Add(transition, info()->zone());
- }
__ li(scratch, Operand(transition));
__ sw(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h
index d96755c..ee01383 100644
--- a/src/mips/lithium-codegen-mips.h
+++ b/src/mips/lithium-codegen-mips.h
@@ -55,7 +55,6 @@
deoptimizations_(4, info->zone()),
deopt_jump_table_(4, info->zone()),
deoptimization_literals_(8, info->zone()),
- transition_maps_(0, info->zone()),
inlined_function_count_(0),
scope_(info->scope()),
status_(UNUSED),
@@ -411,7 +410,6 @@
ZoneList<LEnvironment*> deoptimizations_;
ZoneList<Deoptimizer::JumpTableEntry> deopt_jump_table_;
ZoneList<Handle<Object> > deoptimization_literals_;
- ZoneList<Handle<Map> > transition_maps_;
int inlined_function_count_;
Scope* const scope_;
Status status_;
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index be3279f..ad39c61 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -1364,43 +1364,45 @@
LInstruction* LChunkBuilder::DoMod(HMod* instr) {
+ HValue* left = instr->left();
+ HValue* right = instr->right();
if (instr->representation().IsInteger32()) {
- ASSERT(instr->left()->representation().IsInteger32());
- ASSERT(instr->right()->representation().IsInteger32());
-
- LModI* mod;
+ ASSERT(left->representation().IsInteger32());
+ ASSERT(right->representation().IsInteger32());
if (instr->HasPowerOf2Divisor()) {
- ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
- LOperand* value = UseRegisterAtStart(instr->left());
- mod = new(zone()) LModI(value, UseOrConstant(instr->right()));
+ ASSERT(!right->CanBeZero());
+ LModI* mod = new(zone()) LModI(UseRegisterAtStart(left),
+ UseOrConstant(right));
+ LInstruction* result = DefineAsRegister(mod);
+ return (left->CanBeNegative() &&
+ instr->CheckFlag(HValue::kBailoutOnMinusZero))
+ ? AssignEnvironment(result)
+ : result;
} else {
- LOperand* dividend = UseRegister(instr->left());
- LOperand* divisor = UseRegister(instr->right());
- mod = new(zone()) LModI(dividend,
- divisor,
- TempRegister(),
- FixedTemp(f20),
- FixedTemp(f22));
- }
-
- if (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
- instr->CheckFlag(HValue::kCanBeDivByZero) ||
- instr->CheckFlag(HValue::kCanOverflow)) {
- return AssignEnvironment(DefineAsRegister(mod));
- } else {
- return DefineAsRegister(mod);
+ LModI* mod = new(zone()) LModI(UseRegister(left),
+ UseRegister(right),
+ TempRegister(),
+ FixedTemp(f20),
+ FixedTemp(f22));
+ LInstruction* result = DefineAsRegister(mod);
+ return (right->CanBeZero() ||
+ (left->RangeCanInclude(kMinInt) &&
+ right->RangeCanInclude(-1)) ||
+ instr->CheckFlag(HValue::kBailoutOnMinusZero))
+ ? AssignEnvironment(result)
+ : result;
}
} else if (instr->representation().IsSmiOrTagged()) {
return DoArithmeticT(Token::MOD, instr);
} else {
ASSERT(instr->representation().IsDouble());
- // We call a C function for double modulo. It can't trigger a GC.
- // We need to use fixed result register for the call.
+ // We call a C function for double modulo. It can't trigger a GC. We need
+ // to use fixed result register for the call.
// TODO(fschneider): Allow any register as input registers.
- LOperand* left = UseFixedDouble(instr->left(), f2);
- LOperand* right = UseFixedDouble(instr->right(), f4);
- LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right);
- return MarkAsCall(DefineFixedDouble(result, f2), instr);
+ LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD,
+ UseFixedDouble(left, f2),
+ UseFixedDouble(right, f4));
+ return MarkAsCall(DefineFixedDouble(mod, f2), instr);
}
}
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index 63fde97..b2c78a3 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -337,8 +337,8 @@
__ Branch(miss_label, ne, scratch, Operand(JS_ARRAY_TYPE));
// Load length directly from the JS array.
+ __ Ret(USE_DELAY_SLOT);
__ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
- __ Ret();
}
@@ -384,8 +384,8 @@
support_wrappers ? &check_wrapper : miss);
// Load length directly from the string.
+ __ Ret(USE_DELAY_SLOT);
__ lw(v0, FieldMemOperand(receiver, String::kLengthOffset));
- __ Ret();
if (support_wrappers) {
// Check if the object is a JSValue wrapper.
@@ -395,8 +395,8 @@
// Unwrap the value and check if the wrapped value is a string.
__ lw(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset));
GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss);
+ __ Ret(USE_DELAY_SLOT);
__ lw(v0, FieldMemOperand(scratch1, String::kLengthOffset));
- __ Ret();
}
}
@@ -407,8 +407,8 @@
Register scratch2,
Label* miss_label) {
__ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
+ __ Ret(USE_DELAY_SLOT);
__ mov(v0, scratch1);
- __ Ret();
}
@@ -639,8 +639,8 @@
// Return the value (register v0).
ASSERT(value_reg.is(a0));
__ bind(&exit);
+ __ Ret(USE_DELAY_SLOT);
__ mov(v0, a0);
- __ Ret();
}
@@ -715,8 +715,8 @@
__ sdc1(f4, FieldMemOperand(scratch1, HeapNumber::kValueOffset));
// Return the value (register v0).
ASSERT(value_reg.is(a0));
+ __ Ret(USE_DELAY_SLOT);
__ mov(v0, a0);
- __ Ret();
return;
}
@@ -773,8 +773,8 @@
// Return the value (register v0).
ASSERT(value_reg.is(a0));
__ bind(&exit);
+ __ Ret(USE_DELAY_SLOT);
__ mov(v0, a0);
- __ Ret();
}
@@ -1706,8 +1706,7 @@
if (argc == 0) {
// Nothing to do, just return the length.
__ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
} else {
Label call_builtin;
if (argc == 1) { // Otherwise fall through to call the builtin.
@@ -1755,8 +1754,7 @@
__ sw(t0, MemOperand(end_elements));
// Check for a smi.
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
__ bind(&check_double);
@@ -1788,8 +1786,7 @@
__ sw(a0, FieldMemOperand(receiver, JSArray::kLengthOffset));
// Check for a smi.
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
__ bind(&with_write_barrier);
@@ -1855,8 +1852,7 @@
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
__ bind(&attempt_to_grow_elements);
// v0: array's length + 1.
@@ -1911,8 +1907,7 @@
__ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset));
// Elements are in new space, so write barrier is not required.
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
}
__ bind(&call_builtin);
__ TailCallExternalReference(
@@ -1991,13 +1986,11 @@
// Fill with the hole.
__ sw(t2, FieldMemOperand(elements, FixedArray::kHeaderSize));
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
__ bind(&return_undefined);
__ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
__ bind(&call_builtin);
__ TailCallExternalReference(
@@ -2072,8 +2065,7 @@
index_out_of_range_label,
STRING_INDEX_IS_NUMBER);
generator.GenerateFast(masm());
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
StubRuntimeCallHelper call_helper;
generator.GenerateSlow(masm(), call_helper);
@@ -2081,8 +2073,7 @@
if (index_out_of_range.is_linked()) {
__ bind(&index_out_of_range);
__ LoadRoot(v0, Heap::kNanValueRootIndex);
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
}
__ bind(&miss);
@@ -2155,8 +2146,7 @@
index_out_of_range_label,
STRING_INDEX_IS_NUMBER);
generator.GenerateFast(masm());
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
StubRuntimeCallHelper call_helper;
generator.GenerateSlow(masm(), call_helper);
@@ -2164,8 +2154,7 @@
if (index_out_of_range.is_linked()) {
__ bind(&index_out_of_range);
__ LoadRoot(v0, Heap::kempty_stringRootIndex);
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
}
__ bind(&miss);
@@ -2231,8 +2220,7 @@
StringCharFromCodeGenerator generator(code, v0);
generator.GenerateFast(masm());
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
StubRuntimeCallHelper call_helper;
generator.GenerateSlow(masm(), call_helper);
@@ -2295,8 +2283,7 @@
// If the argument is a smi, just return.
STATIC_ASSERT(kSmiTag == 0);
__ And(t0, v0, Operand(kSmiTagMask));
- __ Drop(argc + 1, eq, t0, Operand(zero_reg));
- __ Ret(eq, t0, Operand(zero_reg));
+ __ DropAndRet(argc + 1, eq, t0, Operand(zero_reg));
__ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK);
@@ -2361,8 +2348,7 @@
// Restore FCSR and return.
__ ctc1(a3, FCSR);
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
__ bind(&wont_fit_smi);
// Restore FCSR and fall to slow case.
@@ -2441,8 +2427,7 @@
__ Branch(&slow, lt, v0, Operand(zero_reg));
// Smi case done.
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
// Check if the argument is a heap number and load its exponent and
// sign.
@@ -2455,8 +2440,7 @@
Label negative_sign;
__ And(t0, a1, Operand(HeapNumber::kSignMask));
__ Branch(&negative_sign, ne, t0, Operand(zero_reg));
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
// If the argument is negative, clear the sign, and return a new
// number.
@@ -2467,8 +2451,7 @@
__ AllocateHeapNumber(v0, t0, t1, t2, &slow);
__ sw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset));
__ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset));
- __ Drop(argc + 1);
- __ Ret();
+ __ DropAndRet(argc + 1);
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
@@ -3066,8 +3049,8 @@
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3);
+ __ Ret(USE_DELAY_SLOT);
__ mov(v0, t0);
- __ Ret();
// Return the generated code.
return GetICCode(kind(), Code::NORMAL, name);
@@ -3338,8 +3321,8 @@
}
// Entry registers are intact, a0 holds the value which is the return value.
+ __ Ret(USE_DELAY_SLOT);
__ mov(v0, a0);
- __ Ret();
if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
// a3: external array.
@@ -3406,8 +3389,8 @@
// Entry registers are intact, a0 holds the value
// which is the return value.
+ __ Ret(USE_DELAY_SLOT);
__ mov(v0, a0);
- __ Ret();
}
// Slow case, key and receiver still in a0 and a1.
@@ -3568,8 +3551,8 @@
// Increment the length of the array.
__ li(length_reg, Operand(Smi::FromInt(1)));
+ __ Ret(USE_DELAY_SLOT);
__ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
- __ Ret();
__ bind(&check_capacity);
// Check for cow elements, in general they are not handled by this stub
@@ -3733,9 +3716,9 @@
// Increment the length of the array.
__ li(length_reg, Operand(Smi::FromInt(1)));
__ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
+ __ Ret(USE_DELAY_SLOT);
__ lw(elements_reg,
FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
- __ Ret();
__ bind(&check_capacity);
// Make sure that the backing store can hold additional elements.