| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/hydrogen-osr.h" | 10 #include "src/hydrogen-osr.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 | 51 |
| 52 return GeneratePrologue() && GenerateBody() && GenerateDeferredCode() && | 52 return GeneratePrologue() && GenerateBody() && GenerateDeferredCode() && |
| 53 GenerateJumpTable() && GenerateSafepointTable(); | 53 GenerateJumpTable() && GenerateSafepointTable(); |
| 54 } | 54 } |
| 55 | 55 |
| 56 | 56 |
| 57 void LCodeGen::FinishCode(Handle<Code> code) { | 57 void LCodeGen::FinishCode(Handle<Code> code) { |
| 58 DCHECK(is_done()); | 58 DCHECK(is_done()); |
| 59 code->set_stack_slots(GetStackSlotCount()); | 59 code->set_stack_slots(GetStackSlotCount()); |
| 60 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 60 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
| 61 if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code); | |
| 62 PopulateDeoptimizationData(code); | 61 PopulateDeoptimizationData(code); |
| 63 } | 62 } |
| 64 | 63 |
| 65 | 64 |
| 66 void LCodeGen::SaveCallerDoubles() { | 65 void LCodeGen::SaveCallerDoubles() { |
| 67 DCHECK(info()->saves_caller_doubles()); | 66 DCHECK(info()->saves_caller_doubles()); |
| 68 DCHECK(NeedsEagerFrame()); | 67 DCHECK(NeedsEagerFrame()); |
| 69 Comment(";;; Save clobbered callee double registers"); | 68 Comment(";;; Save clobbered callee double registers"); |
| 70 int count = 0; | 69 int count = 0; |
| 71 BitVector* doubles = chunk()->allocated_double_registers(); | 70 BitVector* doubles = chunk()->allocated_double_registers(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 // r4: Callee's JS function. | 110 // r4: Callee's JS function. |
| 112 // cp: Callee's context. | 111 // cp: Callee's context. |
| 113 // pp: Callee's constant pool pointer (if FLAG_enable_ool_constant_pool) | 112 // pp: Callee's constant pool pointer (if FLAG_enable_ool_constant_pool) |
| 114 // fp: Caller's frame pointer. | 113 // fp: Caller's frame pointer. |
| 115 // lr: Caller's pc. | 114 // lr: Caller's pc. |
| 116 // ip: Our own function entry (required by the prologue) | 115 // ip: Our own function entry (required by the prologue) |
| 117 | 116 |
| 118 // Sloppy mode functions and builtins need to replace the receiver with the | 117 // Sloppy mode functions and builtins need to replace the receiver with the |
| 119 // global proxy when called as functions (without an explicit receiver | 118 // global proxy when called as functions (without an explicit receiver |
| 120 // object). | 119 // object). |
| 121 if (info_->this_has_uses() && info_->strict_mode() == SLOPPY && | 120 if (info_->this_has_uses() && is_sloppy(info_->language_mode()) && |
| 122 !info_->is_native()) { | 121 !info_->is_native()) { |
| 123 Label ok; | 122 Label ok; |
| 124 int receiver_offset = info_->scope()->num_parameters() * kPointerSize; | 123 int receiver_offset = info_->scope()->num_parameters() * kPointerSize; |
| 125 __ LoadP(r5, MemOperand(sp, receiver_offset)); | 124 __ LoadP(r5, MemOperand(sp, receiver_offset)); |
| 126 __ CompareRoot(r5, Heap::kUndefinedValueRootIndex); | 125 __ CompareRoot(r5, Heap::kUndefinedValueRootIndex); |
| 127 __ bne(&ok); | 126 __ bne(&ok); |
| 128 | 127 |
| 129 __ LoadP(r5, GlobalObjectOperand()); | 128 __ LoadP(r5, GlobalObjectOperand()); |
| 130 __ LoadP(r5, FieldMemOperand(r5, GlobalObject::kGlobalProxyOffset)); | 129 __ LoadP(r5, FieldMemOperand(r5, GlobalObject::kGlobalProxyOffset)); |
| 131 | 130 |
| (...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 765 int deoptimization_index = deoptimizations_.length(); | 764 int deoptimization_index = deoptimizations_.length(); |
| 766 int pc_offset = masm()->pc_offset(); | 765 int pc_offset = masm()->pc_offset(); |
| 767 environment->Register(deoptimization_index, translation.index(), | 766 environment->Register(deoptimization_index, translation.index(), |
| 768 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 767 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
| 769 deoptimizations_.Add(environment, zone()); | 768 deoptimizations_.Add(environment, zone()); |
| 770 } | 769 } |
| 771 } | 770 } |
| 772 | 771 |
| 773 | 772 |
| 774 void LCodeGen::DeoptimizeIf(Condition cond, LInstruction* instr, | 773 void LCodeGen::DeoptimizeIf(Condition cond, LInstruction* instr, |
| 775 const char* detail, | 774 Deoptimizer::DeoptReason deopt_reason, |
| 776 Deoptimizer::BailoutType bailout_type, | 775 Deoptimizer::BailoutType bailout_type, |
| 777 CRegister cr) { | 776 CRegister cr) { |
| 778 LEnvironment* environment = instr->environment(); | 777 LEnvironment* environment = instr->environment(); |
| 779 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 778 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 780 DCHECK(environment->HasBeenRegistered()); | 779 DCHECK(environment->HasBeenRegistered()); |
| 781 int id = environment->deoptimization_index(); | 780 int id = environment->deoptimization_index(); |
| 782 DCHECK(info()->IsOptimizing() || info()->IsStub()); | 781 DCHECK(info()->IsOptimizing() || info()->IsStub()); |
| 783 Address entry = | 782 Address entry = |
| 784 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 783 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
| 785 if (entry == NULL) { | 784 if (entry == NULL) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 807 __ bind(&no_deopt); | 806 __ bind(&no_deopt); |
| 808 __ stw(r4, MemOperand(scratch)); | 807 __ stw(r4, MemOperand(scratch)); |
| 809 __ Pop(r4, scratch); | 808 __ Pop(r4, scratch); |
| 810 } | 809 } |
| 811 | 810 |
| 812 if (info()->ShouldTrapOnDeopt()) { | 811 if (info()->ShouldTrapOnDeopt()) { |
| 813 __ stop("trap_on_deopt", cond, kDefaultStopCode, cr); | 812 __ stop("trap_on_deopt", cond, kDefaultStopCode, cr); |
| 814 } | 813 } |
| 815 | 814 |
| 816 Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(), | 815 Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(), |
| 817 instr->Mnemonic(), detail); | 816 instr->Mnemonic(), deopt_reason); |
| 818 DCHECK(info()->IsStub() || frame_is_built_); | 817 DCHECK(info()->IsStub() || frame_is_built_); |
| 819 // Go through jump table if we need to handle condition, build frame, or | 818 // Go through jump table if we need to handle condition, build frame, or |
| 820 // restore caller doubles. | 819 // restore caller doubles. |
| 821 if (cond == al && frame_is_built_ && !info()->saves_caller_doubles()) { | 820 if (cond == al && frame_is_built_ && !info()->saves_caller_doubles()) { |
| 822 DeoptComment(reason); | 821 DeoptComment(reason); |
| 823 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 822 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
| 824 } else { | 823 } else { |
| 825 Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type, | 824 Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type, |
| 826 !frame_is_built_); | 825 !frame_is_built_); |
| 827 // We often have several deopts to the same entry, reuse the last | 826 // We often have several deopts to the same entry, reuse the last |
| 828 // jump entry if this is the case. | 827 // jump entry if this is the case. |
| 829 if (jump_table_.is_empty() || | 828 if (jump_table_.is_empty() || |
| 830 !table_entry.IsEquivalentTo(jump_table_.last())) { | 829 !table_entry.IsEquivalentTo(jump_table_.last())) { |
| 831 jump_table_.Add(table_entry, zone()); | 830 jump_table_.Add(table_entry, zone()); |
| 832 } | 831 } |
| 833 __ b(cond, &jump_table_.last().label, cr); | 832 __ b(cond, &jump_table_.last().label, cr); |
| 834 } | 833 } |
| 835 } | 834 } |
| 836 | 835 |
| 837 | 836 |
| 838 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, | 837 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, |
| 839 const char* detail, CRegister cr) { | 838 Deoptimizer::DeoptReason deopt_reason, |
| 839 CRegister cr) { |
| 840 Deoptimizer::BailoutType bailout_type = | 840 Deoptimizer::BailoutType bailout_type = |
| 841 info()->IsStub() ? Deoptimizer::LAZY : Deoptimizer::EAGER; | 841 info()->IsStub() ? Deoptimizer::LAZY : Deoptimizer::EAGER; |
| 842 DeoptimizeIf(condition, instr, detail, bailout_type, cr); | 842 DeoptimizeIf(condition, instr, deopt_reason, bailout_type, cr); |
| 843 } | 843 } |
| 844 | 844 |
| 845 | 845 |
| 846 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 846 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 847 int length = deoptimizations_.length(); | 847 int length = deoptimizations_.length(); |
| 848 if (length == 0) return; | 848 if (length == 0) return; |
| 849 Handle<DeoptimizationInputData> data = | 849 Handle<DeoptimizationInputData> data = |
| 850 DeoptimizationInputData::New(isolate(), length, TENURED); | 850 DeoptimizationInputData::New(isolate(), length, TENURED); |
| 851 | 851 |
| 852 Handle<ByteArray> translations = | 852 Handle<ByteArray> translations = |
| 853 translations_.CreateByteArray(isolate()->factory()); | 853 translations_.CreateByteArray(isolate()->factory()); |
| 854 data->SetTranslationByteArray(*translations); | 854 data->SetTranslationByteArray(*translations); |
| 855 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); | 855 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); |
| 856 data->SetOptimizationId(Smi::FromInt(info_->optimization_id())); | 856 data->SetOptimizationId(Smi::FromInt(info_->optimization_id())); |
| 857 if (info_->IsOptimizing()) { | 857 if (info_->IsOptimizing()) { |
| 858 // Reference to shared function info does not change between phases. | 858 // Reference to shared function info does not change between phases. |
| 859 AllowDeferredHandleDereference allow_handle_dereference; | 859 AllowDeferredHandleDereference allow_handle_dereference; |
| 860 data->SetSharedFunctionInfo(*info_->shared_info()); | 860 data->SetSharedFunctionInfo(*info_->shared_info()); |
| 861 } else { | 861 } else { |
| 862 data->SetSharedFunctionInfo(Smi::FromInt(0)); | 862 data->SetSharedFunctionInfo(Smi::FromInt(0)); |
| 863 } | 863 } |
| 864 data->SetWeakCellCache(Smi::FromInt(0)); |
| 864 | 865 |
| 865 Handle<FixedArray> literals = | 866 Handle<FixedArray> literals = |
| 866 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); | 867 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); |
| 867 { | 868 { |
| 868 AllowDeferredHandleDereference copy_handles; | 869 AllowDeferredHandleDereference copy_handles; |
| 869 for (int i = 0; i < deoptimization_literals_.length(); i++) { | 870 for (int i = 0; i < deoptimization_literals_.length(); i++) { |
| 870 literals->set(i, *deoptimization_literals_[i]); | 871 literals->set(i, *deoptimization_literals_[i]); |
| 871 } | 872 } |
| 872 data->SetLiteralArray(*literals); | 873 data->SetLiteralArray(*literals); |
| 873 } | 874 } |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 } | 1113 } |
| 1113 } | 1114 } |
| 1114 | 1115 |
| 1115 | 1116 |
| 1116 void LCodeGen::DoModI(LModI* instr) { | 1117 void LCodeGen::DoModI(LModI* instr) { |
| 1117 HMod* hmod = instr->hydrogen(); | 1118 HMod* hmod = instr->hydrogen(); |
| 1118 Register left_reg = ToRegister(instr->left()); | 1119 Register left_reg = ToRegister(instr->left()); |
| 1119 Register right_reg = ToRegister(instr->right()); | 1120 Register right_reg = ToRegister(instr->right()); |
| 1120 Register result_reg = ToRegister(instr->result()); | 1121 Register result_reg = ToRegister(instr->result()); |
| 1121 Register scratch = scratch0(); | 1122 Register scratch = scratch0(); |
| 1123 bool can_overflow = hmod->CheckFlag(HValue::kCanOverflow); |
| 1122 Label done; | 1124 Label done; |
| 1123 | 1125 |
| 1124 if (hmod->CheckFlag(HValue::kCanOverflow)) { | 1126 if (can_overflow) { |
| 1125 __ li(r0, Operand::Zero()); // clear xer | 1127 __ li(r0, Operand::Zero()); // clear xer |
| 1126 __ mtxer(r0); | 1128 __ mtxer(r0); |
| 1127 } | 1129 } |
| 1128 | 1130 |
| 1129 __ divw(scratch, left_reg, right_reg, SetOE, SetRC); | 1131 __ divw(scratch, left_reg, right_reg, SetOE, SetRC); |
| 1130 | 1132 |
| 1131 // Check for x % 0. | 1133 // Check for x % 0. |
| 1132 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { | 1134 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1133 __ cmpwi(right_reg, Operand::Zero()); | 1135 __ cmpwi(right_reg, Operand::Zero()); |
| 1134 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero); | 1136 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero); |
| 1135 } | 1137 } |
| 1136 | 1138 |
| 1137 // Check for kMinInt % -1, divw will return undefined, which is not what we | 1139 // Check for kMinInt % -1, divw will return undefined, which is not what we |
| 1138 // want. We have to deopt if we care about -0, because we can't return that. | 1140 // want. We have to deopt if we care about -0, because we can't return that. |
| 1139 if (hmod->CheckFlag(HValue::kCanOverflow)) { | 1141 if (can_overflow) { |
| 1140 Label no_overflow_possible; | |
| 1141 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1142 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1142 DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero, cr0); | 1143 DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero, cr0); |
| 1143 } else { | 1144 } else { |
| 1144 __ bnooverflow(&no_overflow_possible, cr0); | 1145 if (CpuFeatures::IsSupported(ISELECT)) { |
| 1145 __ li(result_reg, Operand::Zero()); | 1146 __ isel(overflow, result_reg, r0, result_reg, cr0); |
| 1146 __ b(&done); | 1147 __ boverflow(&done, cr0); |
| 1148 } else { |
| 1149 Label no_overflow_possible; |
| 1150 __ bnooverflow(&no_overflow_possible, cr0); |
| 1151 __ li(result_reg, Operand::Zero()); |
| 1152 __ b(&done); |
| 1153 __ bind(&no_overflow_possible); |
| 1154 } |
| 1147 } | 1155 } |
| 1148 __ bind(&no_overflow_possible); | |
| 1149 } | 1156 } |
| 1150 | 1157 |
| 1151 __ mullw(scratch, right_reg, scratch); | 1158 __ mullw(scratch, right_reg, scratch); |
| 1152 __ sub(result_reg, left_reg, scratch, LeaveOE, SetRC); | 1159 __ sub(result_reg, left_reg, scratch, LeaveOE, SetRC); |
| 1153 | 1160 |
| 1154 // If we care about -0, test if the dividend is <0 and the result is 0. | 1161 // If we care about -0, test if the dividend is <0 and the result is 0. |
| 1155 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1162 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1156 __ bne(&done, cr0); | 1163 __ bne(&done, cr0); |
| 1157 __ cmpwi(left_reg, Operand::Zero()); | 1164 __ cmpwi(left_reg, Operand::Zero()); |
| 1158 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 1165 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1240 } | 1247 } |
| 1241 } | 1248 } |
| 1242 | 1249 |
| 1243 | 1250 |
| 1244 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. | 1251 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. |
| 1245 void LCodeGen::DoDivI(LDivI* instr) { | 1252 void LCodeGen::DoDivI(LDivI* instr) { |
| 1246 HBinaryOperation* hdiv = instr->hydrogen(); | 1253 HBinaryOperation* hdiv = instr->hydrogen(); |
| 1247 const Register dividend = ToRegister(instr->dividend()); | 1254 const Register dividend = ToRegister(instr->dividend()); |
| 1248 const Register divisor = ToRegister(instr->divisor()); | 1255 const Register divisor = ToRegister(instr->divisor()); |
| 1249 Register result = ToRegister(instr->result()); | 1256 Register result = ToRegister(instr->result()); |
| 1257 bool can_overflow = hdiv->CheckFlag(HValue::kCanOverflow); |
| 1250 | 1258 |
| 1251 DCHECK(!dividend.is(result)); | 1259 DCHECK(!dividend.is(result)); |
| 1252 DCHECK(!divisor.is(result)); | 1260 DCHECK(!divisor.is(result)); |
| 1253 | 1261 |
| 1254 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 1262 if (can_overflow) { |
| 1255 __ li(r0, Operand::Zero()); // clear xer | 1263 __ li(r0, Operand::Zero()); // clear xer |
| 1256 __ mtxer(r0); | 1264 __ mtxer(r0); |
| 1257 } | 1265 } |
| 1258 | 1266 |
| 1259 __ divw(result, dividend, divisor, SetOE, SetRC); | 1267 __ divw(result, dividend, divisor, SetOE, SetRC); |
| 1260 | 1268 |
| 1261 // Check for x / 0. | 1269 // Check for x / 0. |
| 1262 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1270 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1263 __ cmpwi(divisor, Operand::Zero()); | 1271 __ cmpwi(divisor, Operand::Zero()); |
| 1264 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero); | 1272 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero); |
| 1265 } | 1273 } |
| 1266 | 1274 |
| 1267 // Check for (0 / -x) that will produce negative zero. | 1275 // Check for (0 / -x) that will produce negative zero. |
| 1268 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1276 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1269 Label dividend_not_zero; | 1277 Label dividend_not_zero; |
| 1270 __ cmpwi(dividend, Operand::Zero()); | 1278 __ cmpwi(dividend, Operand::Zero()); |
| 1271 __ bne(÷nd_not_zero); | 1279 __ bne(÷nd_not_zero); |
| 1272 __ cmpwi(divisor, Operand::Zero()); | 1280 __ cmpwi(divisor, Operand::Zero()); |
| 1273 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 1281 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); |
| 1274 __ bind(÷nd_not_zero); | 1282 __ bind(÷nd_not_zero); |
| 1275 } | 1283 } |
| 1276 | 1284 |
| 1277 // Check for (kMinInt / -1). | 1285 // Check for (kMinInt / -1). |
| 1278 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 1286 if (can_overflow) { |
| 1279 Label no_overflow_possible; | |
| 1280 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1287 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1281 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0); | 1288 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0); |
| 1282 } else { | 1289 } else { |
| 1283 // When truncating, we want kMinInt / -1 = kMinInt. | 1290 // When truncating, we want kMinInt / -1 = kMinInt. |
| 1284 __ bnooverflow(&no_overflow_possible, cr0); | 1291 if (CpuFeatures::IsSupported(ISELECT)) { |
| 1285 __ mr(result, dividend); | 1292 __ isel(overflow, result, dividend, result, cr0); |
| 1293 } else { |
| 1294 Label no_overflow_possible; |
| 1295 __ bnooverflow(&no_overflow_possible, cr0); |
| 1296 __ mr(result, dividend); |
| 1297 __ bind(&no_overflow_possible); |
| 1298 } |
| 1286 } | 1299 } |
| 1287 __ bind(&no_overflow_possible); | |
| 1288 } | 1300 } |
| 1289 | 1301 |
| 1290 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1302 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
| 1291 // Deoptimize if remainder is not 0. | 1303 // Deoptimize if remainder is not 0. |
| 1292 Register scratch = scratch0(); | 1304 Register scratch = scratch0(); |
| 1293 __ mullw(scratch, divisor, result); | 1305 __ mullw(scratch, divisor, result); |
| 1294 __ cmpw(dividend, scratch); | 1306 __ cmpw(dividend, scratch); |
| 1295 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision); | 1307 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision); |
| 1296 } | 1308 } |
| 1297 } | 1309 } |
| 1298 | 1310 |
| 1299 | 1311 |
| 1300 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { | 1312 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { |
| 1301 HBinaryOperation* hdiv = instr->hydrogen(); | 1313 HBinaryOperation* hdiv = instr->hydrogen(); |
| 1302 Register dividend = ToRegister(instr->dividend()); | 1314 Register dividend = ToRegister(instr->dividend()); |
| 1303 Register result = ToRegister(instr->result()); | 1315 Register result = ToRegister(instr->result()); |
| 1304 int32_t divisor = instr->divisor(); | 1316 int32_t divisor = instr->divisor(); |
| 1317 bool can_overflow = hdiv->CheckFlag(HValue::kLeftCanBeMinInt); |
| 1305 | 1318 |
| 1306 // If the divisor is positive, things are easy: There can be no deopts and we | 1319 // If the divisor is positive, things are easy: There can be no deopts and we |
| 1307 // can simply do an arithmetic right shift. | 1320 // can simply do an arithmetic right shift. |
| 1308 int32_t shift = WhichPowerOf2Abs(divisor); | 1321 int32_t shift = WhichPowerOf2Abs(divisor); |
| 1309 if (divisor > 0) { | 1322 if (divisor > 0) { |
| 1310 if (shift || !result.is(dividend)) { | 1323 if (shift || !result.is(dividend)) { |
| 1311 __ srawi(result, dividend, shift); | 1324 __ srawi(result, dividend, shift); |
| 1312 } | 1325 } |
| 1313 return; | 1326 return; |
| 1314 } | 1327 } |
| 1315 | 1328 |
| 1316 // If the divisor is negative, we have to negate and handle edge cases. | 1329 // If the divisor is negative, we have to negate and handle edge cases. |
| 1317 OEBit oe = LeaveOE; | 1330 OEBit oe = LeaveOE; |
| 1318 #if V8_TARGET_ARCH_PPC64 | 1331 #if V8_TARGET_ARCH_PPC64 |
| 1319 if (divisor == -1 && hdiv->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1332 if (divisor == -1 && can_overflow) { |
| 1320 __ lis(r0, Operand(SIGN_EXT_IMM16(0x8000))); | 1333 __ lis(r0, Operand(SIGN_EXT_IMM16(0x8000))); |
| 1321 __ cmpw(dividend, r0); | 1334 __ cmpw(dividend, r0); |
| 1322 DeoptimizeIf(eq, instr, Deoptimizer::kOverflow); | 1335 DeoptimizeIf(eq, instr, Deoptimizer::kOverflow); |
| 1323 } | 1336 } |
| 1324 #else | 1337 #else |
| 1325 if (hdiv->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1338 if (can_overflow) { |
| 1326 __ li(r0, Operand::Zero()); // clear xer | 1339 __ li(r0, Operand::Zero()); // clear xer |
| 1327 __ mtxer(r0); | 1340 __ mtxer(r0); |
| 1328 oe = SetOE; | 1341 oe = SetOE; |
| 1329 } | 1342 } |
| 1330 #endif | 1343 #endif |
| 1331 | 1344 |
| 1332 __ neg(result, dividend, oe, SetRC); | 1345 __ neg(result, dividend, oe, SetRC); |
| 1333 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1346 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1334 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, cr0); | 1347 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, cr0); |
| 1335 } | 1348 } |
| 1336 | 1349 |
| 1337 // If the negation could not overflow, simply shifting is OK. | 1350 // If the negation could not overflow, simply shifting is OK. |
| 1338 #if !V8_TARGET_ARCH_PPC64 | 1351 #if !V8_TARGET_ARCH_PPC64 |
| 1339 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1352 if (!can_overflow) { |
| 1340 #endif | 1353 #endif |
| 1341 if (shift) { | 1354 if (shift) { |
| 1342 __ ShiftRightArithImm(result, result, shift); | 1355 __ ShiftRightArithImm(result, result, shift); |
| 1343 } | 1356 } |
| 1344 return; | 1357 return; |
| 1345 #if !V8_TARGET_ARCH_PPC64 | 1358 #if !V8_TARGET_ARCH_PPC64 |
| 1346 } | 1359 } |
| 1347 | 1360 |
| 1348 // Dividing by -1 is basically negation, unless we overflow. | 1361 // Dividing by -1 is basically negation, unless we overflow. |
| 1349 if (divisor == -1) { | 1362 if (divisor == -1) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1407 __ bind(&done); | 1420 __ bind(&done); |
| 1408 } | 1421 } |
| 1409 | 1422 |
| 1410 | 1423 |
| 1411 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI. | 1424 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI. |
| 1412 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { | 1425 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { |
| 1413 HBinaryOperation* hdiv = instr->hydrogen(); | 1426 HBinaryOperation* hdiv = instr->hydrogen(); |
| 1414 const Register dividend = ToRegister(instr->dividend()); | 1427 const Register dividend = ToRegister(instr->dividend()); |
| 1415 const Register divisor = ToRegister(instr->divisor()); | 1428 const Register divisor = ToRegister(instr->divisor()); |
| 1416 Register result = ToRegister(instr->result()); | 1429 Register result = ToRegister(instr->result()); |
| 1430 bool can_overflow = hdiv->CheckFlag(HValue::kCanOverflow); |
| 1417 | 1431 |
| 1418 DCHECK(!dividend.is(result)); | 1432 DCHECK(!dividend.is(result)); |
| 1419 DCHECK(!divisor.is(result)); | 1433 DCHECK(!divisor.is(result)); |
| 1420 | 1434 |
| 1421 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 1435 if (can_overflow) { |
| 1422 __ li(r0, Operand::Zero()); // clear xer | 1436 __ li(r0, Operand::Zero()); // clear xer |
| 1423 __ mtxer(r0); | 1437 __ mtxer(r0); |
| 1424 } | 1438 } |
| 1425 | 1439 |
| 1426 __ divw(result, dividend, divisor, SetOE, SetRC); | 1440 __ divw(result, dividend, divisor, SetOE, SetRC); |
| 1427 | 1441 |
| 1428 // Check for x / 0. | 1442 // Check for x / 0. |
| 1429 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1443 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1430 __ cmpwi(divisor, Operand::Zero()); | 1444 __ cmpwi(divisor, Operand::Zero()); |
| 1431 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero); | 1445 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero); |
| 1432 } | 1446 } |
| 1433 | 1447 |
| 1434 // Check for (0 / -x) that will produce negative zero. | 1448 // Check for (0 / -x) that will produce negative zero. |
| 1435 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1449 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1436 Label dividend_not_zero; | 1450 Label dividend_not_zero; |
| 1437 __ cmpwi(dividend, Operand::Zero()); | 1451 __ cmpwi(dividend, Operand::Zero()); |
| 1438 __ bne(÷nd_not_zero); | 1452 __ bne(÷nd_not_zero); |
| 1439 __ cmpwi(divisor, Operand::Zero()); | 1453 __ cmpwi(divisor, Operand::Zero()); |
| 1440 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 1454 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); |
| 1441 __ bind(÷nd_not_zero); | 1455 __ bind(÷nd_not_zero); |
| 1442 } | 1456 } |
| 1443 | 1457 |
| 1444 // Check for (kMinInt / -1). | 1458 // Check for (kMinInt / -1). |
| 1445 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 1459 if (can_overflow) { |
| 1446 Label no_overflow_possible; | |
| 1447 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1460 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1448 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0); | 1461 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0); |
| 1449 } else { | 1462 } else { |
| 1450 // When truncating, we want kMinInt / -1 = kMinInt. | 1463 // When truncating, we want kMinInt / -1 = kMinInt. |
| 1451 __ bnooverflow(&no_overflow_possible, cr0); | 1464 if (CpuFeatures::IsSupported(ISELECT)) { |
| 1452 __ mr(result, dividend); | 1465 __ isel(overflow, result, dividend, result, cr0); |
| 1466 } else { |
| 1467 Label no_overflow_possible; |
| 1468 __ bnooverflow(&no_overflow_possible, cr0); |
| 1469 __ mr(result, dividend); |
| 1470 __ bind(&no_overflow_possible); |
| 1471 } |
| 1453 } | 1472 } |
| 1454 __ bind(&no_overflow_possible); | |
| 1455 } | 1473 } |
| 1456 | 1474 |
| 1457 Label done; | 1475 Label done; |
| 1458 Register scratch = scratch0(); | 1476 Register scratch = scratch0(); |
| 1459 // If both operands have the same sign then we are done. | 1477 // If both operands have the same sign then we are done. |
| 1460 #if V8_TARGET_ARCH_PPC64 | 1478 #if V8_TARGET_ARCH_PPC64 |
| 1461 __ xor_(scratch, dividend, divisor); | 1479 __ xor_(scratch, dividend, divisor); |
| 1462 __ cmpwi(scratch, Operand::Zero()); | 1480 __ cmpwi(scratch, Operand::Zero()); |
| 1463 __ bge(&done); | 1481 __ bge(&done); |
| 1464 #else | 1482 #else |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1524 #if V8_TARGET_ARCH_PPC64 | 1542 #if V8_TARGET_ARCH_PPC64 |
| 1525 if (instr->hydrogen()->representation().IsSmi()) { | 1543 if (instr->hydrogen()->representation().IsSmi()) { |
| 1526 #endif | 1544 #endif |
| 1527 __ li(r0, Operand::Zero()); // clear xer | 1545 __ li(r0, Operand::Zero()); // clear xer |
| 1528 __ mtxer(r0); | 1546 __ mtxer(r0); |
| 1529 __ neg(result, left, SetOE, SetRC); | 1547 __ neg(result, left, SetOE, SetRC); |
| 1530 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0); | 1548 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow, cr0); |
| 1531 #if V8_TARGET_ARCH_PPC64 | 1549 #if V8_TARGET_ARCH_PPC64 |
| 1532 } else { | 1550 } else { |
| 1533 __ neg(result, left); | 1551 __ neg(result, left); |
| 1534 __ TestIfInt32(result, scratch, r0); | 1552 __ TestIfInt32(result, r0); |
| 1535 DeoptimizeIf(ne, instr, Deoptimizer::kOverflow); | 1553 DeoptimizeIf(ne, instr, Deoptimizer::kOverflow); |
| 1536 } | 1554 } |
| 1537 #endif | 1555 #endif |
| 1538 } else { | 1556 } else { |
| 1539 __ neg(result, left); | 1557 __ neg(result, left); |
| 1540 } | 1558 } |
| 1541 break; | 1559 break; |
| 1542 case 0: | 1560 case 0: |
| 1543 if (bailout_on_minus_zero) { | 1561 if (bailout_on_minus_zero) { |
| 1544 // If left is strictly negative and the constant is null, the | 1562 // If left is strictly negative and the constant is null, the |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1597 if (can_overflow) { | 1615 if (can_overflow) { |
| 1598 #if V8_TARGET_ARCH_PPC64 | 1616 #if V8_TARGET_ARCH_PPC64 |
| 1599 // result = left * right. | 1617 // result = left * right. |
| 1600 if (instr->hydrogen()->representation().IsSmi()) { | 1618 if (instr->hydrogen()->representation().IsSmi()) { |
| 1601 __ SmiUntag(result, left); | 1619 __ SmiUntag(result, left); |
| 1602 __ SmiUntag(scratch, right); | 1620 __ SmiUntag(scratch, right); |
| 1603 __ Mul(result, result, scratch); | 1621 __ Mul(result, result, scratch); |
| 1604 } else { | 1622 } else { |
| 1605 __ Mul(result, left, right); | 1623 __ Mul(result, left, right); |
| 1606 } | 1624 } |
| 1607 __ TestIfInt32(result, scratch, r0); | 1625 __ TestIfInt32(result, r0); |
| 1608 DeoptimizeIf(ne, instr, Deoptimizer::kOverflow); | 1626 DeoptimizeIf(ne, instr, Deoptimizer::kOverflow); |
| 1609 if (instr->hydrogen()->representation().IsSmi()) { | 1627 if (instr->hydrogen()->representation().IsSmi()) { |
| 1610 __ SmiTag(result); | 1628 __ SmiTag(result); |
| 1611 } | 1629 } |
| 1612 #else | 1630 #else |
| 1613 // scratch:result = left * right. | 1631 // scratch:result = left * right. |
| 1614 if (instr->hydrogen()->representation().IsSmi()) { | 1632 if (instr->hydrogen()->representation().IsSmi()) { |
| 1615 __ SmiUntag(result, left); | 1633 __ SmiUntag(result, left); |
| 1616 __ mulhw(scratch, result, right); | 1634 __ mulhw(scratch, result, right); |
| 1617 __ mullw(result, result, right); | 1635 __ mullw(result, result, right); |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1810 } | 1828 } |
| 1811 } | 1829 } |
| 1812 } | 1830 } |
| 1813 | 1831 |
| 1814 | 1832 |
| 1815 void LCodeGen::DoSubI(LSubI* instr) { | 1833 void LCodeGen::DoSubI(LSubI* instr) { |
| 1816 LOperand* right = instr->right(); | 1834 LOperand* right = instr->right(); |
| 1817 Register left = ToRegister(instr->left()); | 1835 Register left = ToRegister(instr->left()); |
| 1818 Register result = ToRegister(instr->result()); | 1836 Register result = ToRegister(instr->result()); |
| 1819 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1837 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1820 if (!can_overflow) { | 1838 #if V8_TARGET_ARCH_PPC64 |
| 1839 const bool isInteger = !instr->hydrogen()->representation().IsSmi(); |
| 1840 #else |
| 1841 const bool isInteger = false; |
| 1842 #endif |
| 1843 if (!can_overflow || isInteger) { |
| 1821 if (right->IsConstantOperand()) { | 1844 if (right->IsConstantOperand()) { |
| 1822 __ Add(result, left, -(ToOperand(right).immediate()), r0); | 1845 __ Add(result, left, -(ToOperand(right).immediate()), r0); |
| 1823 } else { | 1846 } else { |
| 1824 __ sub(result, left, EmitLoadRegister(right, ip)); | 1847 __ sub(result, left, EmitLoadRegister(right, ip)); |
| 1825 } | 1848 } |
| 1849 #if V8_TARGET_ARCH_PPC64 |
| 1850 if (can_overflow) { |
| 1851 __ TestIfInt32(result, r0); |
| 1852 DeoptimizeIf(ne, instr, Deoptimizer::kOverflow); |
| 1853 } |
| 1854 #endif |
| 1826 } else { | 1855 } else { |
| 1827 if (right->IsConstantOperand()) { | 1856 if (right->IsConstantOperand()) { |
| 1828 __ AddAndCheckForOverflow(result, left, -(ToOperand(right).immediate()), | 1857 __ AddAndCheckForOverflow(result, left, -(ToOperand(right).immediate()), |
| 1829 scratch0(), r0); | 1858 scratch0(), r0); |
| 1830 } else { | 1859 } else { |
| 1831 __ SubAndCheckForOverflow(result, left, EmitLoadRegister(right, ip), | 1860 __ SubAndCheckForOverflow(result, left, EmitLoadRegister(right, ip), |
| 1832 scratch0(), r0); | 1861 scratch0(), r0); |
| 1833 } | 1862 } |
| 1834 // Doptimize on overflow | |
| 1835 #if V8_TARGET_ARCH_PPC64 | |
| 1836 if (!instr->hydrogen()->representation().IsSmi()) { | |
| 1837 __ extsw(scratch0(), scratch0(), SetRC); | |
| 1838 } | |
| 1839 #endif | |
| 1840 DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0); | 1863 DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0); |
| 1841 } | 1864 } |
| 1842 | |
| 1843 #if V8_TARGET_ARCH_PPC64 | |
| 1844 if (!instr->hydrogen()->representation().IsSmi()) { | |
| 1845 __ extsw(result, result); | |
| 1846 } | |
| 1847 #endif | |
| 1848 } | 1865 } |
| 1849 | 1866 |
| 1850 | 1867 |
| 1851 void LCodeGen::DoRSubI(LRSubI* instr) { | 1868 void LCodeGen::DoRSubI(LRSubI* instr) { |
| 1852 LOperand* left = instr->left(); | 1869 LOperand* left = instr->left(); |
| 1853 LOperand* right = instr->right(); | 1870 LOperand* right = instr->right(); |
| 1854 LOperand* result = instr->result(); | 1871 LOperand* result = instr->result(); |
| 1855 | 1872 |
| 1856 DCHECK(!instr->hydrogen()->CheckFlag(HValue::kCanOverflow) && | 1873 DCHECK(!instr->hydrogen()->CheckFlag(HValue::kCanOverflow) && |
| 1857 right->IsConstantOperand()); | 1874 right->IsConstantOperand()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1869 void LCodeGen::DoConstantI(LConstantI* instr) { | 1886 void LCodeGen::DoConstantI(LConstantI* instr) { |
| 1870 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1887 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
| 1871 } | 1888 } |
| 1872 | 1889 |
| 1873 | 1890 |
| 1874 void LCodeGen::DoConstantS(LConstantS* instr) { | 1891 void LCodeGen::DoConstantS(LConstantS* instr) { |
| 1875 __ LoadSmiLiteral(ToRegister(instr->result()), instr->value()); | 1892 __ LoadSmiLiteral(ToRegister(instr->result()), instr->value()); |
| 1876 } | 1893 } |
| 1877 | 1894 |
| 1878 | 1895 |
| 1879 // TODO(penguin): put const to constant pool instead | |
| 1880 // of storing double to stack | |
| 1881 void LCodeGen::DoConstantD(LConstantD* instr) { | 1896 void LCodeGen::DoConstantD(LConstantD* instr) { |
| 1882 DCHECK(instr->result()->IsDoubleRegister()); | 1897 DCHECK(instr->result()->IsDoubleRegister()); |
| 1883 DoubleRegister result = ToDoubleRegister(instr->result()); | 1898 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 1899 #if V8_HOST_ARCH_IA32 |
| 1900 // Need some crappy work-around for x87 sNaN -> qNaN breakage in simulator |
| 1901 // builds. |
| 1902 uint64_t bits = instr->bits(); |
| 1903 if ((bits & V8_UINT64_C(0x7FF8000000000000)) == |
| 1904 V8_UINT64_C(0x7FF0000000000000)) { |
| 1905 uint32_t lo = static_cast<uint32_t>(bits); |
| 1906 uint32_t hi = static_cast<uint32_t>(bits >> 32); |
| 1907 __ mov(ip, Operand(lo)); |
| 1908 __ mov(scratch0(), Operand(hi)); |
| 1909 __ MovInt64ToDouble(result, scratch0(), ip); |
| 1910 return; |
| 1911 } |
| 1912 #endif |
| 1884 double v = instr->value(); | 1913 double v = instr->value(); |
| 1885 __ LoadDoubleLiteral(result, v, scratch0()); | 1914 __ LoadDoubleLiteral(result, v, scratch0()); |
| 1886 } | 1915 } |
| 1887 | 1916 |
| 1888 | 1917 |
| 1889 void LCodeGen::DoConstantE(LConstantE* instr) { | 1918 void LCodeGen::DoConstantE(LConstantE* instr) { |
| 1890 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1919 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
| 1891 } | 1920 } |
| 1892 | 1921 |
| 1893 | 1922 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2022 } | 2051 } |
| 2023 } | 2052 } |
| 2024 | 2053 |
| 2025 | 2054 |
| 2026 void LCodeGen::DoAddI(LAddI* instr) { | 2055 void LCodeGen::DoAddI(LAddI* instr) { |
| 2027 LOperand* right = instr->right(); | 2056 LOperand* right = instr->right(); |
| 2028 Register left = ToRegister(instr->left()); | 2057 Register left = ToRegister(instr->left()); |
| 2029 Register result = ToRegister(instr->result()); | 2058 Register result = ToRegister(instr->result()); |
| 2030 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 2059 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 2031 #if V8_TARGET_ARCH_PPC64 | 2060 #if V8_TARGET_ARCH_PPC64 |
| 2032 bool isInteger = !(instr->hydrogen()->representation().IsSmi() || | 2061 const bool isInteger = !(instr->hydrogen()->representation().IsSmi() || |
| 2033 instr->hydrogen()->representation().IsExternal()); | 2062 instr->hydrogen()->representation().IsExternal()); |
| 2063 #else |
| 2064 const bool isInteger = false; |
| 2034 #endif | 2065 #endif |
| 2035 | 2066 |
| 2036 if (!can_overflow) { | 2067 if (!can_overflow || isInteger) { |
| 2037 if (right->IsConstantOperand()) { | 2068 if (right->IsConstantOperand()) { |
| 2038 __ Add(result, left, ToOperand(right).immediate(), r0); | 2069 __ Add(result, left, ToOperand(right).immediate(), r0); |
| 2039 } else { | 2070 } else { |
| 2040 __ add(result, left, EmitLoadRegister(right, ip)); | 2071 __ add(result, left, EmitLoadRegister(right, ip)); |
| 2041 } | 2072 } |
| 2073 #if V8_TARGET_ARCH_PPC64 |
| 2074 if (can_overflow) { |
| 2075 __ TestIfInt32(result, r0); |
| 2076 DeoptimizeIf(ne, instr, Deoptimizer::kOverflow); |
| 2077 } |
| 2078 #endif |
| 2042 } else { | 2079 } else { |
| 2043 if (right->IsConstantOperand()) { | 2080 if (right->IsConstantOperand()) { |
| 2044 __ AddAndCheckForOverflow(result, left, ToOperand(right).immediate(), | 2081 __ AddAndCheckForOverflow(result, left, ToOperand(right).immediate(), |
| 2045 scratch0(), r0); | 2082 scratch0(), r0); |
| 2046 } else { | 2083 } else { |
| 2047 __ AddAndCheckForOverflow(result, left, EmitLoadRegister(right, ip), | 2084 __ AddAndCheckForOverflow(result, left, EmitLoadRegister(right, ip), |
| 2048 scratch0(), r0); | 2085 scratch0(), r0); |
| 2049 } | 2086 } |
| 2050 // Doptimize on overflow | |
| 2051 #if V8_TARGET_ARCH_PPC64 | |
| 2052 if (isInteger) { | |
| 2053 __ extsw(scratch0(), scratch0(), SetRC); | |
| 2054 } | |
| 2055 #endif | |
| 2056 DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0); | 2087 DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, cr0); |
| 2057 } | 2088 } |
| 2058 | |
| 2059 #if V8_TARGET_ARCH_PPC64 | |
| 2060 if (isInteger) { | |
| 2061 __ extsw(result, result); | |
| 2062 } | |
| 2063 #endif | |
| 2064 } | 2089 } |
| 2065 | 2090 |
| 2066 | 2091 |
| 2067 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 2092 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
| 2068 LOperand* left = instr->left(); | 2093 LOperand* left = instr->left(); |
| 2069 LOperand* right = instr->right(); | 2094 LOperand* right = instr->right(); |
| 2070 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 2095 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
| 2071 Condition cond = (operation == HMathMinMax::kMathMin) ? le : ge; | 2096 Condition cond = (operation == HMathMinMax::kMathMin) ? le : ge; |
| 2072 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { | 2097 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { |
| 2073 Register left_reg = ToRegister(left); | 2098 Register left_reg = ToRegister(left); |
| 2074 Register right_reg = EmitLoadRegister(right, ip); | 2099 Register right_reg = EmitLoadRegister(right, ip); |
| 2075 Register result_reg = ToRegister(instr->result()); | 2100 Register result_reg = ToRegister(instr->result()); |
| 2076 Label return_left, done; | 2101 Label return_left, done; |
| 2077 #if V8_TARGET_ARCH_PPC64 | 2102 #if V8_TARGET_ARCH_PPC64 |
| 2078 if (instr->hydrogen_value()->representation().IsSmi()) { | 2103 if (instr->hydrogen_value()->representation().IsSmi()) { |
| 2079 #endif | 2104 #endif |
| 2080 __ cmp(left_reg, right_reg); | 2105 __ cmp(left_reg, right_reg); |
| 2081 #if V8_TARGET_ARCH_PPC64 | 2106 #if V8_TARGET_ARCH_PPC64 |
| 2082 } else { | 2107 } else { |
| 2083 __ cmpw(left_reg, right_reg); | 2108 __ cmpw(left_reg, right_reg); |
| 2084 } | 2109 } |
| 2085 #endif | 2110 #endif |
| 2086 __ b(cond, &return_left); | 2111 if (CpuFeatures::IsSupported(ISELECT)) { |
| 2087 __ Move(result_reg, right_reg); | 2112 __ isel(cond, result_reg, left_reg, right_reg); |
| 2088 __ b(&done); | 2113 } else { |
| 2089 __ bind(&return_left); | 2114 __ b(cond, &return_left); |
| 2090 __ Move(result_reg, left_reg); | 2115 __ Move(result_reg, right_reg); |
| 2091 __ bind(&done); | 2116 __ b(&done); |
| 2117 __ bind(&return_left); |
| 2118 __ Move(result_reg, left_reg); |
| 2119 __ bind(&done); |
| 2120 } |
| 2092 } else { | 2121 } else { |
| 2093 DCHECK(instr->hydrogen()->representation().IsDouble()); | 2122 DCHECK(instr->hydrogen()->representation().IsDouble()); |
| 2094 DoubleRegister left_reg = ToDoubleRegister(left); | 2123 DoubleRegister left_reg = ToDoubleRegister(left); |
| 2095 DoubleRegister right_reg = ToDoubleRegister(right); | 2124 DoubleRegister right_reg = ToDoubleRegister(right); |
| 2096 DoubleRegister result_reg = ToDoubleRegister(instr->result()); | 2125 DoubleRegister result_reg = ToDoubleRegister(instr->result()); |
| 2097 Label check_nan_left, check_zero, return_left, return_right, done; | 2126 Label check_nan_left, check_zero, return_left, return_right, done; |
| 2098 __ fcmpu(left_reg, right_reg); | 2127 __ fcmpu(left_reg, right_reg); |
| 2099 __ bunordered(&check_nan_left); | 2128 __ bunordered(&check_nan_left); |
| 2100 __ beq(&check_zero); | 2129 __ beq(&check_zero); |
| 2101 __ b(cond, &return_left); | 2130 __ b(cond, &return_left); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2169 } | 2198 } |
| 2170 } | 2199 } |
| 2171 | 2200 |
| 2172 | 2201 |
| 2173 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 2202 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 2174 DCHECK(ToRegister(instr->context()).is(cp)); | 2203 DCHECK(ToRegister(instr->context()).is(cp)); |
| 2175 DCHECK(ToRegister(instr->left()).is(r4)); | 2204 DCHECK(ToRegister(instr->left()).is(r4)); |
| 2176 DCHECK(ToRegister(instr->right()).is(r3)); | 2205 DCHECK(ToRegister(instr->right()).is(r3)); |
| 2177 DCHECK(ToRegister(instr->result()).is(r3)); | 2206 DCHECK(ToRegister(instr->result()).is(r3)); |
| 2178 | 2207 |
| 2179 Handle<Code> code = | 2208 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), instr->op()).code(); |
| 2180 CodeFactory::BinaryOpIC(isolate(), instr->op(), NO_OVERWRITE).code(); | |
| 2181 CallCode(code, RelocInfo::CODE_TARGET, instr); | 2209 CallCode(code, RelocInfo::CODE_TARGET, instr); |
| 2182 } | 2210 } |
| 2183 | 2211 |
| 2184 | 2212 |
| 2185 template <class InstrType> | 2213 template <class InstrType> |
| 2186 void LCodeGen::EmitBranch(InstrType instr, Condition cond, CRegister cr) { | 2214 void LCodeGen::EmitBranch(InstrType instr, Condition cond, CRegister cr) { |
| 2187 int left_block = instr->TrueDestination(chunk_); | 2215 int left_block = instr->TrueDestination(chunk_); |
| 2188 int right_block = instr->FalseDestination(chunk_); | 2216 int right_block = instr->FalseDestination(chunk_); |
| 2189 | 2217 |
| 2190 int next_block = GetNextEmittedBlock(); | 2218 int next_block = GetNextEmittedBlock(); |
| (...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2808 | 2836 |
| 2809 | 2837 |
| 2810 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2838 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 2811 DCHECK(ToRegister(instr->context()).is(cp)); | 2839 DCHECK(ToRegister(instr->context()).is(cp)); |
| 2812 DCHECK(ToRegister(instr->left()).is(r3)); // Object is in r3. | 2840 DCHECK(ToRegister(instr->left()).is(r3)); // Object is in r3. |
| 2813 DCHECK(ToRegister(instr->right()).is(r4)); // Function is in r4. | 2841 DCHECK(ToRegister(instr->right()).is(r4)); // Function is in r4. |
| 2814 | 2842 |
| 2815 InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters); | 2843 InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters); |
| 2816 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2844 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 2817 | 2845 |
| 2818 Label equal, done; | 2846 if (CpuFeatures::IsSupported(ISELECT)) { |
| 2819 __ cmpi(r3, Operand::Zero()); | 2847 __ mov(r4, Operand(factory()->true_value())); |
| 2820 __ beq(&equal); | 2848 __ mov(r5, Operand(factory()->false_value())); |
| 2821 __ mov(r3, Operand(factory()->false_value())); | 2849 __ cmpi(r3, Operand::Zero()); |
| 2822 __ b(&done); | 2850 __ isel(eq, r3, r4, r5); |
| 2851 } else { |
| 2852 Label equal, done; |
| 2853 __ cmpi(r3, Operand::Zero()); |
| 2854 __ beq(&equal); |
| 2855 __ mov(r3, Operand(factory()->false_value())); |
| 2856 __ b(&done); |
| 2823 | 2857 |
| 2824 __ bind(&equal); | 2858 __ bind(&equal); |
| 2825 __ mov(r3, Operand(factory()->true_value())); | 2859 __ mov(r3, Operand(factory()->true_value())); |
| 2826 __ bind(&done); | 2860 __ bind(&done); |
| 2861 } |
| 2827 } | 2862 } |
| 2828 | 2863 |
| 2829 | 2864 |
| 2830 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { | 2865 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
| 2831 class DeferredInstanceOfKnownGlobal FINAL : public LDeferredCode { | 2866 class DeferredInstanceOfKnownGlobal FINAL : public LDeferredCode { |
| 2832 public: | 2867 public: |
| 2833 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, | 2868 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, |
| 2834 LInstanceOfKnownGlobal* instr) | 2869 LInstanceOfKnownGlobal* instr) |
| 2835 : LDeferredCode(codegen), instr_(instr) {} | 2870 : LDeferredCode(codegen), instr_(instr) {} |
| 2836 void Generate() OVERRIDE { | 2871 void Generate() OVERRIDE { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2915 flags | InstanceofStub::kCallSiteInlineCheck); | 2950 flags | InstanceofStub::kCallSiteInlineCheck); |
| 2916 flags = static_cast<InstanceofStub::Flags>( | 2951 flags = static_cast<InstanceofStub::Flags>( |
| 2917 flags | InstanceofStub::kReturnTrueFalseObject); | 2952 flags | InstanceofStub::kReturnTrueFalseObject); |
| 2918 InstanceofStub stub(isolate(), flags); | 2953 InstanceofStub stub(isolate(), flags); |
| 2919 | 2954 |
| 2920 PushSafepointRegistersScope scope(this); | 2955 PushSafepointRegistersScope scope(this); |
| 2921 LoadContextFromDeferred(instr->context()); | 2956 LoadContextFromDeferred(instr->context()); |
| 2922 | 2957 |
| 2923 __ Move(InstanceofStub::right(), instr->function()); | 2958 __ Move(InstanceofStub::right(), instr->function()); |
| 2924 // Include instructions below in delta: mov + call = mov + (mov + 2) | 2959 // Include instructions below in delta: mov + call = mov + (mov + 2) |
| 2925 static const int kAdditionalDelta = (2 * Assembler::kMovInstructions) + 2; | 2960 static const int kAdditionalDelta = 2 * Assembler::kMovInstructions + 2; |
| 2926 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; | 2961 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; |
| 2927 { | 2962 { |
| 2928 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 2963 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
| 2964 if (Assembler::kMovInstructions != 1 && |
| 2965 is_int16(delta * Instruction::kInstrSize)) { |
| 2966 // The following mov will be an li rather than a multi-instruction form |
| 2967 delta -= Assembler::kMovInstructions - 1; |
| 2968 } |
| 2929 // r8 is used to communicate the offset to the location of the map check. | 2969 // r8 is used to communicate the offset to the location of the map check. |
| 2930 __ mov(r8, Operand(delta * Instruction::kInstrSize)); | 2970 __ mov(r8, Operand(delta * Instruction::kInstrSize)); |
| 2931 } | 2971 } |
| 2932 CallCodeGeneric(stub.GetCode(), RelocInfo::CODE_TARGET, instr, | 2972 CallCodeGeneric(stub.GetCode(), RelocInfo::CODE_TARGET, instr, |
| 2933 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 2973 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
| 2934 DCHECK(delta == masm_->InstructionsGeneratedSince(map_check)); | 2974 DCHECK(delta == masm_->InstructionsGeneratedSince(map_check)); |
| 2935 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); | 2975 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); |
| 2936 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 2976 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 2937 // Put the result value (r3) into the result register slot and | 2977 // Put the result value (r3) into the result register slot and |
| 2938 // restore all registers. | 2978 // restore all registers. |
| 2939 __ StoreToSafepointRegisterSlot(r3, ToRegister(instr->result())); | 2979 __ StoreToSafepointRegisterSlot(r3, ToRegister(instr->result())); |
| 2940 } | 2980 } |
| 2941 | 2981 |
| 2942 | 2982 |
| 2943 void LCodeGen::DoCmpT(LCmpT* instr) { | 2983 void LCodeGen::DoCmpT(LCmpT* instr) { |
| 2944 DCHECK(ToRegister(instr->context()).is(cp)); | 2984 DCHECK(ToRegister(instr->context()).is(cp)); |
| 2945 Token::Value op = instr->op(); | 2985 Token::Value op = instr->op(); |
| 2946 | 2986 |
| 2947 Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); | 2987 Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); |
| 2948 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2988 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2949 // This instruction also signals no smi code inlined | 2989 // This instruction also signals no smi code inlined |
| 2950 __ cmpi(r3, Operand::Zero()); | 2990 __ cmpi(r3, Operand::Zero()); |
| 2951 | 2991 |
| 2952 Condition condition = ComputeCompareCondition(op); | 2992 Condition condition = ComputeCompareCondition(op); |
| 2953 Label true_value, done; | 2993 if (CpuFeatures::IsSupported(ISELECT)) { |
| 2994 __ LoadRoot(r4, Heap::kTrueValueRootIndex); |
| 2995 __ LoadRoot(r5, Heap::kFalseValueRootIndex); |
| 2996 __ isel(condition, ToRegister(instr->result()), r4, r5); |
| 2997 } else { |
| 2998 Label true_value, done; |
| 2954 | 2999 |
| 2955 __ b(condition, &true_value); | 3000 __ b(condition, &true_value); |
| 2956 | 3001 |
| 2957 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 3002 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
| 2958 __ b(&done); | 3003 __ b(&done); |
| 2959 | 3004 |
| 2960 __ bind(&true_value); | 3005 __ bind(&true_value); |
| 2961 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); | 3006 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); |
| 2962 | 3007 |
| 2963 __ bind(&done); | 3008 __ bind(&done); |
| 3009 } |
| 2964 } | 3010 } |
| 2965 | 3011 |
| 2966 | 3012 |
| 2967 void LCodeGen::DoReturn(LReturn* instr) { | 3013 void LCodeGen::DoReturn(LReturn* instr) { |
| 2968 if (FLAG_trace && info()->IsOptimizing()) { | 3014 if (FLAG_trace && info()->IsOptimizing()) { |
| 2969 // Push the return value on the stack as the parameter. | 3015 // Push the return value on the stack as the parameter. |
| 2970 // Runtime::TraceExit returns its parameter in r3. We're leaving the code | 3016 // Runtime::TraceExit returns its parameter in r3. We're leaving the code |
| 2971 // managed by the register allocator and tearing down the frame, it's | 3017 // managed by the register allocator and tearing down the frame, it's |
| 2972 // safe to write to the context register. | 3018 // safe to write to the context register. |
| 2973 __ push(r3); | 3019 __ push(r3); |
| 2974 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3020 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2975 __ CallRuntime(Runtime::kTraceExit, 1); | 3021 __ CallRuntime(Runtime::kTraceExit, 1); |
| 2976 } | 3022 } |
| 2977 if (info()->saves_caller_doubles()) { | 3023 if (info()->saves_caller_doubles()) { |
| 2978 RestoreCallerDoubles(); | 3024 RestoreCallerDoubles(); |
| 2979 } | 3025 } |
| 2980 int no_frame_start = -1; | 3026 int no_frame_start = -1; |
| 2981 if (instr->has_constant_parameter_count()) { | 3027 if (instr->has_constant_parameter_count()) { |
| 2982 int parameter_count = ToInteger32(instr->constant_parameter_count()); | 3028 int parameter_count = ToInteger32(instr->constant_parameter_count()); |
| 2983 int32_t sp_delta = (parameter_count + 1) * kPointerSize; | 3029 int32_t sp_delta = (parameter_count + 1) * kPointerSize; |
| 2984 if (NeedsEagerFrame()) { | 3030 if (NeedsEagerFrame()) { |
| 2985 no_frame_start = masm_->LeaveFrame(StackFrame::JAVA_SCRIPT, sp_delta); | 3031 no_frame_start = masm_->LeaveFrame(StackFrame::JAVA_SCRIPT, sp_delta); |
| 2986 } else if (sp_delta != 0) { | 3032 } else if (sp_delta != 0) { |
| 2987 __ addi(sp, sp, Operand(sp_delta)); | 3033 __ addi(sp, sp, Operand(sp_delta)); |
| 2988 } | 3034 } |
| 2989 } else { | 3035 } else { |
| 3036 DCHECK(info()->IsStub()); // Functions would need to drop one more value. |
| 2990 Register reg = ToRegister(instr->parameter_count()); | 3037 Register reg = ToRegister(instr->parameter_count()); |
| 2991 // The argument count parameter is a smi | 3038 // The argument count parameter is a smi |
| 2992 if (NeedsEagerFrame()) { | 3039 if (NeedsEagerFrame()) { |
| 2993 no_frame_start = masm_->LeaveFrame(StackFrame::JAVA_SCRIPT); | 3040 no_frame_start = masm_->LeaveFrame(StackFrame::JAVA_SCRIPT); |
| 2994 } | 3041 } |
| 2995 __ SmiToPtrArrayOffset(r0, reg); | 3042 __ SmiToPtrArrayOffset(r0, reg); |
| 2996 __ add(sp, sp, r0); | 3043 __ add(sp, sp, r0); |
| 2997 } | 3044 } |
| 2998 | 3045 |
| 2999 __ blr(); | 3046 __ blr(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3012 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 3059 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 3013 __ cmp(result, ip); | 3060 __ cmp(result, ip); |
| 3014 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 3061 DeoptimizeIf(eq, instr, Deoptimizer::kHole); |
| 3015 } | 3062 } |
| 3016 } | 3063 } |
| 3017 | 3064 |
| 3018 | 3065 |
| 3019 template <class T> | 3066 template <class T> |
| 3020 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { | 3067 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { |
| 3021 DCHECK(FLAG_vector_ics); | 3068 DCHECK(FLAG_vector_ics); |
| 3022 Register vector = ToRegister(instr->temp_vector()); | 3069 Register vector_register = ToRegister(instr->temp_vector()); |
| 3023 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); | 3070 Register slot_register = VectorLoadICDescriptor::SlotRegister(); |
| 3024 __ Move(vector, instr->hydrogen()->feedback_vector()); | 3071 DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister())); |
| 3072 DCHECK(slot_register.is(r3)); |
| 3073 |
| 3074 AllowDeferredHandleDereference vector_structure_check; |
| 3075 Handle<TypeFeedbackVector> vector = instr->hydrogen()->feedback_vector(); |
| 3076 __ Move(vector_register, vector); |
| 3025 // No need to allocate this register. | 3077 // No need to allocate this register. |
| 3026 DCHECK(VectorLoadICDescriptor::SlotRegister().is(r3)); | 3078 FeedbackVectorICSlot slot = instr->hydrogen()->slot(); |
| 3027 __ mov(VectorLoadICDescriptor::SlotRegister(), | 3079 int index = vector->GetIndex(slot); |
| 3028 Operand(Smi::FromInt(instr->hydrogen()->slot()))); | 3080 __ mov(slot_register, Operand(Smi::FromInt(index))); |
| 3029 } | 3081 } |
| 3030 | 3082 |
| 3031 | 3083 |
| 3032 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { | 3084 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { |
| 3033 DCHECK(ToRegister(instr->context()).is(cp)); | 3085 DCHECK(ToRegister(instr->context()).is(cp)); |
| 3034 DCHECK(ToRegister(instr->global_object()) | 3086 DCHECK(ToRegister(instr->global_object()) |
| 3035 .is(LoadDescriptor::ReceiverRegister())); | 3087 .is(LoadDescriptor::ReceiverRegister())); |
| 3036 DCHECK(ToRegister(instr->result()).is(r3)); | 3088 DCHECK(ToRegister(instr->result()).is(r3)); |
| 3037 | 3089 |
| 3038 __ mov(LoadDescriptor::NameRegister(), Operand(instr->name())); | 3090 __ mov(LoadDescriptor::NameRegister(), Operand(instr->name())); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3069 // Cells are always rescanned, so no write barrier here. | 3121 // Cells are always rescanned, so no write barrier here. |
| 3070 } | 3122 } |
| 3071 | 3123 |
| 3072 | 3124 |
| 3073 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 3125 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
| 3074 Register context = ToRegister(instr->context()); | 3126 Register context = ToRegister(instr->context()); |
| 3075 Register result = ToRegister(instr->result()); | 3127 Register result = ToRegister(instr->result()); |
| 3076 __ LoadP(result, ContextOperand(context, instr->slot_index())); | 3128 __ LoadP(result, ContextOperand(context, instr->slot_index())); |
| 3077 if (instr->hydrogen()->RequiresHoleCheck()) { | 3129 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3078 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 3130 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 3079 __ cmp(result, ip); | |
| 3080 if (instr->hydrogen()->DeoptimizesOnHole()) { | 3131 if (instr->hydrogen()->DeoptimizesOnHole()) { |
| 3132 __ cmp(result, ip); |
| 3081 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 3133 DeoptimizeIf(eq, instr, Deoptimizer::kHole); |
| 3082 } else { | 3134 } else { |
| 3083 Label skip; | 3135 if (CpuFeatures::IsSupported(ISELECT)) { |
| 3084 __ bne(&skip); | 3136 Register scratch = scratch0(); |
| 3085 __ mov(result, Operand(factory()->undefined_value())); | 3137 __ mov(scratch, Operand(factory()->undefined_value())); |
| 3086 __ bind(&skip); | 3138 __ cmp(result, ip); |
| 3139 __ isel(eq, result, scratch, result); |
| 3140 } else { |
| 3141 Label skip; |
| 3142 __ cmp(result, ip); |
| 3143 __ bne(&skip); |
| 3144 __ mov(result, Operand(factory()->undefined_value())); |
| 3145 __ bind(&skip); |
| 3146 } |
| 3087 } | 3147 } |
| 3088 } | 3148 } |
| 3089 } | 3149 } |
| 3090 | 3150 |
| 3091 | 3151 |
| 3092 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 3152 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
| 3093 Register context = ToRegister(instr->context()); | 3153 Register context = ToRegister(instr->context()); |
| 3094 Register value = ToRegister(instr->value()); | 3154 Register value = ToRegister(instr->value()); |
| 3095 Register scratch = scratch0(); | 3155 Register scratch = scratch0(); |
| 3096 MemOperand target = ContextOperand(context, instr->slot_index()); | 3156 MemOperand target = ContextOperand(context, instr->slot_index()); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3128 Register object = ToRegister(instr->object()); | 3188 Register object = ToRegister(instr->object()); |
| 3129 | 3189 |
| 3130 if (access.IsExternalMemory()) { | 3190 if (access.IsExternalMemory()) { |
| 3131 Register result = ToRegister(instr->result()); | 3191 Register result = ToRegister(instr->result()); |
| 3132 MemOperand operand = MemOperand(object, offset); | 3192 MemOperand operand = MemOperand(object, offset); |
| 3133 __ LoadRepresentation(result, operand, access.representation(), r0); | 3193 __ LoadRepresentation(result, operand, access.representation(), r0); |
| 3134 return; | 3194 return; |
| 3135 } | 3195 } |
| 3136 | 3196 |
| 3137 if (instr->hydrogen()->representation().IsDouble()) { | 3197 if (instr->hydrogen()->representation().IsDouble()) { |
| 3198 DCHECK(access.IsInobject()); |
| 3138 DoubleRegister result = ToDoubleRegister(instr->result()); | 3199 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 3139 __ lfd(result, FieldMemOperand(object, offset)); | 3200 __ lfd(result, FieldMemOperand(object, offset)); |
| 3140 return; | 3201 return; |
| 3141 } | 3202 } |
| 3142 | 3203 |
| 3143 Register result = ToRegister(instr->result()); | 3204 Register result = ToRegister(instr->result()); |
| 3144 if (!access.IsInobject()) { | 3205 if (!access.IsInobject()) { |
| 3145 __ LoadP(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 3206 __ LoadP(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 3146 object = result; | 3207 object = result; |
| 3147 } | 3208 } |
| 3148 | 3209 |
| 3149 Representation representation = access.representation(); | 3210 Representation representation = access.representation(); |
| 3150 | 3211 |
| 3151 #if V8_TARGET_ARCH_PPC64 | 3212 #if V8_TARGET_ARCH_PPC64 |
| 3152 // 64-bit Smi optimization | 3213 // 64-bit Smi optimization |
| 3153 if (representation.IsSmi() && | 3214 if (representation.IsSmi() && |
| 3154 instr->hydrogen()->representation().IsInteger32()) { | 3215 instr->hydrogen()->representation().IsInteger32()) { |
| 3155 // Read int value directly from upper half of the smi. | 3216 // Read int value directly from upper half of the smi. |
| 3156 STATIC_ASSERT(kSmiTag == 0); | 3217 offset = SmiWordOffset(offset); |
| 3157 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); | |
| 3158 #if V8_TARGET_LITTLE_ENDIAN | |
| 3159 offset += kPointerSize / 2; | |
| 3160 #endif | |
| 3161 representation = Representation::Integer32(); | 3218 representation = Representation::Integer32(); |
| 3162 } | 3219 } |
| 3163 #endif | 3220 #endif |
| 3164 | 3221 |
| 3165 __ LoadRepresentation(result, FieldMemOperand(object, offset), representation, | 3222 __ LoadRepresentation(result, FieldMemOperand(object, offset), representation, |
| 3166 r0); | 3223 r0); |
| 3167 } | 3224 } |
| 3168 | 3225 |
| 3169 | 3226 |
| 3170 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 3227 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3190 // Get the prototype or initial map from the function. | 3247 // Get the prototype or initial map from the function. |
| 3191 __ LoadP(result, | 3248 __ LoadP(result, |
| 3192 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 3249 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 3193 | 3250 |
| 3194 // Check that the function has a prototype or an initial map. | 3251 // Check that the function has a prototype or an initial map. |
| 3195 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 3252 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
| 3196 __ cmp(result, ip); | 3253 __ cmp(result, ip); |
| 3197 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 3254 DeoptimizeIf(eq, instr, Deoptimizer::kHole); |
| 3198 | 3255 |
| 3199 // If the function does not have an initial map, we're done. | 3256 // If the function does not have an initial map, we're done. |
| 3200 Label done; | 3257 if (CpuFeatures::IsSupported(ISELECT)) { |
| 3201 __ CompareObjectType(result, scratch, scratch, MAP_TYPE); | 3258 // Get the prototype from the initial map (optimistic). |
| 3202 __ bne(&done); | 3259 __ LoadP(ip, FieldMemOperand(result, Map::kPrototypeOffset)); |
| 3260 __ CompareObjectType(result, scratch, scratch, MAP_TYPE); |
| 3261 __ isel(eq, result, ip, result); |
| 3262 } else { |
| 3263 Label done; |
| 3264 __ CompareObjectType(result, scratch, scratch, MAP_TYPE); |
| 3265 __ bne(&done); |
| 3203 | 3266 |
| 3204 // Get the prototype from the initial map. | 3267 // Get the prototype from the initial map. |
| 3205 __ LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset)); | 3268 __ LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset)); |
| 3206 | 3269 |
| 3207 // All done. | 3270 // All done. |
| 3208 __ bind(&done); | 3271 __ bind(&done); |
| 3272 } |
| 3209 } | 3273 } |
| 3210 | 3274 |
| 3211 | 3275 |
| 3212 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { | 3276 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { |
| 3213 Register result = ToRegister(instr->result()); | 3277 Register result = ToRegister(instr->result()); |
| 3214 __ LoadRoot(result, instr->index()); | 3278 __ LoadRoot(result, instr->index()); |
| 3215 } | 3279 } |
| 3216 | 3280 |
| 3217 | 3281 |
| 3218 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 3282 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3312 case UINT8_CLAMPED_ELEMENTS: | 3376 case UINT8_CLAMPED_ELEMENTS: |
| 3313 if (key_is_constant) { | 3377 if (key_is_constant) { |
| 3314 __ LoadByte(result, mem_operand, r0); | 3378 __ LoadByte(result, mem_operand, r0); |
| 3315 } else { | 3379 } else { |
| 3316 __ lbzx(result, mem_operand); | 3380 __ lbzx(result, mem_operand); |
| 3317 } | 3381 } |
| 3318 break; | 3382 break; |
| 3319 case EXTERNAL_INT16_ELEMENTS: | 3383 case EXTERNAL_INT16_ELEMENTS: |
| 3320 case INT16_ELEMENTS: | 3384 case INT16_ELEMENTS: |
| 3321 if (key_is_constant) { | 3385 if (key_is_constant) { |
| 3322 __ LoadHalfWord(result, mem_operand, r0); | 3386 __ LoadHalfWordArith(result, mem_operand, r0); |
| 3323 } else { | 3387 } else { |
| 3324 __ lhzx(result, mem_operand); | 3388 __ lhax(result, mem_operand); |
| 3325 } | 3389 } |
| 3326 __ extsh(result, result); | |
| 3327 break; | 3390 break; |
| 3328 case EXTERNAL_UINT16_ELEMENTS: | 3391 case EXTERNAL_UINT16_ELEMENTS: |
| 3329 case UINT16_ELEMENTS: | 3392 case UINT16_ELEMENTS: |
| 3330 if (key_is_constant) { | 3393 if (key_is_constant) { |
| 3331 __ LoadHalfWord(result, mem_operand, r0); | 3394 __ LoadHalfWord(result, mem_operand, r0); |
| 3332 } else { | 3395 } else { |
| 3333 __ lhzx(result, mem_operand); | 3396 __ lhzx(result, mem_operand); |
| 3334 } | 3397 } |
| 3335 break; | 3398 break; |
| 3336 case EXTERNAL_INT32_ELEMENTS: | 3399 case EXTERNAL_INT32_ELEMENTS: |
| 3337 case INT32_ELEMENTS: | 3400 case INT32_ELEMENTS: |
| 3338 if (key_is_constant) { | 3401 if (key_is_constant) { |
| 3339 __ LoadWord(result, mem_operand, r0); | 3402 __ LoadWordArith(result, mem_operand, r0); |
| 3340 } else { | 3403 } else { |
| 3341 __ lwzx(result, mem_operand); | 3404 __ lwax(result, mem_operand); |
| 3342 } | 3405 } |
| 3343 #if V8_TARGET_ARCH_PPC64 | |
| 3344 __ extsw(result, result); | |
| 3345 #endif | |
| 3346 break; | 3406 break; |
| 3347 case EXTERNAL_UINT32_ELEMENTS: | 3407 case EXTERNAL_UINT32_ELEMENTS: |
| 3348 case UINT32_ELEMENTS: | 3408 case UINT32_ELEMENTS: |
| 3349 if (key_is_constant) { | 3409 if (key_is_constant) { |
| 3350 __ LoadWord(result, mem_operand, r0); | 3410 __ LoadWord(result, mem_operand, r0); |
| 3351 } else { | 3411 } else { |
| 3352 __ lwzx(result, mem_operand); | 3412 __ lwzx(result, mem_operand); |
| 3353 } | 3413 } |
| 3354 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 3414 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
| 3355 __ lis(r0, Operand(SIGN_EXT_IMM16(0x8000))); | 3415 __ lis(r0, Operand(SIGN_EXT_IMM16(0x8000))); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3450 | 3510 |
| 3451 bool requires_hole_check = hinstr->RequiresHoleCheck(); | 3511 bool requires_hole_check = hinstr->RequiresHoleCheck(); |
| 3452 Representation representation = hinstr->representation(); | 3512 Representation representation = hinstr->representation(); |
| 3453 | 3513 |
| 3454 #if V8_TARGET_ARCH_PPC64 | 3514 #if V8_TARGET_ARCH_PPC64 |
| 3455 // 64-bit Smi optimization | 3515 // 64-bit Smi optimization |
| 3456 if (representation.IsInteger32() && | 3516 if (representation.IsInteger32() && |
| 3457 hinstr->elements_kind() == FAST_SMI_ELEMENTS) { | 3517 hinstr->elements_kind() == FAST_SMI_ELEMENTS) { |
| 3458 DCHECK(!requires_hole_check); | 3518 DCHECK(!requires_hole_check); |
| 3459 // Read int value directly from upper half of the smi. | 3519 // Read int value directly from upper half of the smi. |
| 3460 STATIC_ASSERT(kSmiTag == 0); | 3520 offset = SmiWordOffset(offset); |
| 3461 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); | |
| 3462 #if V8_TARGET_LITTLE_ENDIAN | |
| 3463 offset += kPointerSize / 2; | |
| 3464 #endif | |
| 3465 } | 3521 } |
| 3466 #endif | 3522 #endif |
| 3467 | 3523 |
| 3468 __ LoadRepresentation(result, MemOperand(store_base, offset), representation, | 3524 __ LoadRepresentation(result, MemOperand(store_base, offset), representation, |
| 3469 r0); | 3525 r0); |
| 3470 | 3526 |
| 3471 // Check for the hole value. | 3527 // Check for the hole value. |
| 3472 if (requires_hole_check) { | 3528 if (requires_hole_check) { |
| 3473 if (IsFastSmiElementsKind(hinstr->elements_kind())) { | 3529 if (IsFastSmiElementsKind(hinstr->elements_kind())) { |
| 3474 __ TestIfSmi(result, r0); | 3530 __ TestIfSmi(result, r0); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3539 | 3595 |
| 3540 | 3596 |
| 3541 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 3597 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
| 3542 Register scratch = scratch0(); | 3598 Register scratch = scratch0(); |
| 3543 Register result = ToRegister(instr->result()); | 3599 Register result = ToRegister(instr->result()); |
| 3544 | 3600 |
| 3545 if (instr->hydrogen()->from_inlined()) { | 3601 if (instr->hydrogen()->from_inlined()) { |
| 3546 __ subi(result, sp, Operand(2 * kPointerSize)); | 3602 __ subi(result, sp, Operand(2 * kPointerSize)); |
| 3547 } else { | 3603 } else { |
| 3548 // Check if the calling frame is an arguments adaptor frame. | 3604 // Check if the calling frame is an arguments adaptor frame. |
| 3549 Label done, adapted; | |
| 3550 __ LoadP(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 3605 __ LoadP(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 3551 __ LoadP(result, | 3606 __ LoadP(result, |
| 3552 MemOperand(scratch, StandardFrameConstants::kContextOffset)); | 3607 MemOperand(scratch, StandardFrameConstants::kContextOffset)); |
| 3553 __ CmpSmiLiteral(result, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0); | 3608 __ CmpSmiLiteral(result, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0); |
| 3554 | 3609 |
| 3555 // Result is the frame pointer for the frame if not adapted and for the real | 3610 // Result is the frame pointer for the frame if not adapted and for the real |
| 3556 // frame below the adaptor frame if adapted. | 3611 // frame below the adaptor frame if adapted. |
| 3557 __ beq(&adapted); | 3612 if (CpuFeatures::IsSupported(ISELECT)) { |
| 3558 __ mr(result, fp); | 3613 __ isel(eq, result, scratch, fp); |
| 3559 __ b(&done); | 3614 } else { |
| 3615 Label done, adapted; |
| 3616 __ beq(&adapted); |
| 3617 __ mr(result, fp); |
| 3618 __ b(&done); |
| 3560 | 3619 |
| 3561 __ bind(&adapted); | 3620 __ bind(&adapted); |
| 3562 __ mr(result, scratch); | 3621 __ mr(result, scratch); |
| 3563 __ bind(&done); | 3622 __ bind(&done); |
| 3623 } |
| 3564 } | 3624 } |
| 3565 } | 3625 } |
| 3566 | 3626 |
| 3567 | 3627 |
| 3568 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 3628 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
| 3569 Register elem = ToRegister(instr->elements()); | 3629 Register elem = ToRegister(instr->elements()); |
| 3570 Register result = ToRegister(instr->result()); | 3630 Register result = ToRegister(instr->result()); |
| 3571 | 3631 |
| 3572 Label done; | 3632 Label done; |
| 3573 | 3633 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3628 // Normal function. Replace undefined or null with global receiver. | 3688 // Normal function. Replace undefined or null with global receiver. |
| 3629 __ LoadRoot(scratch, Heap::kNullValueRootIndex); | 3689 __ LoadRoot(scratch, Heap::kNullValueRootIndex); |
| 3630 __ cmp(receiver, scratch); | 3690 __ cmp(receiver, scratch); |
| 3631 __ beq(&global_object); | 3691 __ beq(&global_object); |
| 3632 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); | 3692 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
| 3633 __ cmp(receiver, scratch); | 3693 __ cmp(receiver, scratch); |
| 3634 __ beq(&global_object); | 3694 __ beq(&global_object); |
| 3635 | 3695 |
| 3636 // Deoptimize if the receiver is not a JS object. | 3696 // Deoptimize if the receiver is not a JS object. |
| 3637 __ TestIfSmi(receiver, r0); | 3697 __ TestIfSmi(receiver, r0); |
| 3638 DeoptimizeIf(eq, instr, Deoptimizer::kSmi); | 3698 DeoptimizeIf(eq, instr, Deoptimizer::kSmi, cr0); |
| 3639 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE); | 3699 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE); |
| 3640 DeoptimizeIf(lt, instr, Deoptimizer::kNotAJavaScriptObject); | 3700 DeoptimizeIf(lt, instr, Deoptimizer::kNotAJavaScriptObject); |
| 3641 | 3701 |
| 3642 __ b(&result_in_receiver); | 3702 __ b(&result_in_receiver); |
| 3643 __ bind(&global_object); | 3703 __ bind(&global_object); |
| 3644 __ LoadP(result, FieldMemOperand(function, JSFunction::kContextOffset)); | 3704 __ LoadP(result, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 3645 __ LoadP(result, ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); | 3705 __ LoadP(result, ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); |
| 3646 __ LoadP(result, FieldMemOperand(result, GlobalObject::kGlobalProxyOffset)); | 3706 __ LoadP(result, FieldMemOperand(result, GlobalObject::kGlobalProxyOffset)); |
| 3647 if (result.is(receiver)) { | 3707 if (result.is(receiver)) { |
| 3648 __ bind(&result_in_receiver); | 3708 __ bind(&result_in_receiver); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3742 __ Move(scratch0(), instr->hydrogen()->pairs()); | 3802 __ Move(scratch0(), instr->hydrogen()->pairs()); |
| 3743 __ push(scratch0()); | 3803 __ push(scratch0()); |
| 3744 __ LoadSmiLiteral(scratch0(), Smi::FromInt(instr->hydrogen()->flags())); | 3804 __ LoadSmiLiteral(scratch0(), Smi::FromInt(instr->hydrogen()->flags())); |
| 3745 __ push(scratch0()); | 3805 __ push(scratch0()); |
| 3746 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3806 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
| 3747 } | 3807 } |
| 3748 | 3808 |
| 3749 | 3809 |
| 3750 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3810 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| 3751 int formal_parameter_count, int arity, | 3811 int formal_parameter_count, int arity, |
| 3752 LInstruction* instr, R4State r4_state) { | 3812 LInstruction* instr) { |
| 3753 bool dont_adapt_arguments = | 3813 bool dont_adapt_arguments = |
| 3754 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3814 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
| 3755 bool can_invoke_directly = | 3815 bool can_invoke_directly = |
| 3756 dont_adapt_arguments || formal_parameter_count == arity; | 3816 dont_adapt_arguments || formal_parameter_count == arity; |
| 3757 | 3817 |
| 3818 Register function_reg = r4; |
| 3819 |
| 3758 LPointerMap* pointers = instr->pointer_map(); | 3820 LPointerMap* pointers = instr->pointer_map(); |
| 3759 | 3821 |
| 3760 if (can_invoke_directly) { | 3822 if (can_invoke_directly) { |
| 3761 if (r4_state == R4_UNINITIALIZED) { | |
| 3762 __ Move(r4, function); | |
| 3763 } | |
| 3764 | |
| 3765 // Change context. | 3823 // Change context. |
| 3766 __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); | 3824 __ LoadP(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); |
| 3767 | 3825 |
| 3768 // Set r3 to arguments count if adaption is not needed. Assumes that r3 | 3826 // Set r3 to arguments count if adaption is not needed. Assumes that r3 |
| 3769 // is available to write to at this point. | 3827 // is available to write to at this point. |
| 3770 if (dont_adapt_arguments) { | 3828 if (dont_adapt_arguments) { |
| 3771 __ mov(r3, Operand(arity)); | 3829 __ mov(r3, Operand(arity)); |
| 3772 } | 3830 } |
| 3773 | 3831 |
| 3774 bool is_self_call = function.is_identical_to(info()->closure()); | 3832 bool is_self_call = function.is_identical_to(info()->closure()); |
| 3775 | 3833 |
| 3776 // Invoke function. | 3834 // Invoke function. |
| 3777 if (is_self_call) { | 3835 if (is_self_call) { |
| 3778 __ CallSelf(); | 3836 __ CallSelf(); |
| 3779 } else { | 3837 } else { |
| 3780 __ LoadP(ip, FieldMemOperand(r4, JSFunction::kCodeEntryOffset)); | 3838 __ LoadP(ip, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset)); |
| 3781 __ CallJSEntry(ip); | 3839 __ CallJSEntry(ip); |
| 3782 } | 3840 } |
| 3783 | 3841 |
| 3784 // Set up deoptimization. | 3842 // Set up deoptimization. |
| 3785 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3843 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 3786 } else { | 3844 } else { |
| 3787 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3845 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3788 ParameterCount count(arity); | 3846 ParameterCount count(arity); |
| 3789 ParameterCount expected(formal_parameter_count); | 3847 ParameterCount expected(formal_parameter_count); |
| 3790 __ InvokeFunction(function, expected, count, CALL_FUNCTION, generator); | 3848 __ InvokeFunction(function_reg, expected, count, CALL_FUNCTION, generator); |
| 3791 } | 3849 } |
| 3792 } | 3850 } |
| 3793 | 3851 |
| 3794 | 3852 |
| 3795 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3853 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3796 DCHECK(instr->context() != NULL); | 3854 DCHECK(instr->context() != NULL); |
| 3797 DCHECK(ToRegister(instr->context()).is(cp)); | 3855 DCHECK(ToRegister(instr->context()).is(cp)); |
| 3798 Register input = ToRegister(instr->value()); | 3856 Register input = ToRegister(instr->value()); |
| 3799 Register result = ToRegister(instr->result()); | 3857 Register result = ToRegister(instr->result()); |
| 3800 Register scratch = scratch0(); | 3858 Register scratch = scratch0(); |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3984 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4042 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3985 #if V8_TARGET_ARCH_PPC64 | 4043 #if V8_TARGET_ARCH_PPC64 |
| 3986 __ MovDoubleToInt64(scratch1, input); | 4044 __ MovDoubleToInt64(scratch1, input); |
| 3987 #else | 4045 #else |
| 3988 __ MovDoubleHighToInt(scratch1, input); | 4046 __ MovDoubleHighToInt(scratch1, input); |
| 3989 #endif | 4047 #endif |
| 3990 __ cmpi(scratch1, Operand::Zero()); | 4048 __ cmpi(scratch1, Operand::Zero()); |
| 3991 // [-0.5, -0]. | 4049 // [-0.5, -0]. |
| 3992 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 4050 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); |
| 3993 } | 4051 } |
| 3994 Label return_zero; | |
| 3995 __ fcmpu(input, dot_five); | 4052 __ fcmpu(input, dot_five); |
| 3996 __ bne(&return_zero); | 4053 if (CpuFeatures::IsSupported(ISELECT)) { |
| 3997 __ li(result, Operand(1)); // +0.5. | 4054 __ li(result, Operand(1)); |
| 3998 __ b(&done); | 4055 __ isel(lt, result, r0, result); |
| 3999 // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on | 4056 __ b(&done); |
| 4000 // flag kBailoutOnMinusZero. | 4057 } else { |
| 4001 __ bind(&return_zero); | 4058 Label return_zero; |
| 4002 __ li(result, Operand::Zero()); | 4059 __ bne(&return_zero); |
| 4003 __ b(&done); | 4060 __ li(result, Operand(1)); // +0.5. |
| 4061 __ b(&done); |
| 4062 // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on |
| 4063 // flag kBailoutOnMinusZero. |
| 4064 __ bind(&return_zero); |
| 4065 __ li(result, Operand::Zero()); |
| 4066 __ b(&done); |
| 4067 } |
| 4004 | 4068 |
| 4005 __ bind(&convert); | 4069 __ bind(&convert); |
| 4006 __ fadd(input_plus_dot_five, input, dot_five); | 4070 __ fadd(input_plus_dot_five, input, dot_five); |
| 4007 // Reuse dot_five (double_scratch0) as we no longer need this value. | 4071 // Reuse dot_five (double_scratch0) as we no longer need this value. |
| 4008 __ TryInt32Floor(result, input_plus_dot_five, scratch1, scratch2, | 4072 __ TryInt32Floor(result, input_plus_dot_five, scratch1, scratch2, |
| 4009 double_scratch0(), &done, &done); | 4073 double_scratch0(), &done, &done); |
| 4010 DeoptimizeIf(al, instr, Deoptimizer::kLostPrecisionOrNaN); | 4074 DeoptimizeIf(al, instr, Deoptimizer::kLostPrecisionOrNaN); |
| 4011 __ bind(&done); | 4075 __ bind(&done); |
| 4012 } | 4076 } |
| 4013 | 4077 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4047 __ fadd(result, input, kDoubleRegZero); | 4111 __ fadd(result, input, kDoubleRegZero); |
| 4048 __ fsqrt(result, result); | 4112 __ fsqrt(result, result); |
| 4049 __ bind(&done); | 4113 __ bind(&done); |
| 4050 } | 4114 } |
| 4051 | 4115 |
| 4052 | 4116 |
| 4053 void LCodeGen::DoPower(LPower* instr) { | 4117 void LCodeGen::DoPower(LPower* instr) { |
| 4054 Representation exponent_type = instr->hydrogen()->right()->representation(); | 4118 Representation exponent_type = instr->hydrogen()->right()->representation(); |
| 4055 // Having marked this as a call, we can use any registers. | 4119 // Having marked this as a call, we can use any registers. |
| 4056 // Just make sure that the input/output registers are the expected ones. | 4120 // Just make sure that the input/output registers are the expected ones. |
| 4057 #ifdef DEBUG | |
| 4058 Register tagged_exponent = MathPowTaggedDescriptor::exponent(); | 4121 Register tagged_exponent = MathPowTaggedDescriptor::exponent(); |
| 4059 #endif | |
| 4060 DCHECK(!instr->right()->IsDoubleRegister() || | 4122 DCHECK(!instr->right()->IsDoubleRegister() || |
| 4061 ToDoubleRegister(instr->right()).is(d2)); | 4123 ToDoubleRegister(instr->right()).is(d2)); |
| 4062 DCHECK(!instr->right()->IsRegister() || | 4124 DCHECK(!instr->right()->IsRegister() || |
| 4063 ToRegister(instr->right()).is(tagged_exponent)); | 4125 ToRegister(instr->right()).is(tagged_exponent)); |
| 4064 DCHECK(ToDoubleRegister(instr->left()).is(d1)); | 4126 DCHECK(ToDoubleRegister(instr->left()).is(d1)); |
| 4065 DCHECK(ToDoubleRegister(instr->result()).is(d3)); | 4127 DCHECK(ToDoubleRegister(instr->result()).is(d3)); |
| 4066 | 4128 |
| 4067 if (exponent_type.IsSmi()) { | 4129 if (exponent_type.IsSmi()) { |
| 4068 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 4130 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
| 4069 __ CallStub(&stub); | 4131 __ CallStub(&stub); |
| 4070 } else if (exponent_type.IsTagged()) { | 4132 } else if (exponent_type.IsTagged()) { |
| 4071 Label no_deopt; | 4133 Label no_deopt; |
| 4072 __ JumpIfSmi(r5, &no_deopt); | 4134 __ JumpIfSmi(tagged_exponent, &no_deopt); |
| 4073 __ LoadP(r10, FieldMemOperand(r5, HeapObject::kMapOffset)); | 4135 DCHECK(!r10.is(tagged_exponent)); |
| 4136 __ LoadP(r10, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset)); |
| 4074 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 4137 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 4075 __ cmp(r10, ip); | 4138 __ cmp(r10, ip); |
| 4076 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber); | 4139 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber); |
| 4077 __ bind(&no_deopt); | 4140 __ bind(&no_deopt); |
| 4078 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 4141 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
| 4079 __ CallStub(&stub); | 4142 __ CallStub(&stub); |
| 4080 } else if (exponent_type.IsInteger32()) { | 4143 } else if (exponent_type.IsInteger32()) { |
| 4081 MathPowStub stub(isolate(), MathPowStub::INTEGER); | 4144 MathPowStub stub(isolate(), MathPowStub::INTEGER); |
| 4082 __ CallStub(&stub); | 4145 __ CallStub(&stub); |
| 4083 } else { | 4146 } else { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4124 | 4187 |
| 4125 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 4188 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 4126 if (known_function.is_null()) { | 4189 if (known_function.is_null()) { |
| 4127 LPointerMap* pointers = instr->pointer_map(); | 4190 LPointerMap* pointers = instr->pointer_map(); |
| 4128 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 4191 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 4129 ParameterCount count(instr->arity()); | 4192 ParameterCount count(instr->arity()); |
| 4130 __ InvokeFunction(r4, count, CALL_FUNCTION, generator); | 4193 __ InvokeFunction(r4, count, CALL_FUNCTION, generator); |
| 4131 } else { | 4194 } else { |
| 4132 CallKnownFunction(known_function, | 4195 CallKnownFunction(known_function, |
| 4133 instr->hydrogen()->formal_parameter_count(), | 4196 instr->hydrogen()->formal_parameter_count(), |
| 4134 instr->arity(), instr, R4_CONTAINS_TARGET); | 4197 instr->arity(), instr); |
| 4135 } | 4198 } |
| 4136 } | 4199 } |
| 4137 | 4200 |
| 4138 | 4201 |
| 4139 void LCodeGen::DoTailCallThroughMegamorphicCache( | 4202 void LCodeGen::DoTailCallThroughMegamorphicCache( |
| 4140 LTailCallThroughMegamorphicCache* instr) { | 4203 LTailCallThroughMegamorphicCache* instr) { |
| 4141 Register receiver = ToRegister(instr->receiver()); | 4204 Register receiver = ToRegister(instr->receiver()); |
| 4142 Register name = ToRegister(instr->name()); | 4205 Register name = ToRegister(instr->name()); |
| 4143 DCHECK(receiver.is(LoadDescriptor::ReceiverRegister())); | 4206 DCHECK(receiver.is(LoadDescriptor::ReceiverRegister())); |
| 4144 DCHECK(name.is(LoadDescriptor::NameRegister())); | 4207 DCHECK(name.is(LoadDescriptor::NameRegister())); |
| 4145 DCHECK(receiver.is(r4)); | 4208 DCHECK(receiver.is(r4)); |
| 4146 DCHECK(name.is(r5)); | 4209 DCHECK(name.is(r5)); |
| 4210 Register scratch = r7; |
| 4211 Register extra = r8; |
| 4212 Register extra2 = r9; |
| 4213 Register extra3 = r10; |
| 4147 | 4214 |
| 4148 Register scratch = r6; | 4215 #ifdef DEBUG |
| 4149 Register extra = r7; | 4216 Register slot = FLAG_vector_ics ? ToRegister(instr->slot()) : no_reg; |
| 4150 Register extra2 = r8; | 4217 Register vector = FLAG_vector_ics ? ToRegister(instr->vector()) : no_reg; |
| 4151 Register extra3 = r9; | 4218 DCHECK(!FLAG_vector_ics || |
| 4219 !AreAliased(slot, vector, scratch, extra, extra2, extra3)); |
| 4220 #endif |
| 4152 | 4221 |
| 4153 // Important for the tail-call. | 4222 // Important for the tail-call. |
| 4154 bool must_teardown_frame = NeedsEagerFrame(); | 4223 bool must_teardown_frame = NeedsEagerFrame(); |
| 4155 | 4224 |
| 4156 // The probe will tail call to a handler if found. | 4225 if (!instr->hydrogen()->is_just_miss()) { |
| 4157 isolate()->stub_cache()->GenerateProbe(masm(), instr->hydrogen()->flags(), | 4226 DCHECK(!instr->hydrogen()->is_keyed_load()); |
| 4158 must_teardown_frame, receiver, name, | 4227 |
| 4159 scratch, extra, extra2, extra3); | 4228 // The probe will tail call to a handler if found. |
| 4229 isolate()->stub_cache()->GenerateProbe( |
| 4230 masm(), Code::LOAD_IC, instr->hydrogen()->flags(), must_teardown_frame, |
| 4231 receiver, name, scratch, extra, extra2, extra3); |
| 4232 } |
| 4160 | 4233 |
| 4161 // Tail call to miss if we ended up here. | 4234 // Tail call to miss if we ended up here. |
| 4162 if (must_teardown_frame) __ LeaveFrame(StackFrame::INTERNAL); | 4235 if (must_teardown_frame) __ LeaveFrame(StackFrame::INTERNAL); |
| 4163 LoadIC::GenerateMiss(masm()); | 4236 if (instr->hydrogen()->is_keyed_load()) { |
| 4237 KeyedLoadIC::GenerateMiss(masm()); |
| 4238 } else { |
| 4239 LoadIC::GenerateMiss(masm()); |
| 4240 } |
| 4164 } | 4241 } |
| 4165 | 4242 |
| 4166 | 4243 |
| 4167 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { | 4244 void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) { |
| 4168 DCHECK(ToRegister(instr->result()).is(r3)); | 4245 DCHECK(ToRegister(instr->result()).is(r3)); |
| 4169 | 4246 |
| 4170 LPointerMap* pointers = instr->pointer_map(); | 4247 if (instr->hydrogen()->IsTailCall()) { |
| 4171 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 4248 if (NeedsEagerFrame()) __ LeaveFrame(StackFrame::INTERNAL); |
| 4172 | 4249 |
| 4173 if (instr->target()->IsConstantOperand()) { | 4250 if (instr->target()->IsConstantOperand()) { |
| 4174 LConstantOperand* target = LConstantOperand::cast(instr->target()); | 4251 LConstantOperand* target = LConstantOperand::cast(instr->target()); |
| 4175 Handle<Code> code = Handle<Code>::cast(ToHandle(target)); | 4252 Handle<Code> code = Handle<Code>::cast(ToHandle(target)); |
| 4176 generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET)); | 4253 __ Jump(code, RelocInfo::CODE_TARGET); |
| 4177 __ Call(code, RelocInfo::CODE_TARGET); | 4254 } else { |
| 4255 DCHECK(instr->target()->IsRegister()); |
| 4256 Register target = ToRegister(instr->target()); |
| 4257 __ addi(ip, target, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 4258 __ JumpToJSEntry(ip); |
| 4259 } |
| 4178 } else { | 4260 } else { |
| 4179 DCHECK(instr->target()->IsRegister()); | 4261 LPointerMap* pointers = instr->pointer_map(); |
| 4180 Register target = ToRegister(instr->target()); | 4262 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 4181 generator.BeforeCall(__ CallSize(target)); | 4263 |
| 4182 __ addi(ip, target, Operand(Code::kHeaderSize - kHeapObjectTag)); | 4264 if (instr->target()->IsConstantOperand()) { |
| 4183 __ CallJSEntry(ip); | 4265 LConstantOperand* target = LConstantOperand::cast(instr->target()); |
| 4266 Handle<Code> code = Handle<Code>::cast(ToHandle(target)); |
| 4267 generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET)); |
| 4268 __ Call(code, RelocInfo::CODE_TARGET); |
| 4269 } else { |
| 4270 DCHECK(instr->target()->IsRegister()); |
| 4271 Register target = ToRegister(instr->target()); |
| 4272 generator.BeforeCall(__ CallSize(target)); |
| 4273 __ addi(ip, target, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 4274 __ CallJSEntry(ip); |
| 4275 } |
| 4276 generator.AfterCall(); |
| 4184 } | 4277 } |
| 4185 generator.AfterCall(); | |
| 4186 } | 4278 } |
| 4187 | 4279 |
| 4188 | 4280 |
| 4189 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { | 4281 void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) { |
| 4190 DCHECK(ToRegister(instr->function()).is(r4)); | 4282 DCHECK(ToRegister(instr->function()).is(r4)); |
| 4191 DCHECK(ToRegister(instr->result()).is(r3)); | 4283 DCHECK(ToRegister(instr->result()).is(r3)); |
| 4192 | 4284 |
| 4193 if (instr->hydrogen()->pass_argument_count()) { | 4285 if (instr->hydrogen()->pass_argument_count()) { |
| 4194 __ mov(r3, Operand(instr->arity())); | 4286 __ mov(r3, Operand(instr->arity())); |
| 4195 } | 4287 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4215 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 4307 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 4216 } | 4308 } |
| 4217 | 4309 |
| 4218 | 4310 |
| 4219 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 4311 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 4220 DCHECK(ToRegister(instr->context()).is(cp)); | 4312 DCHECK(ToRegister(instr->context()).is(cp)); |
| 4221 DCHECK(ToRegister(instr->function()).is(r4)); | 4313 DCHECK(ToRegister(instr->function()).is(r4)); |
| 4222 DCHECK(ToRegister(instr->result()).is(r3)); | 4314 DCHECK(ToRegister(instr->result()).is(r3)); |
| 4223 | 4315 |
| 4224 int arity = instr->arity(); | 4316 int arity = instr->arity(); |
| 4225 CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags()); | 4317 CallFunctionFlags flags = instr->hydrogen()->function_flags(); |
| 4226 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 4318 if (instr->hydrogen()->HasVectorAndSlot()) { |
| 4319 Register slot_register = ToRegister(instr->temp_slot()); |
| 4320 Register vector_register = ToRegister(instr->temp_vector()); |
| 4321 DCHECK(slot_register.is(r6)); |
| 4322 DCHECK(vector_register.is(r5)); |
| 4323 |
| 4324 AllowDeferredHandleDereference vector_structure_check; |
| 4325 Handle<TypeFeedbackVector> vector = instr->hydrogen()->feedback_vector(); |
| 4326 int index = vector->GetIndex(instr->hydrogen()->slot()); |
| 4327 |
| 4328 __ Move(vector_register, vector); |
| 4329 __ LoadSmiLiteral(slot_register, Smi::FromInt(index)); |
| 4330 |
| 4331 CallICState::CallType call_type = |
| 4332 (flags & CALL_AS_METHOD) ? CallICState::METHOD : CallICState::FUNCTION; |
| 4333 |
| 4334 Handle<Code> ic = |
| 4335 CodeFactory::CallICInOptimizedCode(isolate(), arity, call_type).code(); |
| 4336 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4337 } else { |
| 4338 CallFunctionStub stub(isolate(), arity, flags); |
| 4339 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 4340 } |
| 4227 } | 4341 } |
| 4228 | 4342 |
| 4229 | 4343 |
| 4230 void LCodeGen::DoCallNew(LCallNew* instr) { | 4344 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 4231 DCHECK(ToRegister(instr->context()).is(cp)); | 4345 DCHECK(ToRegister(instr->context()).is(cp)); |
| 4232 DCHECK(ToRegister(instr->constructor()).is(r4)); | 4346 DCHECK(ToRegister(instr->constructor()).is(r4)); |
| 4233 DCHECK(ToRegister(instr->result()).is(r3)); | 4347 DCHECK(ToRegister(instr->result()).is(r3)); |
| 4234 | 4348 |
| 4235 __ mov(r3, Operand(instr->arity())); | 4349 __ mov(r3, Operand(instr->arity())); |
| 4236 // No cell in r5 for construct type feedback in optimized code | 4350 // No cell in r5 for construct type feedback in optimized code |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4330 | 4444 |
| 4331 __ AssertNotSmi(object); | 4445 __ AssertNotSmi(object); |
| 4332 | 4446 |
| 4333 #if V8_TARGET_ARCH_PPC64 | 4447 #if V8_TARGET_ARCH_PPC64 |
| 4334 DCHECK(!representation.IsSmi() || !instr->value()->IsConstantOperand() || | 4448 DCHECK(!representation.IsSmi() || !instr->value()->IsConstantOperand() || |
| 4335 IsInteger32(LConstantOperand::cast(instr->value()))); | 4449 IsInteger32(LConstantOperand::cast(instr->value()))); |
| 4336 #else | 4450 #else |
| 4337 DCHECK(!representation.IsSmi() || !instr->value()->IsConstantOperand() || | 4451 DCHECK(!representation.IsSmi() || !instr->value()->IsConstantOperand() || |
| 4338 IsSmi(LConstantOperand::cast(instr->value()))); | 4452 IsSmi(LConstantOperand::cast(instr->value()))); |
| 4339 #endif | 4453 #endif |
| 4340 if (representation.IsDouble()) { | 4454 if (!FLAG_unbox_double_fields && representation.IsDouble()) { |
| 4341 DCHECK(access.IsInobject()); | 4455 DCHECK(access.IsInobject()); |
| 4342 DCHECK(!hinstr->has_transition()); | 4456 DCHECK(!hinstr->has_transition()); |
| 4343 DCHECK(!hinstr->NeedsWriteBarrier()); | 4457 DCHECK(!hinstr->NeedsWriteBarrier()); |
| 4344 DoubleRegister value = ToDoubleRegister(instr->value()); | 4458 DoubleRegister value = ToDoubleRegister(instr->value()); |
| 4345 __ stfd(value, FieldMemOperand(object, offset)); | 4459 __ stfd(value, FieldMemOperand(object, offset)); |
| 4346 return; | 4460 return; |
| 4347 } | 4461 } |
| 4348 | 4462 |
| 4349 if (hinstr->has_transition()) { | 4463 if (hinstr->has_transition()) { |
| 4350 Handle<Map> transition = hinstr->transition_map(); | 4464 Handle<Map> transition = hinstr->transition_map(); |
| 4351 AddDeprecationDependency(transition); | 4465 AddDeprecationDependency(transition); |
| 4352 __ mov(scratch, Operand(transition)); | 4466 __ mov(scratch, Operand(transition)); |
| 4353 __ StoreP(scratch, FieldMemOperand(object, HeapObject::kMapOffset), r0); | 4467 __ StoreP(scratch, FieldMemOperand(object, HeapObject::kMapOffset), r0); |
| 4354 if (hinstr->NeedsWriteBarrierForMap()) { | 4468 if (hinstr->NeedsWriteBarrierForMap()) { |
| 4355 Register temp = ToRegister(instr->temp()); | 4469 Register temp = ToRegister(instr->temp()); |
| 4356 // Update the write barrier for the map field. | 4470 // Update the write barrier for the map field. |
| 4357 __ RecordWriteForMap(object, scratch, temp, GetLinkRegisterState(), | 4471 __ RecordWriteForMap(object, scratch, temp, GetLinkRegisterState(), |
| 4358 kSaveFPRegs); | 4472 kSaveFPRegs); |
| 4359 } | 4473 } |
| 4360 } | 4474 } |
| 4361 | 4475 |
| 4362 // Do the store. | 4476 // Do the store. |
| 4363 Register value = ToRegister(instr->value()); | 4477 Register record_dest = object; |
| 4364 | 4478 Register record_value = no_reg; |
| 4479 Register record_scratch = scratch; |
| 4365 #if V8_TARGET_ARCH_PPC64 | 4480 #if V8_TARGET_ARCH_PPC64 |
| 4366 // 64-bit Smi optimization | 4481 if (FLAG_unbox_double_fields && representation.IsDouble()) { |
| 4367 if (representation.IsSmi() && | 4482 DCHECK(access.IsInobject()); |
| 4368 hinstr->value()->representation().IsInteger32()) { | 4483 DoubleRegister value = ToDoubleRegister(instr->value()); |
| 4369 DCHECK(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); | 4484 __ stfd(value, FieldMemOperand(object, offset)); |
| 4370 // Store int value directly to upper half of the smi. | 4485 if (hinstr->NeedsWriteBarrier()) { |
| 4371 STATIC_ASSERT(kSmiTag == 0); | 4486 record_value = ToRegister(instr->value()); |
| 4372 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 4487 } |
| 4373 #if V8_TARGET_LITTLE_ENDIAN | 4488 } else { |
| 4374 offset += kPointerSize / 2; | 4489 if (representation.IsSmi() && |
| 4490 hinstr->value()->representation().IsInteger32()) { |
| 4491 DCHECK(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); |
| 4492 // 64-bit Smi optimization |
| 4493 // Store int value directly to upper half of the smi. |
| 4494 offset = SmiWordOffset(offset); |
| 4495 representation = Representation::Integer32(); |
| 4496 } |
| 4375 #endif | 4497 #endif |
| 4376 representation = Representation::Integer32(); | 4498 if (access.IsInobject()) { |
| 4499 Register value = ToRegister(instr->value()); |
| 4500 MemOperand operand = FieldMemOperand(object, offset); |
| 4501 __ StoreRepresentation(value, operand, representation, r0); |
| 4502 record_value = value; |
| 4503 } else { |
| 4504 Register value = ToRegister(instr->value()); |
| 4505 __ LoadP(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| 4506 MemOperand operand = FieldMemOperand(scratch, offset); |
| 4507 __ StoreRepresentation(value, operand, representation, r0); |
| 4508 record_dest = scratch; |
| 4509 record_value = value; |
| 4510 record_scratch = object; |
| 4511 } |
| 4512 #if V8_TARGET_ARCH_PPC64 |
| 4377 } | 4513 } |
| 4378 #endif | 4514 #endif |
| 4379 | 4515 |
| 4380 if (access.IsInobject()) { | 4516 if (hinstr->NeedsWriteBarrier()) { |
| 4381 MemOperand operand = FieldMemOperand(object, offset); | 4517 __ RecordWriteField(record_dest, offset, record_value, record_scratch, |
| 4382 __ StoreRepresentation(value, operand, representation, r0); | 4518 GetLinkRegisterState(), kSaveFPRegs, |
| 4383 if (hinstr->NeedsWriteBarrier()) { | 4519 EMIT_REMEMBERED_SET, hinstr->SmiCheckForWriteBarrier(), |
| 4384 // Update the write barrier for the object for in-object properties. | 4520 hinstr->PointersToHereCheckForValue()); |
| 4385 __ RecordWriteField( | |
| 4386 object, offset, value, scratch, GetLinkRegisterState(), kSaveFPRegs, | |
| 4387 EMIT_REMEMBERED_SET, hinstr->SmiCheckForWriteBarrier(), | |
| 4388 hinstr->PointersToHereCheckForValue()); | |
| 4389 } | |
| 4390 } else { | |
| 4391 __ LoadP(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); | |
| 4392 MemOperand operand = FieldMemOperand(scratch, offset); | |
| 4393 __ StoreRepresentation(value, operand, representation, r0); | |
| 4394 if (hinstr->NeedsWriteBarrier()) { | |
| 4395 // Update the write barrier for the properties array. | |
| 4396 // object is used as a scratch register. | |
| 4397 __ RecordWriteField( | |
| 4398 scratch, offset, value, object, GetLinkRegisterState(), kSaveFPRegs, | |
| 4399 EMIT_REMEMBERED_SET, hinstr->SmiCheckForWriteBarrier(), | |
| 4400 hinstr->PointersToHereCheckForValue()); | |
| 4401 } | |
| 4402 } | 4521 } |
| 4403 } | 4522 } |
| 4404 | 4523 |
| 4405 | 4524 |
| 4406 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 4525 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
| 4407 DCHECK(ToRegister(instr->context()).is(cp)); | 4526 DCHECK(ToRegister(instr->context()).is(cp)); |
| 4408 DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister())); | 4527 DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister())); |
| 4409 DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister())); | 4528 DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister())); |
| 4410 | 4529 |
| 4411 __ mov(StoreDescriptor::NameRegister(), Operand(instr->name())); | 4530 __ mov(StoreDescriptor::NameRegister(), Operand(instr->name())); |
| 4412 Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode()); | 4531 Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->language_mode()); |
| 4413 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4532 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4414 } | 4533 } |
| 4415 | 4534 |
| 4416 | 4535 |
| 4417 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 4536 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
| 4418 Representation representation = instr->hydrogen()->length()->representation(); | 4537 Representation representation = instr->hydrogen()->length()->representation(); |
| 4419 DCHECK(representation.Equals(instr->hydrogen()->index()->representation())); | 4538 DCHECK(representation.Equals(instr->hydrogen()->index()->representation())); |
| 4420 DCHECK(representation.IsSmiOrInteger32()); | 4539 DCHECK(representation.IsSmiOrInteger32()); |
| 4421 | 4540 |
| 4422 Condition cc = instr->hydrogen()->allow_equality() ? lt : le; | 4541 Condition cc = instr->hydrogen()->allow_equality() ? lt : le; |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4583 __ add(scratch, elements, scratch); | 4702 __ add(scratch, elements, scratch); |
| 4584 elements = scratch; | 4703 elements = scratch; |
| 4585 } | 4704 } |
| 4586 if (!is_int16(base_offset)) { | 4705 if (!is_int16(base_offset)) { |
| 4587 __ Add(scratch, elements, base_offset, r0); | 4706 __ Add(scratch, elements, base_offset, r0); |
| 4588 base_offset = 0; | 4707 base_offset = 0; |
| 4589 elements = scratch; | 4708 elements = scratch; |
| 4590 } | 4709 } |
| 4591 | 4710 |
| 4592 if (instr->NeedsCanonicalization()) { | 4711 if (instr->NeedsCanonicalization()) { |
| 4593 // Force a canonical NaN. | 4712 // Turn potential sNaN value into qNaN. |
| 4594 __ CanonicalizeNaN(double_scratch, value); | 4713 __ CanonicalizeNaN(double_scratch, value); |
| 4595 __ stfd(double_scratch, MemOperand(elements, base_offset)); | 4714 __ stfd(double_scratch, MemOperand(elements, base_offset)); |
| 4596 } else { | 4715 } else { |
| 4597 __ stfd(value, MemOperand(elements, base_offset)); | 4716 __ stfd(value, MemOperand(elements, base_offset)); |
| 4598 } | 4717 } |
| 4599 } | 4718 } |
| 4600 | 4719 |
| 4601 | 4720 |
| 4602 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { | 4721 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
| 4603 HStoreKeyed* hinstr = instr->hydrogen(); | 4722 HStoreKeyed* hinstr = instr->hydrogen(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 4628 } | 4747 } |
| 4629 | 4748 |
| 4630 Representation representation = hinstr->value()->representation(); | 4749 Representation representation = hinstr->value()->representation(); |
| 4631 | 4750 |
| 4632 #if V8_TARGET_ARCH_PPC64 | 4751 #if V8_TARGET_ARCH_PPC64 |
| 4633 // 64-bit Smi optimization | 4752 // 64-bit Smi optimization |
| 4634 if (representation.IsInteger32()) { | 4753 if (representation.IsInteger32()) { |
| 4635 DCHECK(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); | 4754 DCHECK(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); |
| 4636 DCHECK(hinstr->elements_kind() == FAST_SMI_ELEMENTS); | 4755 DCHECK(hinstr->elements_kind() == FAST_SMI_ELEMENTS); |
| 4637 // Store int value directly to upper half of the smi. | 4756 // Store int value directly to upper half of the smi. |
| 4638 STATIC_ASSERT(kSmiTag == 0); | 4757 offset = SmiWordOffset(offset); |
| 4639 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); | |
| 4640 #if V8_TARGET_LITTLE_ENDIAN | |
| 4641 offset += kPointerSize / 2; | |
| 4642 #endif | |
| 4643 } | 4758 } |
| 4644 #endif | 4759 #endif |
| 4645 | 4760 |
| 4646 __ StoreRepresentation(value, MemOperand(store_base, offset), representation, | 4761 __ StoreRepresentation(value, MemOperand(store_base, offset), representation, |
| 4647 r0); | 4762 r0); |
| 4648 | 4763 |
| 4649 if (hinstr->NeedsWriteBarrier()) { | 4764 if (hinstr->NeedsWriteBarrier()) { |
| 4650 SmiCheck check_needed = hinstr->value()->type().IsHeapObject() | 4765 SmiCheck check_needed = hinstr->value()->type().IsHeapObject() |
| 4651 ? OMIT_SMI_CHECK | 4766 ? OMIT_SMI_CHECK |
| 4652 : INLINE_SMI_CHECK; | 4767 : INLINE_SMI_CHECK; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4671 } | 4786 } |
| 4672 | 4787 |
| 4673 | 4788 |
| 4674 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 4789 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
| 4675 DCHECK(ToRegister(instr->context()).is(cp)); | 4790 DCHECK(ToRegister(instr->context()).is(cp)); |
| 4676 DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister())); | 4791 DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister())); |
| 4677 DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister())); | 4792 DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister())); |
| 4678 DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister())); | 4793 DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister())); |
| 4679 | 4794 |
| 4680 Handle<Code> ic = | 4795 Handle<Code> ic = |
| 4681 CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code(); | 4796 CodeFactory::KeyedStoreIC(isolate(), instr->language_mode()).code(); |
| 4682 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4797 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4683 } | 4798 } |
| 4684 | 4799 |
| 4685 | 4800 |
| 4686 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 4801 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
| 4687 Register object_reg = ToRegister(instr->object()); | 4802 Register object_reg = ToRegister(instr->object()); |
| 4688 Register scratch = scratch0(); | 4803 Register scratch = scratch0(); |
| 4689 | 4804 |
| 4690 Handle<Map> from_map = instr->original_map(); | 4805 Handle<Map> from_map = instr->original_map(); |
| 4691 Handle<Map> to_map = instr->transitioned_map(); | 4806 Handle<Map> to_map = instr->transitioned_map(); |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5054 } | 5169 } |
| 5055 #endif | 5170 #endif |
| 5056 } | 5171 } |
| 5057 | 5172 |
| 5058 | 5173 |
| 5059 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 5174 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
| 5060 Register scratch = scratch0(); | 5175 Register scratch = scratch0(); |
| 5061 Register input = ToRegister(instr->value()); | 5176 Register input = ToRegister(instr->value()); |
| 5062 Register result = ToRegister(instr->result()); | 5177 Register result = ToRegister(instr->result()); |
| 5063 if (instr->needs_check()) { | 5178 if (instr->needs_check()) { |
| 5064 STATIC_ASSERT(kHeapObjectTag == 1); | |
| 5065 // If the input is a HeapObject, value of scratch won't be zero. | 5179 // If the input is a HeapObject, value of scratch won't be zero. |
| 5066 __ andi(scratch, input, Operand(kHeapObjectTag)); | 5180 __ andi(scratch, input, Operand(kHeapObjectTag)); |
| 5067 __ SmiUntag(result, input); | 5181 __ SmiUntag(result, input); |
| 5068 DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, cr0); | 5182 DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, cr0); |
| 5069 } else { | 5183 } else { |
| 5070 __ SmiUntag(result, input); | 5184 __ SmiUntag(result, input); |
| 5071 } | 5185 } |
| 5072 } | 5186 } |
| 5073 | 5187 |
| 5074 | 5188 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5174 __ bind(&check_bools); | 5288 __ bind(&check_bools); |
| 5175 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 5289 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 5176 __ cmp(input_reg, ip); | 5290 __ cmp(input_reg, ip); |
| 5177 __ bne(&check_false); | 5291 __ bne(&check_false); |
| 5178 __ li(input_reg, Operand(1)); | 5292 __ li(input_reg, Operand(1)); |
| 5179 __ b(&done); | 5293 __ b(&done); |
| 5180 | 5294 |
| 5181 __ bind(&check_false); | 5295 __ bind(&check_false); |
| 5182 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 5296 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
| 5183 __ cmp(input_reg, ip); | 5297 __ cmp(input_reg, ip); |
| 5184 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedTrueFalse, | 5298 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedBoolean); |
| 5185 cr7); | |
| 5186 __ li(input_reg, Operand::Zero()); | 5299 __ li(input_reg, Operand::Zero()); |
| 5187 } else { | 5300 } else { |
| 5188 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, cr7); | 5301 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber); |
| 5189 | 5302 |
| 5190 __ lfd(double_scratch2, | 5303 __ lfd(double_scratch2, |
| 5191 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); | 5304 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
| 5192 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5305 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 5193 // preserve heap number pointer in scratch2 for minus zero check below | 5306 // preserve heap number pointer in scratch2 for minus zero check below |
| 5194 __ mr(scratch2, input_reg); | 5307 __ mr(scratch2, input_reg); |
| 5195 } | 5308 } |
| 5196 __ TryDoubleToInt32Exact(input_reg, double_scratch2, scratch1, | 5309 __ TryDoubleToInt32Exact(input_reg, double_scratch2, scratch1, |
| 5197 double_scratch); | 5310 double_scratch); |
| 5198 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, cr7); | 5311 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN); |
| 5199 | 5312 |
| 5200 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5313 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 5201 __ cmpi(input_reg, Operand::Zero()); | 5314 __ cmpi(input_reg, Operand::Zero()); |
| 5202 __ bne(&done); | 5315 __ bne(&done); |
| 5203 __ lwz(scratch1, | 5316 __ lwz(scratch1, |
| 5204 FieldMemOperand(scratch2, HeapNumber::kValueOffset + | 5317 FieldMemOperand(scratch2, HeapNumber::kValueOffset + |
| 5205 Register::kExponentOffset)); | 5318 Register::kExponentOffset)); |
| 5206 __ cmpwi(scratch1, Operand::Zero()); | 5319 __ cmpwi(scratch1, Operand::Zero()); |
| 5207 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, cr7); | 5320 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); |
| 5208 } | 5321 } |
| 5209 } | 5322 } |
| 5210 __ bind(&done); | 5323 __ bind(&done); |
| 5211 } | 5324 } |
| 5212 | 5325 |
| 5213 | 5326 |
| 5214 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 5327 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 5215 class DeferredTaggedToI FINAL : public LDeferredCode { | 5328 class DeferredTaggedToI FINAL : public LDeferredCode { |
| 5216 public: | 5329 public: |
| 5217 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 5330 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5594 __ b(deferred->entry()); | 5707 __ b(deferred->entry()); |
| 5595 } | 5708 } |
| 5596 } else { | 5709 } else { |
| 5597 Register size = ToRegister(instr->size()); | 5710 Register size = ToRegister(instr->size()); |
| 5598 __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags); | 5711 __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags); |
| 5599 } | 5712 } |
| 5600 | 5713 |
| 5601 __ bind(deferred->exit()); | 5714 __ bind(deferred->exit()); |
| 5602 | 5715 |
| 5603 if (instr->hydrogen()->MustPrefillWithFiller()) { | 5716 if (instr->hydrogen()->MustPrefillWithFiller()) { |
| 5604 STATIC_ASSERT(kHeapObjectTag == 1); | |
| 5605 if (instr->size()->IsConstantOperand()) { | 5717 if (instr->size()->IsConstantOperand()) { |
| 5606 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5718 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
| 5607 __ LoadIntLiteral(scratch, size - kHeapObjectTag); | 5719 __ LoadIntLiteral(scratch, size - kHeapObjectTag); |
| 5608 } else { | 5720 } else { |
| 5609 __ subi(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag)); | 5721 __ subi(scratch, ToRegister(instr->size()), Operand(kHeapObjectTag)); |
| 5610 } | 5722 } |
| 5611 __ mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); | 5723 __ mov(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); |
| 5612 Label loop; | 5724 Label loop; |
| 5613 __ bind(&loop); | 5725 __ bind(&loop); |
| 5614 __ subi(scratch, scratch, Operand(kPointerSize)); | 5726 __ subi(scratch, scratch, Operand(kPointerSize)); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5718 __ CopyFields(r3, r4, r5.bit(), size / kPointerSize); | 5830 __ CopyFields(r3, r4, r5.bit(), size / kPointerSize); |
| 5719 } | 5831 } |
| 5720 | 5832 |
| 5721 | 5833 |
| 5722 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 5834 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
| 5723 DCHECK(ToRegister(instr->context()).is(cp)); | 5835 DCHECK(ToRegister(instr->context()).is(cp)); |
| 5724 // Use the fast case closure allocation code that allocates in new | 5836 // Use the fast case closure allocation code that allocates in new |
| 5725 // space for nested functions that don't need literals cloning. | 5837 // space for nested functions that don't need literals cloning. |
| 5726 bool pretenure = instr->hydrogen()->pretenure(); | 5838 bool pretenure = instr->hydrogen()->pretenure(); |
| 5727 if (!pretenure && instr->hydrogen()->has_no_literals()) { | 5839 if (!pretenure && instr->hydrogen()->has_no_literals()) { |
| 5728 FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(), | 5840 FastNewClosureStub stub(isolate(), instr->hydrogen()->language_mode(), |
| 5729 instr->hydrogen()->kind()); | 5841 instr->hydrogen()->kind()); |
| 5730 __ mov(r5, Operand(instr->hydrogen()->shared_info())); | 5842 __ mov(r5, Operand(instr->hydrogen()->shared_info())); |
| 5731 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 5843 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 5732 } else { | 5844 } else { |
| 5733 __ mov(r5, Operand(instr->hydrogen()->shared_info())); | 5845 __ mov(r5, Operand(instr->hydrogen()->shared_info())); |
| 5734 __ mov(r4, Operand(pretenure ? factory()->true_value() | 5846 __ mov(r4, Operand(pretenure ? factory()->true_value() |
| 5735 : factory()->false_value())); | 5847 : factory()->false_value())); |
| 5736 __ Push(cp, r5, r4); | 5848 __ Push(cp, r5, r4); |
| 5737 CallRuntime(Runtime::kNewClosure, 3, instr); | 5849 CallRuntime(Runtime::kNewClosure, 3, instr); |
| 5738 } | 5850 } |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6129 __ Push(scope_info); | 6241 __ Push(scope_info); |
| 6130 __ push(ToRegister(instr->function())); | 6242 __ push(ToRegister(instr->function())); |
| 6131 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 6243 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
| 6132 RecordSafepoint(Safepoint::kNoLazyDeopt); | 6244 RecordSafepoint(Safepoint::kNoLazyDeopt); |
| 6133 } | 6245 } |
| 6134 | 6246 |
| 6135 | 6247 |
| 6136 #undef __ | 6248 #undef __ |
| 6137 } | 6249 } |
| 6138 } // namespace v8::internal | 6250 } // namespace v8::internal |
| OLD | NEW |