| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 4024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4035 __ jmp(&skip_call, Assembler::kNearJump); | 4035 __ jmp(&skip_call, Assembler::kNearJump); |
| 4036 } | 4036 } |
| 4037 __ Bind(&do_call); | 4037 __ Bind(&do_call); |
| 4038 __ CallRuntime(TargetFunction(), InputCount()); | 4038 __ CallRuntime(TargetFunction(), InputCount()); |
| 4039 __ movaps(locs()->out().fpu_reg(), XMM0); | 4039 __ movaps(locs()->out().fpu_reg(), XMM0); |
| 4040 __ Bind(&skip_call); | 4040 __ Bind(&skip_call); |
| 4041 __ leave(); | 4041 __ leave(); |
| 4042 } | 4042 } |
| 4043 | 4043 |
| 4044 | 4044 |
| 4045 LocationSummary* MergedMathInstr::MakeLocationSummary() const { |
| 4046 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 4047 const intptr_t kNumInputs = 2; |
| 4048 const intptr_t kNumTemps = 1; |
| 4049 LocationSummary* summary = |
| 4050 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4051 // Both inputs must be writable because they will be untagged. |
| 4052 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 4053 summary->set_in(1, Location::WritableRegister()); |
| 4054 summary->set_out(Location::RequiresRegister()); |
| 4055 // Will be used for sign extension and division. |
| 4056 summary->set_temp(0, Location::RegisterLocation(RDX)); |
| 4057 return summary; |
| 4058 } |
| 4059 UNIMPLEMENTED(); |
| 4060 return NULL; |
| 4061 } |
| 4062 |
| 4063 |
| 4064 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4065 Label* deopt = NULL; |
| 4066 if (CanDeoptimize()) { |
| 4067 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
| 4068 } |
| 4069 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 4070 Register left = locs()->in(0).reg(); |
| 4071 Register right = locs()->in(1).reg(); |
| 4072 Register result = locs()->out().reg(); |
| 4073 Label not_32bit, done; |
| 4074 Register temp = locs()->temp(0).reg(); |
| 4075 ASSERT(left == RAX); |
| 4076 ASSERT((right != RDX) && (right != RAX)); |
| 4077 ASSERT(temp == RDX); |
| 4078 ASSERT((result != RDX) && (result != RAX)); |
| 4079 // Handle divide by zero in runtime. |
| 4080 __ testq(right, right); |
| 4081 __ j(ZERO, deopt); |
| 4082 // Check if both operands fit into 32bits as idiv with 64bit operands |
| 4083 // requires twice as many cycles and has much higher latency. |
| 4084 // We are checking this before untagging them to avoid corner case |
| 4085 // dividing INT_MAX by -1 that raises exception because quotient is |
| 4086 // too large for 32bit register. |
| 4087 __ movsxd(temp, left); |
| 4088 __ cmpq(temp, left); |
| 4089 __ j(NOT_EQUAL, ¬_32bit); |
| 4090 __ movsxd(temp, right); |
| 4091 __ cmpq(temp, right); |
| 4092 __ j(NOT_EQUAL, ¬_32bit); |
| 4093 |
| 4094 // Both operands are 31bit smis. Divide using 32bit idiv. |
| 4095 __ SmiUntag(left); |
| 4096 __ SmiUntag(right); |
| 4097 __ cdq(); |
| 4098 __ idivl(right); |
| 4099 __ movsxd(RAX, RAX); |
| 4100 __ movsxd(RDX, RDX); |
| 4101 __ jmp(&done); |
| 4102 |
| 4103 // Divide using 64bit idiv. |
| 4104 __ Bind(¬_32bit); |
| 4105 __ SmiUntag(left); |
| 4106 __ SmiUntag(right); |
| 4107 __ cqo(); // Sign extend RAX -> RDX:RAX. |
| 4108 __ idivq(right); // RAX: quotient, RDX: remainder. |
| 4109 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 4110 // case we cannot tag the result. |
| 4111 __ CompareImmediate(RAX, Immediate(0x4000000000000000), PP); |
| 4112 __ j(EQUAL, deopt); |
| 4113 __ Bind(&done); |
| 4114 |
| 4115 // Modulo correction (RDX). |
| 4116 // res = left % right; |
| 4117 // if (res < 0) { |
| 4118 // if (right < 0) { |
| 4119 // res = res - right; |
| 4120 // } else { |
| 4121 // res = res + right; |
| 4122 // } |
| 4123 // } |
| 4124 Label subtract, all_done; |
| 4125 __ cmpq(RDX, Immediate(0)); |
| 4126 __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump); |
| 4127 // Result is negative, adjust it. |
| 4128 __ cmpq(right, Immediate(0)); |
| 4129 __ j(LESS, &subtract, Assembler::kNearJump); |
| 4130 __ addq(RDX, right); |
| 4131 __ jmp(&all_done, Assembler::kNearJump); |
| 4132 __ Bind(&subtract); |
| 4133 __ subq(RDX, right); |
| 4134 __ Bind(&all_done); |
| 4135 __ SmiTag(result); |
| 4136 |
| 4137 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld)), PP); |
| 4138 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid); |
| 4139 Address trunc_div_address( |
| 4140 FlowGraphCompiler::ElementAddressForIntIndex(kArrayCid, |
| 4141 index_scale, |
| 4142 result, |
| 4143 0)); |
| 4144 Address mod_address( |
| 4145 FlowGraphCompiler::ElementAddressForIntIndex(kArrayCid, |
| 4146 index_scale, |
| 4147 result, |
| 4148 1)); |
| 4149 __ SmiTag(RAX); |
| 4150 __ SmiTag(RDX); |
| 4151 __ StoreIntoObjectNoBarrier(result, trunc_div_address, RAX); |
| 4152 __ StoreIntoObjectNoBarrier(result, mod_address, RDX); |
| 4153 // FLAG_throw_on_javascript_int_overflow: not needed. |
| 4154 // Note that the result of an integer division/modulo of two |
| 4155 // in-range arguments, cannot create out-of-range result. |
| 4156 return; |
| 4157 } |
| 4158 UNIMPLEMENTED(); |
| 4159 } |
| 4160 |
| 4161 |
| 4045 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { | 4162 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary() const { |
| 4046 return MakeCallSummary(); | 4163 return MakeCallSummary(); |
| 4047 } | 4164 } |
| 4048 | 4165 |
| 4049 | 4166 |
| 4050 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4167 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4051 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 4168 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 4052 kDeoptPolymorphicInstanceCallTestFail); | 4169 kDeoptPolymorphicInstanceCallTestFail); |
| 4053 if (ic_data().NumberOfChecks() == 0) { | 4170 if (ic_data().NumberOfChecks() == 0) { |
| 4054 __ jmp(deopt); | 4171 __ jmp(deopt); |
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4572 PcDescriptors::kOther, | 4689 PcDescriptors::kOther, |
| 4573 locs()); | 4690 locs()); |
| 4574 __ Drop(2); // Discard type arguments and receiver. | 4691 __ Drop(2); // Discard type arguments and receiver. |
| 4575 } | 4692 } |
| 4576 | 4693 |
| 4577 } // namespace dart | 4694 } // namespace dart |
| 4578 | 4695 |
| 4579 #undef __ | 4696 #undef __ |
| 4580 | 4697 |
| 4581 #endif // defined TARGET_ARCH_X64 | 4698 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |