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

Side by Side Diff: src/mips/lithium-codegen-mips.cc

Issue 196133017: Experimental parser: merge r19949 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 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 | « src/mips/lithium-codegen-mips.h ('k') | src/mips/lithium-mips.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 2012 the V8 project authors. All rights reserved.7 1 // Copyright 2012 the V8 project authors. All rights reserved.7
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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 139 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
140 __ stop("stop_at"); 140 __ stop("stop_at");
141 } 141 }
142 #endif 142 #endif
143 143
144 // a1: Callee's JS function. 144 // a1: Callee's JS function.
145 // cp: Callee's context. 145 // cp: Callee's context.
146 // fp: Caller's frame pointer. 146 // fp: Caller's frame pointer.
147 // lr: Caller's pc. 147 // lr: Caller's pc.
148 148
149 // Classic mode functions and builtins need to replace the receiver with the 149 // Sloppy mode functions and builtins need to replace the receiver with the
150 // global proxy when called as functions (without an explicit receiver 150 // global proxy when called as functions (without an explicit receiver
151 // object). 151 // object).
152 if (info_->this_has_uses() && 152 if (info_->this_has_uses() &&
153 info_->is_classic_mode() && 153 info_->strict_mode() == SLOPPY &&
154 !info_->is_native()) { 154 !info_->is_native()) {
155 Label ok; 155 Label ok;
156 int receiver_offset = info_->scope()->num_parameters() * kPointerSize; 156 int receiver_offset = info_->scope()->num_parameters() * kPointerSize;
157 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 157 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
158 __ lw(a2, MemOperand(sp, receiver_offset)); 158 __ lw(a2, MemOperand(sp, receiver_offset));
159 __ Branch(&ok, ne, a2, Operand(at)); 159 __ Branch(&ok, ne, a2, Operand(at));
160 160
161 __ lw(a2, GlobalObjectOperand()); 161 __ lw(a2, GlobalObjectOperand());
162 __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset)); 162 __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset));
163 163
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 osr_pc_offset_ = masm()->pc_offset(); 252 osr_pc_offset_ = masm()->pc_offset();
253 253
254 // Adjust the frame size, subsuming the unoptimized frame into the 254 // Adjust the frame size, subsuming the unoptimized frame into the
255 // optimized frame. 255 // optimized frame.
256 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); 256 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots();
257 ASSERT(slots >= 0); 257 ASSERT(slots >= 0);
258 __ Subu(sp, sp, Operand(slots * kPointerSize)); 258 __ Subu(sp, sp, Operand(slots * kPointerSize));
259 } 259 }
260 260
261 261
262 void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
263 if (!instr->IsLazyBailout() && !instr->IsGap()) {
264 safepoints_.BumpLastLazySafepointIndex();
265 }
266 }
267
268
262 bool LCodeGen::GenerateDeferredCode() { 269 bool LCodeGen::GenerateDeferredCode() {
263 ASSERT(is_generating()); 270 ASSERT(is_generating());
264 if (deferred_.length() > 0) { 271 if (deferred_.length() > 0) {
265 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 272 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
266 LDeferredCode* code = deferred_[i]; 273 LDeferredCode* code = deferred_[i];
267 274
268 HValue* value = 275 HValue* value =
269 instructions_->at(code->instruction_index())->hydrogen_value(); 276 instructions_->at(code->instruction_index())->hydrogen_value();
270 RecordAndWritePosition( 277 RecordAndWritePosition(
271 chunk()->graph()->SourcePositionToScriptPosition(value->position())); 278 chunk()->graph()->SourcePositionToScriptPosition(value->position()));
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 } else if (r.IsSmi()) { 401 } else if (r.IsSmi()) {
395 ASSERT(constant->HasSmiValue()); 402 ASSERT(constant->HasSmiValue());
396 __ li(scratch, Operand(Smi::FromInt(constant->Integer32Value()))); 403 __ li(scratch, Operand(Smi::FromInt(constant->Integer32Value())));
397 } else if (r.IsDouble()) { 404 } else if (r.IsDouble()) {
398 Abort(kEmitLoadRegisterUnsupportedDoubleImmediate); 405 Abort(kEmitLoadRegisterUnsupportedDoubleImmediate);
399 } else { 406 } else {
400 ASSERT(r.IsSmiOrTagged()); 407 ASSERT(r.IsSmiOrTagged());
401 __ li(scratch, literal); 408 __ li(scratch, literal);
402 } 409 }
403 return scratch; 410 return scratch;
404 } else if (op->IsStackSlot() || op->IsArgument()) { 411 } else if (op->IsStackSlot()) {
405 __ lw(scratch, ToMemOperand(op)); 412 __ lw(scratch, ToMemOperand(op));
406 return scratch; 413 return scratch;
407 } 414 }
408 UNREACHABLE(); 415 UNREACHABLE();
409 return scratch; 416 return scratch;
410 } 417 }
411 418
412 419
413 DoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const { 420 DoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
414 ASSERT(op->IsDoubleRegister()); 421 ASSERT(op->IsDoubleRegister());
(...skipping 15 matching lines...) Expand all
430 ASSERT(literal->IsNumber()); 437 ASSERT(literal->IsNumber());
431 __ li(at, Operand(static_cast<int32_t>(literal->Number()))); 438 __ li(at, Operand(static_cast<int32_t>(literal->Number())));
432 __ mtc1(at, flt_scratch); 439 __ mtc1(at, flt_scratch);
433 __ cvt_d_w(dbl_scratch, flt_scratch); 440 __ cvt_d_w(dbl_scratch, flt_scratch);
434 return dbl_scratch; 441 return dbl_scratch;
435 } else if (r.IsDouble()) { 442 } else if (r.IsDouble()) {
436 Abort(kUnsupportedDoubleImmediate); 443 Abort(kUnsupportedDoubleImmediate);
437 } else if (r.IsTagged()) { 444 } else if (r.IsTagged()) {
438 Abort(kUnsupportedTaggedImmediate); 445 Abort(kUnsupportedTaggedImmediate);
439 } 446 }
440 } else if (op->IsStackSlot() || op->IsArgument()) { 447 } else if (op->IsStackSlot()) {
441 MemOperand mem_op = ToMemOperand(op); 448 MemOperand mem_op = ToMemOperand(op);
442 __ ldc1(dbl_scratch, mem_op); 449 __ ldc1(dbl_scratch, mem_op);
443 return dbl_scratch; 450 return dbl_scratch;
444 } 451 }
445 UNREACHABLE(); 452 UNREACHABLE();
446 return dbl_scratch; 453 return dbl_scratch;
447 } 454 }
448 455
449 456
450 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { 457 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 if (op->IsStackSlot()) { 655 if (op->IsStackSlot()) {
649 if (is_tagged) { 656 if (is_tagged) {
650 translation->StoreStackSlot(op->index()); 657 translation->StoreStackSlot(op->index());
651 } else if (is_uint32) { 658 } else if (is_uint32) {
652 translation->StoreUint32StackSlot(op->index()); 659 translation->StoreUint32StackSlot(op->index());
653 } else { 660 } else {
654 translation->StoreInt32StackSlot(op->index()); 661 translation->StoreInt32StackSlot(op->index());
655 } 662 }
656 } else if (op->IsDoubleStackSlot()) { 663 } else if (op->IsDoubleStackSlot()) {
657 translation->StoreDoubleStackSlot(op->index()); 664 translation->StoreDoubleStackSlot(op->index());
658 } else if (op->IsArgument()) {
659 ASSERT(is_tagged);
660 int src_index = GetStackSlotCount() + op->index();
661 translation->StoreStackSlot(src_index);
662 } else if (op->IsRegister()) { 665 } else if (op->IsRegister()) {
663 Register reg = ToRegister(op); 666 Register reg = ToRegister(op);
664 if (is_tagged) { 667 if (is_tagged) {
665 translation->StoreRegister(reg); 668 translation->StoreRegister(reg);
666 } else if (is_uint32) { 669 } else if (is_uint32) {
667 translation->StoreUint32Register(reg); 670 translation->StoreUint32Register(reg);
668 } else { 671 } else {
669 translation->StoreInt32Register(reg); 672 translation->StoreInt32Register(reg);
670 } 673 }
671 } else if (op->IsDoubleRegister()) { 674 } else if (op->IsDoubleRegister()) {
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
1057 UNREACHABLE(); 1060 UNREACHABLE();
1058 } 1061 }
1059 } 1062 }
1060 1063
1061 1064
1062 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 1065 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
1063 GenerateOsrPrologue(); 1066 GenerateOsrPrologue();
1064 } 1067 }
1065 1068
1066 1069
1070 void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
1071 Register dividend = ToRegister(instr->dividend());
1072 int32_t divisor = instr->divisor();
1073 ASSERT(dividend.is(ToRegister(instr->result())));
1074
1075 // Theoretically, a variation of the branch-free code for integer division by
1076 // a power of 2 (calculating the remainder via an additional multiplication
1077 // (which gets simplified to an 'and') and subtraction) should be faster, and
1078 // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to
1079 // indicate that positive dividends are heavily favored, so the branching
1080 // version performs better.
1081 HMod* hmod = instr->hydrogen();
1082 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1083 Label dividend_is_not_negative, done;
1084
1085 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1086 __ Branch(&dividend_is_not_negative, ge, dividend, Operand(zero_reg));
1087 // Note: The code below even works when right contains kMinInt.
1088 __ subu(dividend, zero_reg, dividend);
1089 __ And(dividend, dividend, Operand(mask));
1090 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1091 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg));
1092 }
1093 __ Branch(USE_DELAY_SLOT, &done);
1094 __ subu(dividend, zero_reg, dividend);
1095 }
1096
1097 __ bind(&dividend_is_not_negative);
1098 __ And(dividend, dividend, Operand(mask));
1099 __ bind(&done);
1100 }
1101
1102
1103 void LCodeGen::DoModByConstI(LModByConstI* instr) {
1104 Register dividend = ToRegister(instr->dividend());
1105 int32_t divisor = instr->divisor();
1106 Register result = ToRegister(instr->result());
1107 ASSERT(!dividend.is(result));
1108
1109 if (divisor == 0) {
1110 DeoptimizeIf(al, instr->environment());
1111 return;
1112 }
1113
1114 __ FlooringDiv(result, dividend, Abs(divisor));
1115 __ srl(at, dividend, 31);
1116 __ Addu(result, result, at);
1117 __ Mul(result, result, Operand(Abs(divisor)));
1118 __ Subu(result, dividend, Operand(result));
1119
1120 // Check for negative zero.
1121 HMod* hmod = instr->hydrogen();
1122 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1123 Label remainder_not_zero;
1124 __ Branch(&remainder_not_zero, ne, result, Operand(zero_reg));
1125 DeoptimizeIf(lt, instr->environment(), dividend, Operand(zero_reg));
1126 __ bind(&remainder_not_zero);
1127 }
1128 }
1129
1130
1067 void LCodeGen::DoModI(LModI* instr) { 1131 void LCodeGen::DoModI(LModI* instr) {
1068 HMod* hmod = instr->hydrogen(); 1132 HMod* hmod = instr->hydrogen();
1069 HValue* left = hmod->left(); 1133 const Register left_reg = ToRegister(instr->left());
1070 HValue* right = hmod->right(); 1134 const Register right_reg = ToRegister(instr->right());
1071 if (hmod->RightIsPowerOf2()) { 1135 const Register result_reg = ToRegister(instr->result());
1072 const Register left_reg = ToRegister(instr->left());
1073 const Register result_reg = ToRegister(instr->result());
1074 1136
1075 // Note: The code below even works when right contains kMinInt. 1137 // div runs in the background while we check for special cases.
1076 int32_t divisor = Abs(right->GetInteger32Constant()); 1138 __ div(left_reg, right_reg);
1077 1139
1078 Label left_is_not_negative, done; 1140 Label done;
1079 if (left->CanBeNegative()) { 1141 // Check for x % 0, we have to deopt in this case because we can't return a
1080 __ Branch(left_reg.is(result_reg) ? PROTECT : USE_DELAY_SLOT, 1142 // NaN.
1081 &left_is_not_negative, ge, left_reg, Operand(zero_reg)); 1143 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1082 __ subu(result_reg, zero_reg, left_reg); 1144 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(zero_reg));
1083 __ And(result_reg, result_reg, divisor - 1); 1145 }
1084 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1146
1085 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg)); 1147 // Check for kMinInt % -1, div will return kMinInt, which is not what we
1086 } 1148 // want. We have to deopt if we care about -0, because we can't return that.
1149 if (hmod->CheckFlag(HValue::kCanOverflow)) {
1150 Label no_overflow_possible;
1151 __ Branch(&no_overflow_possible, ne, left_reg, Operand(kMinInt));
1152 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1153 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(-1));
1154 } else {
1155 __ Branch(&no_overflow_possible, ne, right_reg, Operand(-1));
1087 __ Branch(USE_DELAY_SLOT, &done); 1156 __ Branch(USE_DELAY_SLOT, &done);
1088 __ subu(result_reg, zero_reg, result_reg); 1157 __ mov(result_reg, zero_reg);
1089 } 1158 }
1159 __ bind(&no_overflow_possible);
1160 }
1090 1161
1091 __ bind(&left_is_not_negative); 1162 // If we care about -0, test if the dividend is <0 and the result is 0.
1092 __ And(result_reg, left_reg, divisor - 1); 1163 __ Branch(USE_DELAY_SLOT, &done, ge, left_reg, Operand(zero_reg));
1093 __ bind(&done); 1164 __ mfhi(result_reg);
1094 } else { 1165 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1095 const Register scratch = scratch0(); 1166 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg));
1096 const Register left_reg = ToRegister(instr->left());
1097 const Register result_reg = ToRegister(instr->result());
1098
1099 // div runs in the background while we check for special cases.
1100 Register right_reg = EmitLoadRegister(instr->right(), scratch);
1101 __ div(left_reg, right_reg);
1102
1103 Label done;
1104 // Check for x % 0, we have to deopt in this case because we can't return a
1105 // NaN.
1106 if (right->CanBeZero()) {
1107 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(zero_reg));
1108 }
1109
1110 // Check for kMinInt % -1, we have to deopt if we care about -0, because we
1111 // can't return that.
1112 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) {
1113 Label left_not_min_int;
1114 __ Branch(&left_not_min_int, ne, left_reg, Operand(kMinInt));
1115 // TODO(svenpanne) Don't deopt when we don't care about -0.
1116 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(-1));
1117 __ bind(&left_not_min_int);
1118 }
1119
1120 // TODO(svenpanne) Only emit the test/deopt if we have to.
1121 __ Branch(USE_DELAY_SLOT, &done, ge, left_reg, Operand(zero_reg));
1122 __ mfhi(result_reg);
1123
1124 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1125 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg));
1126 }
1127 __ bind(&done);
1128 } 1167 }
1168 __ bind(&done);
1129 } 1169 }
1130 1170
1131 1171
1132 void LCodeGen::EmitSignedIntegerDivisionByConstant( 1172 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1133 Register result, 1173 Register dividend = ToRegister(instr->dividend());
1134 Register dividend, 1174 int32_t divisor = instr->divisor();
1135 int32_t divisor, 1175 Register result = ToRegister(instr->result());
1136 Register remainder, 1176 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor))));
1137 Register scratch, 1177 ASSERT(!result.is(dividend));
1138 LEnvironment* environment) {
1139 ASSERT(!AreAliased(dividend, scratch, at, no_reg));
1140 1178
1141 uint32_t divisor_abs = abs(divisor); 1179 // Check for (0 / -x) that will produce negative zero.
1180 HDiv* hdiv = instr->hydrogen();
1181 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1182 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg));
1183 }
1184 // Check for (kMinInt / -1).
1185 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1186 DeoptimizeIf(eq, instr->environment(), dividend, Operand(kMinInt));
1187 }
1188 // Deoptimize if remainder will not be 0.
1189 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1190 divisor != 1 && divisor != -1) {
1191 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1192 __ And(at, dividend, Operand(mask));
1193 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg));
1194 }
1142 1195
1143 int32_t power_of_2_factor = 1196 if (divisor == -1) { // Nice shortcut, not needed for correctness.
1144 CompilerIntrinsics::CountTrailingZeros(divisor_abs); 1197 __ Subu(result, zero_reg, dividend);
1198 return;
1199 }
1200 uint16_t shift = WhichPowerOf2Abs(divisor);
1201 if (shift == 0) {
1202 __ Move(result, dividend);
1203 } else if (shift == 1) {
1204 __ srl(result, dividend, 31);
1205 __ Addu(result, dividend, Operand(result));
1206 } else {
1207 __ sra(result, dividend, 31);
1208 __ srl(result, result, 32 - shift);
1209 __ Addu(result, dividend, Operand(result));
1210 }
1211 if (shift > 0) __ sra(result, result, shift);
1212 if (divisor < 0) __ Subu(result, zero_reg, result);
1213 }
1145 1214
1146 switch (divisor_abs) {
1147 case 0:
1148 DeoptimizeIf(al, environment);
1149 return;
1150 1215
1151 case 1: 1216 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1152 if (divisor > 0) { 1217 Register dividend = ToRegister(instr->dividend());
1153 __ Move(result, dividend); 1218 int32_t divisor = instr->divisor();
1154 } else { 1219 Register result = ToRegister(instr->result());
1155 __ SubuAndCheckForOverflow(result, zero_reg, dividend, scratch); 1220 ASSERT(!dividend.is(result));
1156 DeoptimizeIf(lt, environment, scratch, Operand(zero_reg));
1157 }
1158 // Compute the remainder.
1159 __ Move(remainder, zero_reg);
1160 return;
1161 1221
1162 default: 1222 if (divisor == 0) {
1163 if (IsPowerOf2(divisor_abs)) { 1223 DeoptimizeIf(al, instr->environment());
1164 // Branch and condition free code for integer division by a power 1224 return;
1165 // of two. 1225 }
1166 int32_t power = WhichPowerOf2(divisor_abs);
1167 if (power > 1) {
1168 __ sra(scratch, dividend, power - 1);
1169 }
1170 __ srl(scratch, scratch, 32 - power);
1171 __ Addu(scratch, dividend, Operand(scratch));
1172 __ sra(result, scratch, power);
1173 // Negate if necessary.
1174 // We don't need to check for overflow because the case '-1' is
1175 // handled separately.
1176 if (divisor < 0) {
1177 ASSERT(divisor != -1);
1178 __ Subu(result, zero_reg, Operand(result));
1179 }
1180 // Compute the remainder.
1181 if (divisor > 0) {
1182 __ sll(scratch, result, power);
1183 __ Subu(remainder, dividend, Operand(scratch));
1184 } else {
1185 __ sll(scratch, result, power);
1186 __ Addu(remainder, dividend, Operand(scratch));
1187 }
1188 return;
1189 } else if (LChunkBuilder::HasMagicNumberForDivisor(divisor)) {
1190 // Use magic numbers for a few specific divisors.
1191 // Details and proofs can be found in:
1192 // - Hacker's Delight, Henry S. Warren, Jr.
1193 // - The PowerPC Compiler Writer's Guide
1194 // and probably many others.
1195 //
1196 // We handle
1197 // <divisor with magic numbers> * <power of 2>
1198 // but not
1199 // <divisor with magic numbers> * <other divisor with magic numbers>
1200 DivMagicNumbers magic_numbers =
1201 DivMagicNumberFor(divisor_abs >> power_of_2_factor);
1202 // Branch and condition free code for integer division by a power
1203 // of two.
1204 const int32_t M = magic_numbers.M;
1205 const int32_t s = magic_numbers.s + power_of_2_factor;
1206 1226
1207 __ li(scratch, Operand(M)); 1227 // Check for (0 / -x) that will produce negative zero.
1208 __ mult(dividend, scratch); 1228 HDiv* hdiv = instr->hydrogen();
1209 __ mfhi(scratch); 1229 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1210 if (M < 0) { 1230 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg));
1211 __ Addu(scratch, scratch, Operand(dividend)); 1231 }
1212 } 1232
1213 if (s > 0) { 1233 __ FlooringDiv(result, dividend, Abs(divisor));
1214 __ sra(scratch, scratch, s); 1234 __ srl(at, dividend, 31);
1215 __ mov(scratch, scratch); 1235 __ Addu(result, result, Operand(at));
1216 } 1236 if (divisor < 0) __ Subu(result, zero_reg, result);
1217 __ srl(at, dividend, 31); 1237
1218 __ Addu(result, scratch, Operand(at)); 1238 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1219 if (divisor < 0) __ Subu(result, zero_reg, Operand(result)); 1239 __ Mul(scratch0(), result, Operand(divisor));
1220 // Compute the remainder. 1240 __ Subu(scratch0(), scratch0(), dividend);
1221 __ li(scratch, Operand(divisor)); 1241 DeoptimizeIf(ne, instr->environment(), scratch0(), Operand(zero_reg));
1222 __ Mul(scratch, result, Operand(scratch));
1223 __ Subu(remainder, dividend, Operand(scratch));
1224 } else {
1225 __ li(scratch, Operand(divisor));
1226 __ div(dividend, scratch);
1227 __ mfhi(remainder);
1228 __ mflo(result);
1229 }
1230 } 1242 }
1231 } 1243 }
1232 1244
1233 1245
1234 void LCodeGen::DoDivI(LDivI* instr) { 1246 void LCodeGen::DoDivI(LDivI* instr) {
1247 HBinaryOperation* hdiv = instr->hydrogen();
1235 const Register left = ToRegister(instr->left()); 1248 const Register left = ToRegister(instr->left());
1236 const Register right = ToRegister(instr->right()); 1249 const Register right = ToRegister(instr->right());
1237 const Register result = ToRegister(instr->result()); 1250 const Register result = ToRegister(instr->result());
1238 1251
1239 // On MIPS div is asynchronous - it will run in the background while we 1252 // On MIPS div is asynchronous - it will run in the background while we
1240 // check for special cases. 1253 // check for special cases.
1241 __ div(left, right); 1254 __ div(left, right);
1242 1255
1243 // Check for x / 0. 1256 // Check for x / 0.
1244 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 1257 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1245 DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg)); 1258 DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg));
1246 } 1259 }
1247 1260
1248 // Check for (0 / -x) that will produce negative zero. 1261 // Check for (0 / -x) that will produce negative zero.
1249 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1262 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1250 Label left_not_zero; 1263 Label left_not_zero;
1251 __ Branch(&left_not_zero, ne, left, Operand(zero_reg)); 1264 __ Branch(&left_not_zero, ne, left, Operand(zero_reg));
1252 DeoptimizeIf(lt, instr->environment(), right, Operand(zero_reg)); 1265 DeoptimizeIf(lt, instr->environment(), right, Operand(zero_reg));
1253 __ bind(&left_not_zero); 1266 __ bind(&left_not_zero);
1254 } 1267 }
1255 1268
1256 // Check for (kMinInt / -1). 1269 // Check for (kMinInt / -1).
1257 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1270 if (hdiv->CheckFlag(HValue::kCanOverflow) &&
1271 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1258 Label left_not_min_int; 1272 Label left_not_min_int;
1259 __ Branch(&left_not_min_int, ne, left, Operand(kMinInt)); 1273 __ Branch(&left_not_min_int, ne, left, Operand(kMinInt));
1260 DeoptimizeIf(eq, instr->environment(), right, Operand(-1)); 1274 DeoptimizeIf(eq, instr->environment(), right, Operand(-1));
1261 __ bind(&left_not_min_int); 1275 __ bind(&left_not_min_int);
1262 } 1276 }
1263 1277
1264 if (!instr->hydrogen()->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { 1278 if (hdiv->IsMathFloorOfDiv()) {
1279 // We performed a truncating division. Correct the result if necessary.
1280 Label done;
1281 Register remainder = scratch0();
1282 __ mfhi(remainder);
1283 __ mflo(result);
1284 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT);
1285 __ Xor(remainder, remainder, Operand(right));
1286 __ Branch(&done, ge, remainder, Operand(zero_reg));
1287 __ Subu(result, result, Operand(1));
1288 __ bind(&done);
1289 } else if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1265 __ mfhi(result); 1290 __ mfhi(result);
1266 DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg)); 1291 DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg));
1292 __ mflo(result);
1293 } else {
1294 __ mflo(result);
1267 } 1295 }
1268 __ mflo(result);
1269 } 1296 }
1270 1297
1271 1298
1272 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { 1299 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) {
1273 DoubleRegister addend = ToDoubleRegister(instr->addend()); 1300 DoubleRegister addend = ToDoubleRegister(instr->addend());
1274 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); 1301 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier());
1275 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); 1302 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand());
1276 1303
1277 // This is computed in-place. 1304 // This is computed in-place.
1278 ASSERT(addend.is(ToDoubleRegister(instr->result()))); 1305 ASSERT(addend.is(ToDoubleRegister(instr->result())));
1279 1306
1280 __ madd_d(addend, addend, multiplier, multiplicand); 1307 __ madd_d(addend, addend, multiplier, multiplicand);
1281 } 1308 }
1282 1309
1283 1310
1284 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { 1311 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
1285 const Register result = ToRegister(instr->result()); 1312 Register dividend = ToRegister(instr->dividend());
1286 const Register left = ToRegister(instr->left()); 1313 Register result = ToRegister(instr->result());
1287 const Register remainder = ToRegister(instr->temp()); 1314 int32_t divisor = instr->divisor();
1288 const Register scratch = scratch0(); 1315 Register scratch = scratch0();
1316 ASSERT(!scratch.is(dividend));
1289 1317
1290 if (instr->right()->IsConstantOperand()) { 1318 // If the divisor is positive, things are easy: There can be no deopts and we
1291 Label done; 1319 // can simply do an arithmetic right shift.
1292 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); 1320 if (divisor == 1) return;
1293 if (divisor < 0) { 1321 uint16_t shift = WhichPowerOf2Abs(divisor);
1294 DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg)); 1322 if (divisor > 1) {
1323 __ sra(result, dividend, shift);
1324 return;
1325 }
1326
1327 // If the divisor is negative, we have to negate and handle edge cases.
1328 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1329 __ Move(scratch, dividend);
1330 }
1331 __ Subu(result, zero_reg, dividend);
1332 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1333 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg));
1334 }
1335 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1336 // Note that we could emit branch-free code, but that would need one more
1337 // register.
1338 __ Xor(at, scratch, result);
1339 if (divisor == -1) {
1340 DeoptimizeIf(ge, instr->environment(), at, Operand(zero_reg));
1341 __ sra(result, dividend, shift);
1342 } else {
1343 Label no_overflow, done;
1344 __ Branch(&no_overflow, lt, at, Operand(zero_reg));
1345 __ li(result, Operand(kMinInt / divisor));
1346 __ Branch(&done);
1347 __ bind(&no_overflow);
1348 __ sra(result, dividend, shift);
1349 __ bind(&done);
1295 } 1350 }
1296 EmitSignedIntegerDivisionByConstant(result,
1297 left,
1298 divisor,
1299 remainder,
1300 scratch,
1301 instr->environment());
1302 // We performed a truncating division. Correct the result if necessary.
1303 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT);
1304 __ Xor(scratch , remainder, Operand(divisor));
1305 __ Branch(&done, ge, scratch, Operand(zero_reg));
1306 __ Subu(result, result, Operand(1));
1307 __ bind(&done);
1308 } else { 1351 } else {
1309 Label done; 1352 __ sra(result, dividend, shift);
1310 const Register right = ToRegister(instr->right());
1311
1312 // On MIPS div is asynchronous - it will run in the background while we
1313 // check for special cases.
1314 __ div(left, right);
1315
1316 // Check for x / 0.
1317 DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg));
1318
1319 // Check for (0 / -x) that will produce negative zero.
1320 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1321 Label left_not_zero;
1322 __ Branch(&left_not_zero, ne, left, Operand(zero_reg));
1323 DeoptimizeIf(lt, instr->environment(), right, Operand(zero_reg));
1324 __ bind(&left_not_zero);
1325 }
1326
1327 // Check for (kMinInt / -1).
1328 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1329 Label left_not_min_int;
1330 __ Branch(&left_not_min_int, ne, left, Operand(kMinInt));
1331 DeoptimizeIf(eq, instr->environment(), right, Operand(-1));
1332 __ bind(&left_not_min_int);
1333 }
1334
1335 __ mfhi(remainder);
1336 __ mflo(result);
1337
1338 // We performed a truncating division. Correct the result if necessary.
1339 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT);
1340 __ Xor(scratch , remainder, Operand(right));
1341 __ Branch(&done, ge, scratch, Operand(zero_reg));
1342 __ Subu(result, result, Operand(1));
1343 __ bind(&done);
1344 } 1353 }
1345 } 1354 }
1346 1355
1347 1356
1357 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1358 Register dividend = ToRegister(instr->dividend());
1359 int32_t divisor = instr->divisor();
1360 Register result = ToRegister(instr->result());
1361 ASSERT(!dividend.is(result));
1362
1363 if (divisor == 0) {
1364 DeoptimizeIf(al, instr->environment());
1365 return;
1366 }
1367
1368 // Check for (0 / -x) that will produce negative zero.
1369 HMathFloorOfDiv* hdiv = instr->hydrogen();
1370 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1371 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg));
1372 }
1373
1374 __ FlooringDiv(result, dividend, divisor);
1375 }
1376
1377
1348 void LCodeGen::DoMulI(LMulI* instr) { 1378 void LCodeGen::DoMulI(LMulI* instr) {
1349 Register scratch = scratch0(); 1379 Register scratch = scratch0();
1350 Register result = ToRegister(instr->result()); 1380 Register result = ToRegister(instr->result());
1351 // Note that result may alias left. 1381 // Note that result may alias left.
1352 Register left = ToRegister(instr->left()); 1382 Register left = ToRegister(instr->left());
1353 LOperand* right_op = instr->right(); 1383 LOperand* right_op = instr->right();
1354 1384
1355 bool bailout_on_minus_zero = 1385 bool bailout_on_minus_zero =
1356 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); 1386 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
1357 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 1387 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1460 1490
1461 1491
1462 void LCodeGen::DoBitI(LBitI* instr) { 1492 void LCodeGen::DoBitI(LBitI* instr) {
1463 LOperand* left_op = instr->left(); 1493 LOperand* left_op = instr->left();
1464 LOperand* right_op = instr->right(); 1494 LOperand* right_op = instr->right();
1465 ASSERT(left_op->IsRegister()); 1495 ASSERT(left_op->IsRegister());
1466 Register left = ToRegister(left_op); 1496 Register left = ToRegister(left_op);
1467 Register result = ToRegister(instr->result()); 1497 Register result = ToRegister(instr->result());
1468 Operand right(no_reg); 1498 Operand right(no_reg);
1469 1499
1470 if (right_op->IsStackSlot() || right_op->IsArgument()) { 1500 if (right_op->IsStackSlot()) {
1471 right = Operand(EmitLoadRegister(right_op, at)); 1501 right = Operand(EmitLoadRegister(right_op, at));
1472 } else { 1502 } else {
1473 ASSERT(right_op->IsRegister() || right_op->IsConstantOperand()); 1503 ASSERT(right_op->IsRegister() || right_op->IsConstantOperand());
1474 right = ToOperand(right_op); 1504 right = ToOperand(right_op);
1475 } 1505 }
1476 1506
1477 switch (instr->op()) { 1507 switch (instr->op()) {
1478 case Token::BIT_AND: 1508 case Token::BIT_AND:
1479 __ And(result, left, right); 1509 __ And(result, left, right);
1480 break; 1510 break;
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1582 } 1612 }
1583 1613
1584 1614
1585 void LCodeGen::DoSubI(LSubI* instr) { 1615 void LCodeGen::DoSubI(LSubI* instr) {
1586 LOperand* left = instr->left(); 1616 LOperand* left = instr->left();
1587 LOperand* right = instr->right(); 1617 LOperand* right = instr->right();
1588 LOperand* result = instr->result(); 1618 LOperand* result = instr->result();
1589 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 1619 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1590 1620
1591 if (!can_overflow) { 1621 if (!can_overflow) {
1592 if (right->IsStackSlot() || right->IsArgument()) { 1622 if (right->IsStackSlot()) {
1593 Register right_reg = EmitLoadRegister(right, at); 1623 Register right_reg = EmitLoadRegister(right, at);
1594 __ Subu(ToRegister(result), ToRegister(left), Operand(right_reg)); 1624 __ Subu(ToRegister(result), ToRegister(left), Operand(right_reg));
1595 } else { 1625 } else {
1596 ASSERT(right->IsRegister() || right->IsConstantOperand()); 1626 ASSERT(right->IsRegister() || right->IsConstantOperand());
1597 __ Subu(ToRegister(result), ToRegister(left), ToOperand(right)); 1627 __ Subu(ToRegister(result), ToRegister(left), ToOperand(right));
1598 } 1628 }
1599 } else { // can_overflow. 1629 } else { // can_overflow.
1600 Register overflow = scratch0(); 1630 Register overflow = scratch0();
1601 Register scratch = scratch1(); 1631 Register scratch = scratch1();
1602 if (right->IsStackSlot() || 1632 if (right->IsStackSlot() || right->IsConstantOperand()) {
1603 right->IsArgument() ||
1604 right->IsConstantOperand()) {
1605 Register right_reg = EmitLoadRegister(right, scratch); 1633 Register right_reg = EmitLoadRegister(right, scratch);
1606 __ SubuAndCheckForOverflow(ToRegister(result), 1634 __ SubuAndCheckForOverflow(ToRegister(result),
1607 ToRegister(left), 1635 ToRegister(left),
1608 right_reg, 1636 right_reg,
1609 overflow); // Reg at also used as scratch. 1637 overflow); // Reg at also used as scratch.
1610 } else { 1638 } else {
1611 ASSERT(right->IsRegister()); 1639 ASSERT(right->IsRegister());
1612 // Due to overflow check macros not supporting constant operands, 1640 // Due to overflow check macros not supporting constant operands,
1613 // handling the IsConstantOperand case was moved to prev if clause. 1641 // handling the IsConstantOperand case was moved to prev if clause.
1614 __ SubuAndCheckForOverflow(ToRegister(result), 1642 __ SubuAndCheckForOverflow(ToRegister(result),
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
1774 } 1802 }
1775 1803
1776 1804
1777 void LCodeGen::DoAddI(LAddI* instr) { 1805 void LCodeGen::DoAddI(LAddI* instr) {
1778 LOperand* left = instr->left(); 1806 LOperand* left = instr->left();
1779 LOperand* right = instr->right(); 1807 LOperand* right = instr->right();
1780 LOperand* result = instr->result(); 1808 LOperand* result = instr->result();
1781 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 1809 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1782 1810
1783 if (!can_overflow) { 1811 if (!can_overflow) {
1784 if (right->IsStackSlot() || right->IsArgument()) { 1812 if (right->IsStackSlot()) {
1785 Register right_reg = EmitLoadRegister(right, at); 1813 Register right_reg = EmitLoadRegister(right, at);
1786 __ Addu(ToRegister(result), ToRegister(left), Operand(right_reg)); 1814 __ Addu(ToRegister(result), ToRegister(left), Operand(right_reg));
1787 } else { 1815 } else {
1788 ASSERT(right->IsRegister() || right->IsConstantOperand()); 1816 ASSERT(right->IsRegister() || right->IsConstantOperand());
1789 __ Addu(ToRegister(result), ToRegister(left), ToOperand(right)); 1817 __ Addu(ToRegister(result), ToRegister(left), ToOperand(right));
1790 } 1818 }
1791 } else { // can_overflow. 1819 } else { // can_overflow.
1792 Register overflow = scratch0(); 1820 Register overflow = scratch0();
1793 Register scratch = scratch1(); 1821 Register scratch = scratch1();
1794 if (right->IsStackSlot() || 1822 if (right->IsStackSlot() ||
1795 right->IsArgument() ||
1796 right->IsConstantOperand()) { 1823 right->IsConstantOperand()) {
1797 Register right_reg = EmitLoadRegister(right, scratch); 1824 Register right_reg = EmitLoadRegister(right, scratch);
1798 __ AdduAndCheckForOverflow(ToRegister(result), 1825 __ AdduAndCheckForOverflow(ToRegister(result),
1799 ToRegister(left), 1826 ToRegister(left),
1800 right_reg, 1827 right_reg,
1801 overflow); // Reg at also used as scratch. 1828 overflow); // Reg at also used as scratch.
1802 } else { 1829 } else {
1803 ASSERT(right->IsRegister()); 1830 ASSERT(right->IsRegister());
1804 // Due to overflow check macros not supporting constant operands, 1831 // Due to overflow check macros not supporting constant operands,
1805 // handling the IsConstantOperand case was moved to prev if clause. 1832 // handling the IsConstantOperand case was moved to prev if clause.
(...skipping 1277 matching lines...) Expand 10 before | Expand all | Expand 10 after
3083 case FLOAT64_ELEMENTS: 3110 case FLOAT64_ELEMENTS:
3084 case EXTERNAL_FLOAT32_ELEMENTS: 3111 case EXTERNAL_FLOAT32_ELEMENTS:
3085 case EXTERNAL_FLOAT64_ELEMENTS: 3112 case EXTERNAL_FLOAT64_ELEMENTS:
3086 case FAST_DOUBLE_ELEMENTS: 3113 case FAST_DOUBLE_ELEMENTS:
3087 case FAST_ELEMENTS: 3114 case FAST_ELEMENTS:
3088 case FAST_SMI_ELEMENTS: 3115 case FAST_SMI_ELEMENTS:
3089 case FAST_HOLEY_DOUBLE_ELEMENTS: 3116 case FAST_HOLEY_DOUBLE_ELEMENTS:
3090 case FAST_HOLEY_ELEMENTS: 3117 case FAST_HOLEY_ELEMENTS:
3091 case FAST_HOLEY_SMI_ELEMENTS: 3118 case FAST_HOLEY_SMI_ELEMENTS:
3092 case DICTIONARY_ELEMENTS: 3119 case DICTIONARY_ELEMENTS:
3093 case NON_STRICT_ARGUMENTS_ELEMENTS: 3120 case SLOPPY_ARGUMENTS_ELEMENTS:
3094 UNREACHABLE(); 3121 UNREACHABLE();
3095 break; 3122 break;
3096 } 3123 }
3097 } 3124 }
3098 } 3125 }
3099 3126
3100 3127
3101 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { 3128 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
3102 Register elements = ToRegister(instr->elements()); 3129 Register elements = ToRegister(instr->elements());
3103 bool key_is_constant = instr->key()->IsConstantOperand(); 3130 bool key_is_constant = instr->key()->IsConstantOperand();
(...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after
3883 } 3910 }
3884 3911
3885 3912
3886 void LCodeGen::DoCallNew(LCallNew* instr) { 3913 void LCodeGen::DoCallNew(LCallNew* instr) {
3887 ASSERT(ToRegister(instr->context()).is(cp)); 3914 ASSERT(ToRegister(instr->context()).is(cp));
3888 ASSERT(ToRegister(instr->constructor()).is(a1)); 3915 ASSERT(ToRegister(instr->constructor()).is(a1));
3889 ASSERT(ToRegister(instr->result()).is(v0)); 3916 ASSERT(ToRegister(instr->result()).is(v0));
3890 3917
3891 __ li(a0, Operand(instr->arity())); 3918 __ li(a0, Operand(instr->arity()));
3892 // No cell in a2 for construct type feedback in optimized code 3919 // No cell in a2 for construct type feedback in optimized code
3893 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); 3920 Handle<Object> megamorphic_symbol =
3894 __ li(a2, Operand(undefined_value)); 3921 TypeFeedbackInfo::MegamorphicSentinel(isolate());
3922 __ li(a2, Operand(megamorphic_symbol));
3895 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); 3923 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
3896 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 3924 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
3897 } 3925 }
3898 3926
3899 3927
3900 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { 3928 void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
3901 ASSERT(ToRegister(instr->context()).is(cp)); 3929 ASSERT(ToRegister(instr->context()).is(cp));
3902 ASSERT(ToRegister(instr->constructor()).is(a1)); 3930 ASSERT(ToRegister(instr->constructor()).is(a1));
3903 ASSERT(ToRegister(instr->result()).is(v0)); 3931 ASSERT(ToRegister(instr->result()).is(v0));
3904 3932
3905 __ li(a0, Operand(instr->arity())); 3933 __ li(a0, Operand(instr->arity()));
3906 __ li(a2, Operand(factory()->undefined_value())); 3934 __ li(a2, Operand(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
3907 ElementsKind kind = instr->hydrogen()->elements_kind(); 3935 ElementsKind kind = instr->hydrogen()->elements_kind();
3908 AllocationSiteOverrideMode override_mode = 3936 AllocationSiteOverrideMode override_mode =
3909 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) 3937 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
3910 ? DISABLE_ALLOCATION_SITES 3938 ? DISABLE_ALLOCATION_SITES
3911 : DONT_OVERRIDE; 3939 : DONT_OVERRIDE;
3912 3940
3913 if (instr->arity() == 0) { 3941 if (instr->arity() == 0) {
3914 ArrayNoArgumentConstructorStub stub(kind, override_mode); 3942 ArrayNoArgumentConstructorStub stub(kind, override_mode);
3915 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 3943 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
3916 } else if (instr->arity() == 1) { 3944 } else if (instr->arity() == 1) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
3980 MemOperand operand = MemOperand(object, offset); 4008 MemOperand operand = MemOperand(object, offset);
3981 __ Store(value, operand, representation); 4009 __ Store(value, operand, representation);
3982 return; 4010 return;
3983 } 4011 }
3984 4012
3985 Handle<Map> transition = instr->transition(); 4013 Handle<Map> transition = instr->transition();
3986 SmiCheck check_needed = 4014 SmiCheck check_needed =
3987 instr->hydrogen()->value()->IsHeapObject() 4015 instr->hydrogen()->value()->IsHeapObject()
3988 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 4016 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3989 4017
3990 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { 4018 if (representation.IsHeapObject()) {
3991 Register value = ToRegister(instr->value()); 4019 Register value = ToRegister(instr->value());
3992 if (!instr->hydrogen()->value()->type().IsHeapObject()) { 4020 if (!instr->hydrogen()->value()->type().IsHeapObject()) {
3993 __ SmiTst(value, scratch); 4021 __ SmiTst(value, scratch);
3994 DeoptimizeIf(eq, instr->environment(), scratch, Operand(zero_reg)); 4022 DeoptimizeIf(eq, instr->environment(), scratch, Operand(zero_reg));
3995 4023
3996 // We know that value is a smi now, so we can omit the check below. 4024 // We know that value is a smi now, so we can omit the check below.
3997 check_needed = OMIT_SMI_CHECK; 4025 check_needed = OMIT_SMI_CHECK;
3998 } 4026 }
3999 } else if (representation.IsDouble()) { 4027 } else if (representation.IsDouble()) {
4000 ASSERT(transition.is_null()); 4028 ASSERT(transition.is_null());
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
4058 } 4086 }
4059 4087
4060 4088
4061 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 4089 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
4062 ASSERT(ToRegister(instr->context()).is(cp)); 4090 ASSERT(ToRegister(instr->context()).is(cp));
4063 ASSERT(ToRegister(instr->object()).is(a1)); 4091 ASSERT(ToRegister(instr->object()).is(a1));
4064 ASSERT(ToRegister(instr->value()).is(a0)); 4092 ASSERT(ToRegister(instr->value()).is(a0));
4065 4093
4066 // Name is always in a2. 4094 // Name is always in a2.
4067 __ li(a2, Operand(instr->name())); 4095 __ li(a2, Operand(instr->name()));
4068 Handle<Code> ic = StoreIC::initialize_stub(isolate(), 4096 Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
4069 instr->strict_mode_flag());
4070 CallCode(ic, RelocInfo::CODE_TARGET, instr); 4097 CallCode(ic, RelocInfo::CODE_TARGET, instr);
4071 } 4098 }
4072 4099
4073 4100
4074 void LCodeGen::ApplyCheckIf(Condition condition, 4101 void LCodeGen::ApplyCheckIf(Condition condition,
4075 LBoundsCheck* check, 4102 LBoundsCheck* check,
4076 Register src1, 4103 Register src1,
4077 const Operand& src2) { 4104 const Operand& src2) {
4078 if (FLAG_debug_code && check->hydrogen()->skip_check()) { 4105 if (FLAG_debug_code && check->hydrogen()->skip_check()) {
4079 Label done; 4106 Label done;
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
4190 case FLOAT64_ELEMENTS: 4217 case FLOAT64_ELEMENTS:
4191 case EXTERNAL_FLOAT32_ELEMENTS: 4218 case EXTERNAL_FLOAT32_ELEMENTS:
4192 case EXTERNAL_FLOAT64_ELEMENTS: 4219 case EXTERNAL_FLOAT64_ELEMENTS:
4193 case FAST_DOUBLE_ELEMENTS: 4220 case FAST_DOUBLE_ELEMENTS:
4194 case FAST_ELEMENTS: 4221 case FAST_ELEMENTS:
4195 case FAST_SMI_ELEMENTS: 4222 case FAST_SMI_ELEMENTS:
4196 case FAST_HOLEY_DOUBLE_ELEMENTS: 4223 case FAST_HOLEY_DOUBLE_ELEMENTS:
4197 case FAST_HOLEY_ELEMENTS: 4224 case FAST_HOLEY_ELEMENTS:
4198 case FAST_HOLEY_SMI_ELEMENTS: 4225 case FAST_HOLEY_SMI_ELEMENTS:
4199 case DICTIONARY_ELEMENTS: 4226 case DICTIONARY_ELEMENTS:
4200 case NON_STRICT_ARGUMENTS_ELEMENTS: 4227 case SLOPPY_ARGUMENTS_ELEMENTS:
4201 UNREACHABLE(); 4228 UNREACHABLE();
4202 break; 4229 break;
4203 } 4230 }
4204 } 4231 }
4205 } 4232 }
4206 4233
4207 4234
4208 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { 4235 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
4209 DoubleRegister value = ToDoubleRegister(instr->value()); 4236 DoubleRegister value = ToDoubleRegister(instr->value());
4210 Register elements = ToRegister(instr->elements()); 4237 Register elements = ToRegister(instr->elements());
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
4315 } 4342 }
4316 } 4343 }
4317 4344
4318 4345
4319 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { 4346 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
4320 ASSERT(ToRegister(instr->context()).is(cp)); 4347 ASSERT(ToRegister(instr->context()).is(cp));
4321 ASSERT(ToRegister(instr->object()).is(a2)); 4348 ASSERT(ToRegister(instr->object()).is(a2));
4322 ASSERT(ToRegister(instr->key()).is(a1)); 4349 ASSERT(ToRegister(instr->key()).is(a1));
4323 ASSERT(ToRegister(instr->value()).is(a0)); 4350 ASSERT(ToRegister(instr->value()).is(a0));
4324 4351
4325 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) 4352 Handle<Code> ic = (instr->strict_mode() == STRICT)
4326 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 4353 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
4327 : isolate()->builtins()->KeyedStoreIC_Initialize(); 4354 : isolate()->builtins()->KeyedStoreIC_Initialize();
4328 CallCode(ic, RelocInfo::CODE_TARGET, instr); 4355 CallCode(ic, RelocInfo::CODE_TARGET, instr);
4329 } 4356 }
4330 4357
4331 4358
4332 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { 4359 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4333 Register object_reg = ToRegister(instr->object()); 4360 Register object_reg = ToRegister(instr->object());
4334 Register scratch = scratch0(); 4361 Register scratch = scratch0();
4335 4362
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
4501 Register scratch = scratch0(); 4528 Register scratch = scratch0();
4502 __ lw(scratch, ToMemOperand(input)); 4529 __ lw(scratch, ToMemOperand(input));
4503 __ mtc1(scratch, single_scratch); 4530 __ mtc1(scratch, single_scratch);
4504 } else { 4531 } else {
4505 __ mtc1(ToRegister(input), single_scratch); 4532 __ mtc1(ToRegister(input), single_scratch);
4506 } 4533 }
4507 __ cvt_d_w(ToDoubleRegister(output), single_scratch); 4534 __ cvt_d_w(ToDoubleRegister(output), single_scratch);
4508 } 4535 }
4509 4536
4510 4537
4511 void LCodeGen::DoInteger32ToSmi(LInteger32ToSmi* instr) {
4512 LOperand* input = instr->value();
4513 LOperand* output = instr->result();
4514 Register scratch = scratch0();
4515
4516 ASSERT(output->IsRegister());
4517 if (!instr->hydrogen()->value()->HasRange() ||
4518 !instr->hydrogen()->value()->range()->IsInSmiRange()) {
4519 __ SmiTagCheckOverflow(ToRegister(output), ToRegister(input), scratch);
4520 DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg));
4521 } else {
4522 __ SmiTag(ToRegister(output), ToRegister(input));
4523 }
4524 }
4525
4526
4527 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { 4538 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
4528 LOperand* input = instr->value(); 4539 LOperand* input = instr->value();
4529 LOperand* output = instr->result(); 4540 LOperand* output = instr->result();
4530 4541
4531 FPURegister dbl_scratch = double_scratch0(); 4542 FPURegister dbl_scratch = double_scratch0();
4532 __ mtc1(ToRegister(input), dbl_scratch); 4543 __ mtc1(ToRegister(input), dbl_scratch);
4533 __ Cvt_d_uw(ToDoubleRegister(output), dbl_scratch, f22); 4544 __ Cvt_d_uw(ToDoubleRegister(output), dbl_scratch, f22);
4534 } 4545 }
4535 4546
4536 4547
4537 void LCodeGen::DoUint32ToSmi(LUint32ToSmi* instr) {
4538 LOperand* input = instr->value();
4539 LOperand* output = instr->result();
4540 if (!instr->hydrogen()->value()->HasRange() ||
4541 !instr->hydrogen()->value()->range()->IsInSmiRange()) {
4542 Register scratch = scratch0();
4543 __ And(scratch, ToRegister(input), Operand(0xc0000000));
4544 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg));
4545 }
4546 __ SmiTag(ToRegister(output), ToRegister(input));
4547 }
4548
4549
4550 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { 4548 void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
4551 class DeferredNumberTagI V8_FINAL : public LDeferredCode { 4549 class DeferredNumberTagI V8_FINAL : public LDeferredCode {
4552 public: 4550 public:
4553 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) 4551 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr)
4554 : LDeferredCode(codegen), instr_(instr) { } 4552 : LDeferredCode(codegen), instr_(instr) { }
4555 virtual void Generate() V8_OVERRIDE { 4553 virtual void Generate() V8_OVERRIDE {
4556 codegen()->DoDeferredNumberTagI(instr_, 4554 codegen()->DoDeferredNumberTagIU(instr_,
4557 instr_->value(), 4555 instr_->value(),
4558 SIGNED_INT32); 4556 instr_->temp1(),
4557 instr_->temp2(),
4558 SIGNED_INT32);
4559 } 4559 }
4560 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4560 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4561 private: 4561 private:
4562 LNumberTagI* instr_; 4562 LNumberTagI* instr_;
4563 }; 4563 };
4564 4564
4565 Register src = ToRegister(instr->value()); 4565 Register src = ToRegister(instr->value());
4566 Register dst = ToRegister(instr->result()); 4566 Register dst = ToRegister(instr->result());
4567 Register overflow = scratch0(); 4567 Register overflow = scratch0();
4568 4568
4569 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); 4569 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr);
4570 __ SmiTagCheckOverflow(dst, src, overflow); 4570 __ SmiTagCheckOverflow(dst, src, overflow);
4571 __ BranchOnOverflow(deferred->entry(), overflow); 4571 __ BranchOnOverflow(deferred->entry(), overflow);
4572 __ bind(deferred->exit()); 4572 __ bind(deferred->exit());
4573 } 4573 }
4574 4574
4575 4575
4576 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { 4576 void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
4577 class DeferredNumberTagU V8_FINAL : public LDeferredCode { 4577 class DeferredNumberTagU V8_FINAL : public LDeferredCode {
4578 public: 4578 public:
4579 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) 4579 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr)
4580 : LDeferredCode(codegen), instr_(instr) { } 4580 : LDeferredCode(codegen), instr_(instr) { }
4581 virtual void Generate() V8_OVERRIDE { 4581 virtual void Generate() V8_OVERRIDE {
4582 codegen()->DoDeferredNumberTagI(instr_, 4582 codegen()->DoDeferredNumberTagIU(instr_,
4583 instr_->value(), 4583 instr_->value(),
4584 UNSIGNED_INT32); 4584 instr_->temp1(),
4585 instr_->temp2(),
4586 UNSIGNED_INT32);
4585 } 4587 }
4586 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4588 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4587 private: 4589 private:
4588 LNumberTagU* instr_; 4590 LNumberTagU* instr_;
4589 }; 4591 };
4590 4592
4591 Register input = ToRegister(instr->value()); 4593 Register input = ToRegister(instr->value());
4592 Register result = ToRegister(instr->result()); 4594 Register result = ToRegister(instr->result());
4593 4595
4594 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); 4596 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr);
4595 __ Branch(deferred->entry(), hi, input, Operand(Smi::kMaxValue)); 4597 __ Branch(deferred->entry(), hi, input, Operand(Smi::kMaxValue));
4596 __ SmiTag(result, input); 4598 __ SmiTag(result, input);
4597 __ bind(deferred->exit()); 4599 __ bind(deferred->exit());
4598 } 4600 }
4599 4601
4600 4602
4601 void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, 4603 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
4602 LOperand* value, 4604 LOperand* value,
4603 IntegerSignedness signedness) { 4605 LOperand* temp1,
4604 Label slow; 4606 LOperand* temp2,
4607 IntegerSignedness signedness) {
4608 Label done, slow;
4605 Register src = ToRegister(value); 4609 Register src = ToRegister(value);
4606 Register dst = ToRegister(instr->result()); 4610 Register dst = ToRegister(instr->result());
4611 Register tmp1 = scratch0();
4612 Register tmp2 = ToRegister(temp1);
4613 Register tmp3 = ToRegister(temp2);
4607 DoubleRegister dbl_scratch = double_scratch0(); 4614 DoubleRegister dbl_scratch = double_scratch0();
4608 4615
4609 // Preserve the value of all registers.
4610 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
4611
4612 Label done;
4613 if (signedness == SIGNED_INT32) { 4616 if (signedness == SIGNED_INT32) {
4614 // There was overflow, so bits 30 and 31 of the original integer 4617 // There was overflow, so bits 30 and 31 of the original integer
4615 // disagree. Try to allocate a heap number in new space and store 4618 // disagree. Try to allocate a heap number in new space and store
4616 // the value in there. If that fails, call the runtime system. 4619 // the value in there. If that fails, call the runtime system.
4617 if (dst.is(src)) { 4620 if (dst.is(src)) {
4618 __ SmiUntag(src, dst); 4621 __ SmiUntag(src, dst);
4619 __ Xor(src, src, Operand(0x80000000)); 4622 __ Xor(src, src, Operand(0x80000000));
4620 } 4623 }
4621 __ mtc1(src, dbl_scratch); 4624 __ mtc1(src, dbl_scratch);
4622 __ cvt_d_w(dbl_scratch, dbl_scratch); 4625 __ cvt_d_w(dbl_scratch, dbl_scratch);
4623 } else { 4626 } else {
4624 __ mtc1(src, dbl_scratch); 4627 __ mtc1(src, dbl_scratch);
4625 __ Cvt_d_uw(dbl_scratch, dbl_scratch, f22); 4628 __ Cvt_d_uw(dbl_scratch, dbl_scratch, f22);
4626 } 4629 }
4627 4630
4628 if (FLAG_inline_new) { 4631 if (FLAG_inline_new) {
4629 __ LoadRoot(scratch0(), Heap::kHeapNumberMapRootIndex); 4632 __ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex);
4630 __ AllocateHeapNumber(t1, a3, t0, scratch0(), &slow, DONT_TAG_RESULT); 4633 __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow, DONT_TAG_RESULT);
4631 __ Move(dst, t1);
4632 __ Branch(&done); 4634 __ Branch(&done);
4633 } 4635 }
4634 4636
4635 // Slow case: Call the runtime system to do the number allocation. 4637 // Slow case: Call the runtime system to do the number allocation.
4636 __ bind(&slow); 4638 __ bind(&slow);
4639 {
4640 // TODO(3095996): Put a valid pointer value in the stack slot where the
4641 // result register is stored, as this register is in the pointer map, but
4642 // contains an integer value.
4643 __ mov(dst, zero_reg);
4637 4644
4638 // TODO(3095996): Put a valid pointer value in the stack slot where the result 4645 // Preserve the value of all registers.
4639 // register is stored, as this register is in the pointer map, but contains an 4646 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
4640 // integer value. 4647
4641 __ StoreToSafepointRegisterSlot(zero_reg, dst); 4648 // NumberTagI and NumberTagD use the context from the frame, rather than
4642 // NumberTagI and NumberTagD use the context from the frame, rather than 4649 // the environment's HContext or HInlinedContext value.
4643 // the environment's HContext or HInlinedContext value. 4650 // They only call Runtime::kAllocateHeapNumber.
4644 // They only call Runtime::kAllocateHeapNumber. 4651 // The corresponding HChange instructions are added in a phase that does
4645 // The corresponding HChange instructions are added in a phase that does 4652 // not have easy access to the local context.
4646 // not have easy access to the local context. 4653 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
4647 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 4654 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4648 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 4655 RecordSafepointWithRegisters(
4649 RecordSafepointWithRegisters( 4656 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4650 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 4657 __ Subu(v0, v0, kHeapObjectTag);
4651 __ Move(dst, v0); 4658 __ StoreToSafepointRegisterSlot(v0, dst);
4652 __ Subu(dst, dst, kHeapObjectTag); 4659 }
4660
4653 4661
4654 // Done. Put the value in dbl_scratch into the value of the allocated heap 4662 // Done. Put the value in dbl_scratch into the value of the allocated heap
4655 // number. 4663 // number.
4656 __ bind(&done); 4664 __ bind(&done);
4657 __ sdc1(dbl_scratch, MemOperand(dst, HeapNumber::kValueOffset)); 4665 __ sdc1(dbl_scratch, MemOperand(dst, HeapNumber::kValueOffset));
4658 __ Addu(dst, dst, kHeapObjectTag); 4666 __ Addu(dst, dst, kHeapObjectTag);
4659 __ StoreToSafepointRegisterSlot(dst, dst);
4660 } 4667 }
4661 4668
4662 4669
4663 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { 4670 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
4664 class DeferredNumberTagD V8_FINAL : public LDeferredCode { 4671 class DeferredNumberTagD V8_FINAL : public LDeferredCode {
4665 public: 4672 public:
4666 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) 4673 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
4667 : LDeferredCode(codegen), instr_(instr) { } 4674 : LDeferredCode(codegen), instr_(instr) { }
4668 virtual void Generate() V8_OVERRIDE { 4675 virtual void Generate() V8_OVERRIDE {
4669 codegen()->DoDeferredNumberTagD(instr_); 4676 codegen()->DoDeferredNumberTagD(instr_);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
4711 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 4718 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
4712 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 4719 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4713 RecordSafepointWithRegisters( 4720 RecordSafepointWithRegisters(
4714 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 4721 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4715 __ Subu(v0, v0, kHeapObjectTag); 4722 __ Subu(v0, v0, kHeapObjectTag);
4716 __ StoreToSafepointRegisterSlot(v0, reg); 4723 __ StoreToSafepointRegisterSlot(v0, reg);
4717 } 4724 }
4718 4725
4719 4726
4720 void LCodeGen::DoSmiTag(LSmiTag* instr) { 4727 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4721 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); 4728 HChange* hchange = instr->hydrogen();
4722 __ SmiTag(ToRegister(instr->result()), ToRegister(instr->value())); 4729 Register input = ToRegister(instr->value());
4730 Register output = ToRegister(instr->result());
4731 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4732 hchange->value()->CheckFlag(HValue::kUint32)) {
4733 __ And(at, input, Operand(0xc0000000));
4734 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg));
4735 }
4736 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4737 !hchange->value()->CheckFlag(HValue::kUint32)) {
4738 __ SmiTagCheckOverflow(output, input, at);
4739 DeoptimizeIf(lt, instr->environment(), at, Operand(zero_reg));
4740 } else {
4741 __ SmiTag(output, input);
4742 }
4723 } 4743 }
4724 4744
4725 4745
4726 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 4746 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4727 Register scratch = scratch0(); 4747 Register scratch = scratch0();
4728 Register input = ToRegister(instr->value()); 4748 Register input = ToRegister(instr->value());
4729 Register result = ToRegister(instr->result()); 4749 Register result = ToRegister(instr->result());
4730 if (instr->needs_check()) { 4750 if (instr->needs_check()) {
4731 STATIC_ASSERT(kHeapObjectTag == 1); 4751 STATIC_ASSERT(kHeapObjectTag == 1);
4732 // If the input is a HeapObject, value of scratch won't be zero. 4752 // If the input is a HeapObject, value of scratch won't be zero.
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
5173 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); 5193 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg);
5174 __ jmp(&done); 5194 __ jmp(&done);
5175 5195
5176 __ bind(&is_smi); 5196 __ bind(&is_smi);
5177 __ ClampUint8(result_reg, scratch); 5197 __ ClampUint8(result_reg, scratch);
5178 5198
5179 __ bind(&done); 5199 __ bind(&done);
5180 } 5200 }
5181 5201
5182 5202
5203 void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
5204 DoubleRegister value_reg = ToDoubleRegister(instr->value());
5205 Register result_reg = ToRegister(instr->result());
5206 if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
5207 __ FmoveHigh(result_reg, value_reg);
5208 } else {
5209 __ FmoveLow(result_reg, value_reg);
5210 }
5211 }
5212
5213
5214 void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
5215 Register hi_reg = ToRegister(instr->hi());
5216 Register lo_reg = ToRegister(instr->lo());
5217 DoubleRegister result_reg = ToDoubleRegister(instr->result());
5218 __ Move(result_reg, lo_reg, hi_reg);
5219 }
5220
5221
5183 void LCodeGen::DoAllocate(LAllocate* instr) { 5222 void LCodeGen::DoAllocate(LAllocate* instr) {
5184 class DeferredAllocate V8_FINAL : public LDeferredCode { 5223 class DeferredAllocate V8_FINAL : public LDeferredCode {
5185 public: 5224 public:
5186 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) 5225 DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
5187 : LDeferredCode(codegen), instr_(instr) { } 5226 : LDeferredCode(codegen), instr_(instr) { }
5188 virtual void Generate() V8_OVERRIDE { 5227 virtual void Generate() V8_OVERRIDE {
5189 codegen()->DoDeferredAllocate(instr_); 5228 codegen()->DoDeferredAllocate(instr_);
5190 } 5229 }
5191 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 5230 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5192 private: 5231 private:
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
5352 } 5391 }
5353 } 5392 }
5354 5393
5355 5394
5356 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { 5395 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
5357 ASSERT(ToRegister(instr->context()).is(cp)); 5396 ASSERT(ToRegister(instr->context()).is(cp));
5358 // Use the fast case closure allocation code that allocates in new 5397 // Use the fast case closure allocation code that allocates in new
5359 // space for nested functions that don't need literals cloning. 5398 // space for nested functions that don't need literals cloning.
5360 bool pretenure = instr->hydrogen()->pretenure(); 5399 bool pretenure = instr->hydrogen()->pretenure();
5361 if (!pretenure && instr->hydrogen()->has_no_literals()) { 5400 if (!pretenure && instr->hydrogen()->has_no_literals()) {
5362 FastNewClosureStub stub(instr->hydrogen()->language_mode(), 5401 FastNewClosureStub stub(instr->hydrogen()->strict_mode(),
5363 instr->hydrogen()->is_generator()); 5402 instr->hydrogen()->is_generator());
5364 __ li(a2, Operand(instr->hydrogen()->shared_info())); 5403 __ li(a2, Operand(instr->hydrogen()->shared_info()));
5365 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 5404 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
5366 } else { 5405 } else {
5367 __ li(a2, Operand(instr->hydrogen()->shared_info())); 5406 __ li(a2, Operand(instr->hydrogen()->shared_info()));
5368 __ li(a1, Operand(pretenure ? factory()->true_value() 5407 __ li(a1, Operand(pretenure ? factory()->true_value()
5369 : factory()->false_value())); 5408 : factory()->false_value()));
5370 __ Push(cp, a2, a1); 5409 __ Push(cp, a2, a1);
5371 CallRuntime(Runtime::kNewClosure, 3, instr); 5410 CallRuntime(Runtime::kNewClosure, 3, instr);
5372 } 5411 }
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
5753 __ Subu(scratch, result, scratch); 5792 __ Subu(scratch, result, scratch);
5754 __ lw(result, FieldMemOperand(scratch, 5793 __ lw(result, FieldMemOperand(scratch,
5755 FixedArray::kHeaderSize - kPointerSize)); 5794 FixedArray::kHeaderSize - kPointerSize));
5756 __ bind(&done); 5795 __ bind(&done);
5757 } 5796 }
5758 5797
5759 5798
5760 #undef __ 5799 #undef __
5761 5800
5762 } } // namespace v8::internal 5801 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/mips/lithium-codegen-mips.h ('k') | src/mips/lithium-mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698