| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "vm/symbols.h" | 22 #include "vm/symbols.h" |
| 23 | 23 |
| 24 #define __ compiler->assembler()-> | 24 #define __ compiler->assembler()-> |
| 25 #define Z (compiler->zone()) | 25 #define Z (compiler->zone()) |
| 26 | 26 |
| 27 namespace dart { | 27 namespace dart { |
| 28 | 28 |
| 29 // Generic summary for call instructions that have all arguments pushed | 29 // Generic summary for call instructions that have all arguments pushed |
| 30 // on the stack and return the result in a fixed register R0. | 30 // on the stack and return the result in a fixed register R0. |
| 31 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { | 31 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { |
| 32 LocationSummary* result = new(zone) LocationSummary( | 32 LocationSummary* result = |
| 33 zone, 0, 0, LocationSummary::kCall); | 33 new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 34 result->set_out(0, Location::RegisterLocation(R0)); | 34 result->set_out(0, Location::RegisterLocation(R0)); |
| 35 return result; | 35 return result; |
| 36 } | 36 } |
| 37 | 37 |
| 38 | 38 |
| 39 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, | 39 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, |
| 40 bool opt) const { | 40 bool opt) const { |
| 41 const intptr_t kNumInputs = 1; | 41 const intptr_t kNumInputs = 1; |
| 42 const intptr_t kNumTemps = 0; | 42 const intptr_t kNumTemps = 0; |
| 43 LocationSummary* locs = new(zone) LocationSummary( | 43 LocationSummary* locs = new (zone) |
| 44 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 44 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 45 locs->set_in(0, Location::AnyOrConstant(value())); | 45 locs->set_in(0, Location::AnyOrConstant(value())); |
| 46 return locs; | 46 return locs; |
| 47 } | 47 } |
| 48 | 48 |
| 49 | 49 |
| 50 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 50 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 51 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 51 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
| 52 // where PushArgument is handled by BindInstr::EmitNativeCode. | 52 // where PushArgument is handled by BindInstr::EmitNativeCode. |
| 53 if (compiler->is_optimizing()) { | 53 if (compiler->is_optimizing()) { |
| 54 Location value = locs()->in(0); | 54 Location value = locs()->in(0); |
| 55 if (value.IsRegister()) { | 55 if (value.IsRegister()) { |
| 56 __ Push(value.reg()); | 56 __ Push(value.reg()); |
| 57 } else if (value.IsConstant()) { | 57 } else if (value.IsConstant()) { |
| 58 __ PushObject(value.constant()); | 58 __ PushObject(value.constant()); |
| 59 } else { | 59 } else { |
| 60 ASSERT(value.IsStackSlot()); | 60 ASSERT(value.IsStackSlot()); |
| 61 const intptr_t value_offset = value.ToStackSlotOffset(); | 61 const intptr_t value_offset = value.ToStackSlotOffset(); |
| 62 __ LoadFromOffset(TMP, value.base_reg(), value_offset); | 62 __ LoadFromOffset(TMP, value.base_reg(), value_offset); |
| 63 __ Push(TMP); | 63 __ Push(TMP); |
| 64 } | 64 } |
| 65 } | 65 } |
| 66 } | 66 } |
| 67 | 67 |
| 68 | 68 |
| 69 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, | 69 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 70 bool opt) const { | |
| 71 const intptr_t kNumInputs = 1; | 70 const intptr_t kNumInputs = 1; |
| 72 const intptr_t kNumTemps = 0; | 71 const intptr_t kNumTemps = 0; |
| 73 LocationSummary* locs = new(zone) LocationSummary( | 72 LocationSummary* locs = new (zone) |
| 74 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 73 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 75 locs->set_in(0, Location::RegisterLocation(R0)); | 74 locs->set_in(0, Location::RegisterLocation(R0)); |
| 76 return locs; | 75 return locs; |
| 77 } | 76 } |
| 78 | 77 |
| 79 | 78 |
| 80 // Attempt optimized compilation at return instruction instead of at the entry. | 79 // Attempt optimized compilation at return instruction instead of at the entry. |
| 81 // The entry needs to be patchable, no inlined objects are allowed in the area | 80 // The entry needs to be patchable, no inlined objects are allowed in the area |
| 82 // that will be overwritten by the patch instructions: a branch macro sequence. | 81 // that will be overwritten by the patch instructions: a branch macro sequence. |
| 83 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 82 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 84 const Register result = locs()->in(0).reg(); | 83 const Register result = locs()->in(0).reg(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 106 __ LeaveDartFrame(); // Disallows constant pool use. | 105 __ LeaveDartFrame(); // Disallows constant pool use. |
| 107 __ ret(); | 106 __ ret(); |
| 108 // This ReturnInstr may be emitted out of order by the optimizer. The next | 107 // This ReturnInstr may be emitted out of order by the optimizer. The next |
| 109 // block may be a target expecting a properly set constant pool pointer. | 108 // block may be a target expecting a properly set constant pool pointer. |
| 110 __ set_constant_pool_allowed(true); | 109 __ set_constant_pool_allowed(true); |
| 111 } | 110 } |
| 112 | 111 |
| 113 | 112 |
| 114 static Condition NegateCondition(Condition condition) { | 113 static Condition NegateCondition(Condition condition) { |
| 115 switch (condition) { | 114 switch (condition) { |
| 116 case EQ: return NE; | 115 case EQ: |
| 117 case NE: return EQ; | 116 return NE; |
| 118 case LT: return GE; | 117 case NE: |
| 119 case LE: return GT; | 118 return EQ; |
| 120 case GT: return LE; | 119 case LT: |
| 121 case GE: return LT; | 120 return GE; |
| 122 case CC: return CS; | 121 case LE: |
| 123 case LS: return HI; | 122 return GT; |
| 124 case HI: return LS; | 123 case GT: |
| 125 case CS: return CC; | 124 return LE; |
| 126 case VS: return VC; | 125 case GE: |
| 127 case VC: return VS; | 126 return LT; |
| 127 case CC: |
| 128 return CS; |
| 129 case LS: |
| 130 return HI; |
| 131 case HI: |
| 132 return LS; |
| 133 case CS: |
| 134 return CC; |
| 135 case VS: |
| 136 return VC; |
| 137 case VC: |
| 138 return VS; |
| 128 default: | 139 default: |
| 129 UNREACHABLE(); | 140 UNREACHABLE(); |
| 130 return EQ; | 141 return EQ; |
| 131 } | 142 } |
| 132 } | 143 } |
| 133 | 144 |
| 134 | 145 |
| 135 // Detect pattern when one value is zero and another is a power of 2. | 146 // Detect pattern when one value is zero and another is a power of 2. |
| 136 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 147 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 137 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 148 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| 138 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 149 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
| 139 } | 150 } |
| 140 | 151 |
| 141 | 152 |
| 142 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, | 153 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, |
| 143 bool opt) const { | 154 bool opt) const { |
| 144 comparison()->InitializeLocationSummary(zone, opt); | 155 comparison()->InitializeLocationSummary(zone, opt); |
| 145 return comparison()->locs(); | 156 return comparison()->locs(); |
| 146 } | 157 } |
| 147 | 158 |
| 148 | 159 |
| 149 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 160 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 150 const Register result = locs()->out(0).reg(); | 161 const Register result = locs()->out(0).reg(); |
| 151 | 162 |
| 152 Location left = locs()->in(0); | 163 Location left = locs()->in(0); |
| 153 Location right = locs()->in(1); | 164 Location right = locs()->in(1); |
| 154 ASSERT(!left.IsConstant() || !right.IsConstant()); | 165 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 155 | 166 |
| 156 // Emit comparison code. This must not overwrite the result register. | 167 // Emit comparison code. This must not overwrite the result register. |
| 157 BranchLabels labels = { NULL, NULL, NULL }; | 168 BranchLabels labels = {NULL, NULL, NULL}; |
| 158 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 169 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
| 159 | 170 |
| 160 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 171 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
| 161 | 172 |
| 162 intptr_t true_value = if_true_; | 173 intptr_t true_value = if_true_; |
| 163 intptr_t false_value = if_false_; | 174 intptr_t false_value = if_false_; |
| 164 | 175 |
| 165 if (is_power_of_two_kind) { | 176 if (is_power_of_two_kind) { |
| 166 if (true_value == 0) { | 177 if (true_value == 0) { |
| 167 // We need to have zero in result on true_condition. | 178 // We need to have zero in result on true_condition. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 179 } | 190 } |
| 180 | 191 |
| 181 __ cset(result, true_condition); | 192 __ cset(result, true_condition); |
| 182 | 193 |
| 183 if (is_power_of_two_kind) { | 194 if (is_power_of_two_kind) { |
| 184 const intptr_t shift = | 195 const intptr_t shift = |
| 185 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); | 196 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
| 186 __ LslImmediate(result, result, shift + kSmiTagSize); | 197 __ LslImmediate(result, result, shift + kSmiTagSize); |
| 187 } else { | 198 } else { |
| 188 __ sub(result, result, Operand(1)); | 199 __ sub(result, result, Operand(1)); |
| 189 const int64_t val = | 200 const int64_t val = Smi::RawValue(true_value) - Smi::RawValue(false_value); |
| 190 Smi::RawValue(true_value) - Smi::RawValue(false_value); | |
| 191 __ AndImmediate(result, result, val); | 201 __ AndImmediate(result, result, val); |
| 192 if (false_value != 0) { | 202 if (false_value != 0) { |
| 193 __ AddImmediate(result, result, Smi::RawValue(false_value)); | 203 __ AddImmediate(result, result, Smi::RawValue(false_value)); |
| 194 } | 204 } |
| 195 } | 205 } |
| 196 } | 206 } |
| 197 | 207 |
| 198 | 208 |
| 199 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 209 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |
| 200 bool opt) const { | 210 bool opt) const { |
| 201 const intptr_t kNumInputs = 1; | 211 const intptr_t kNumInputs = 1; |
| 202 const intptr_t kNumTemps = 0; | 212 const intptr_t kNumTemps = 0; |
| 203 LocationSummary* summary = new(zone) LocationSummary( | 213 LocationSummary* summary = new (zone) |
| 204 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 214 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 205 summary->set_in(0, Location::RegisterLocation(R0)); // Function. | 215 summary->set_in(0, Location::RegisterLocation(R0)); // Function. |
| 206 summary->set_out(0, Location::RegisterLocation(R0)); | 216 summary->set_out(0, Location::RegisterLocation(R0)); |
| 207 return summary; | 217 return summary; |
| 208 } | 218 } |
| 209 | 219 |
| 210 | 220 |
| 211 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 221 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 212 // Load arguments descriptor in R4. | 222 // Load arguments descriptor in R4. |
| 213 int argument_count = ArgumentCount(); | 223 int argument_count = ArgumentCount(); |
| 214 const Array& arguments_descriptor = | 224 const Array& arguments_descriptor = Array::ZoneHandle( |
| 215 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 225 ArgumentsDescriptor::New(argument_count, argument_names())); |
| 216 argument_names())); | |
| 217 __ LoadObject(R4, arguments_descriptor); | 226 __ LoadObject(R4, arguments_descriptor); |
| 218 | 227 |
| 219 // R4: Arguments descriptor. | 228 // R4: Arguments descriptor. |
| 220 // R0: Function. | 229 // R0: Function. |
| 221 ASSERT(locs()->in(0).reg() == R0); | 230 ASSERT(locs()->in(0).reg() == R0); |
| 222 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset()); | 231 __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset()); |
| 223 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset()); | 232 __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset()); |
| 224 | 233 |
| 225 // R2: instructions. | 234 // R2: instructions. |
| 226 // R5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). | 235 // R5: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). |
| 227 __ LoadImmediate(R5, 0); | 236 __ LoadImmediate(R5, 0); |
| 228 //?? | 237 //?? |
| 229 __ blr(R2); | 238 __ blr(R2); |
| 230 compiler->RecordSafepoint(locs()); | 239 compiler->RecordSafepoint(locs()); |
| 231 // Marks either the continuation point in unoptimized code or the | 240 // Marks either the continuation point in unoptimized code or the |
| 232 // deoptimization point in optimized code, after call. | 241 // deoptimization point in optimized code, after call. |
| 233 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); | 242 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); |
| 234 if (compiler->is_optimizing()) { | 243 if (compiler->is_optimizing()) { |
| 235 compiler->AddDeoptIndexAtCall(deopt_id_after); | 244 compiler->AddDeoptIndexAtCall(deopt_id_after); |
| 236 } | 245 } |
| 237 // Add deoptimization continuation point after the call and before the | 246 // Add deoptimization continuation point after the call and before the |
| 238 // arguments are removed. | 247 // arguments are removed. |
| 239 // In optimized code this descriptor is needed for exception handling. | 248 // In optimized code this descriptor is needed for exception handling. |
| 240 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 249 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, |
| 241 deopt_id_after, | |
| 242 token_pos()); | 250 token_pos()); |
| 243 __ Drop(argument_count); | 251 __ Drop(argument_count); |
| 244 } | 252 } |
| 245 | 253 |
| 246 | 254 |
| 247 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 255 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
| 248 bool opt) const { | 256 bool opt) const { |
| 249 return LocationSummary::Make(zone, | 257 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), |
| 250 0, | |
| 251 Location::RequiresRegister(), | |
| 252 LocationSummary::kNoCall); | 258 LocationSummary::kNoCall); |
| 253 } | 259 } |
| 254 | 260 |
| 255 | 261 |
| 256 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 262 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 257 const Register result = locs()->out(0).reg(); | 263 const Register result = locs()->out(0).reg(); |
| 258 __ LoadFromOffset(result, FP, local().index() * kWordSize); | 264 __ LoadFromOffset(result, FP, local().index() * kWordSize); |
| 259 } | 265 } |
| 260 | 266 |
| 261 | 267 |
| 262 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 268 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |
| 263 bool opt) const { | 269 bool opt) const { |
| 264 return LocationSummary::Make(zone, | 270 return LocationSummary::Make(zone, 1, Location::SameAsFirstInput(), |
| 265 1, | |
| 266 Location::SameAsFirstInput(), | |
| 267 LocationSummary::kNoCall); | 271 LocationSummary::kNoCall); |
| 268 } | 272 } |
| 269 | 273 |
| 270 | 274 |
| 271 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 275 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 272 const Register value = locs()->in(0).reg(); | 276 const Register value = locs()->in(0).reg(); |
| 273 const Register result = locs()->out(0).reg(); | 277 const Register result = locs()->out(0).reg(); |
| 274 ASSERT(result == value); // Assert that register assignment is correct. | 278 ASSERT(result == value); // Assert that register assignment is correct. |
| 275 __ StoreToOffset(value, FP, local().index() * kWordSize); | 279 __ StoreToOffset(value, FP, local().index() * kWordSize); |
| 276 } | 280 } |
| 277 | 281 |
| 278 | 282 |
| 279 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 283 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |
| 280 bool opt) const { | 284 bool opt) const { |
| 281 return LocationSummary::Make(zone, | 285 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), |
| 282 0, | |
| 283 Location::RequiresRegister(), | |
| 284 LocationSummary::kNoCall); | 286 LocationSummary::kNoCall); |
| 285 } | 287 } |
| 286 | 288 |
| 287 | 289 |
| 288 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 290 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 289 // The register allocator drops constant definitions that have no uses. | 291 // The register allocator drops constant definitions that have no uses. |
| 290 if (!locs()->out(0).IsInvalid()) { | 292 if (!locs()->out(0).IsInvalid()) { |
| 291 const Register result = locs()->out(0).reg(); | 293 const Register result = locs()->out(0).reg(); |
| 292 __ LoadObject(result, value()); | 294 __ LoadObject(result, value()); |
| 293 } | 295 } |
| 294 } | 296 } |
| 295 | 297 |
| 296 | 298 |
| 297 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 299 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
| 298 bool opt) const { | 300 bool opt) const { |
| 299 const intptr_t kNumInputs = 0; | 301 const intptr_t kNumInputs = 0; |
| 300 const Location out = (representation_ == kUnboxedInt32) ? | 302 const Location out = (representation_ == kUnboxedInt32) |
| 301 Location::RequiresRegister() : Location::RequiresFpuRegister(); | 303 ? Location::RequiresRegister() |
| 302 return LocationSummary::Make(zone, | 304 : Location::RequiresFpuRegister(); |
| 303 kNumInputs, | 305 return LocationSummary::Make(zone, kNumInputs, out, LocationSummary::kNoCall); |
| 304 out, | |
| 305 LocationSummary::kNoCall); | |
| 306 } | 306 } |
| 307 | 307 |
| 308 | 308 |
| 309 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 309 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 310 if (!locs()->out(0).IsInvalid()) { | 310 if (!locs()->out(0).IsInvalid()) { |
| 311 switch (representation_) { | 311 switch (representation_) { |
| 312 case kUnboxedDouble: | 312 case kUnboxedDouble: |
| 313 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { | 313 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { |
| 314 const VRegister dst = locs()->out(0).fpu_reg(); | 314 const VRegister dst = locs()->out(0).fpu_reg(); |
| 315 __ veor(dst, dst, dst); | 315 __ veor(dst, dst, dst); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 327 break; | 327 break; |
| 328 } | 328 } |
| 329 } | 329 } |
| 330 } | 330 } |
| 331 | 331 |
| 332 | 332 |
| 333 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 333 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
| 334 bool opt) const { | 334 bool opt) const { |
| 335 const intptr_t kNumInputs = 2; | 335 const intptr_t kNumInputs = 2; |
| 336 const intptr_t kNumTemps = 0; | 336 const intptr_t kNumTemps = 0; |
| 337 LocationSummary* summary = new(zone) LocationSummary( | 337 LocationSummary* summary = new (zone) |
| 338 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 338 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 339 summary->set_in(0, Location::RegisterLocation(R0)); // Value. | 339 summary->set_in(0, Location::RegisterLocation(R0)); // Value. |
| 340 summary->set_in(1, Location::RegisterLocation(R1)); // Type arguments. | 340 summary->set_in(1, Location::RegisterLocation(R1)); // Type arguments. |
| 341 summary->set_out(0, Location::RegisterLocation(R0)); | 341 summary->set_out(0, Location::RegisterLocation(R0)); |
| 342 return summary; | 342 return summary; |
| 343 } | 343 } |
| 344 | 344 |
| 345 | 345 |
| 346 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 346 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
| 347 bool opt) const { | 347 bool opt) const { |
| 348 const intptr_t kNumInputs = 1; | 348 const intptr_t kNumInputs = 1; |
| 349 const intptr_t kNumTemps = 0; | 349 const intptr_t kNumTemps = 0; |
| 350 LocationSummary* locs = new(zone) LocationSummary( | 350 LocationSummary* locs = new (zone) |
| 351 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 351 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 352 locs->set_in(0, Location::RegisterLocation(R0)); | 352 locs->set_in(0, Location::RegisterLocation(R0)); |
| 353 locs->set_out(0, Location::RegisterLocation(R0)); | 353 locs->set_out(0, Location::RegisterLocation(R0)); |
| 354 return locs; | 354 return locs; |
| 355 } | 355 } |
| 356 | 356 |
| 357 | 357 |
| 358 static void EmitAssertBoolean(Register reg, | 358 static void EmitAssertBoolean(Register reg, |
| 359 TokenPosition token_pos, | 359 TokenPosition token_pos, |
| 360 intptr_t deopt_id, | 360 intptr_t deopt_id, |
| 361 LocationSummary* locs, | 361 LocationSummary* locs, |
| 362 FlowGraphCompiler* compiler) { | 362 FlowGraphCompiler* compiler) { |
| 363 // Check that the type of the value is allowed in conditional context. | 363 // Check that the type of the value is allowed in conditional context. |
| 364 // Call the runtime if the object is not bool::true or bool::false. | 364 // Call the runtime if the object is not bool::true or bool::false. |
| 365 ASSERT(locs->always_calls()); | 365 ASSERT(locs->always_calls()); |
| 366 Label done; | 366 Label done; |
| 367 | 367 |
| 368 if (Isolate::Current()->type_checks()) { | 368 if (Isolate::Current()->type_checks()) { |
| 369 __ CompareObject(reg, Bool::True()); | 369 __ CompareObject(reg, Bool::True()); |
| 370 __ b(&done, EQ); | 370 __ b(&done, EQ); |
| 371 __ CompareObject(reg, Bool::False()); | 371 __ CompareObject(reg, Bool::False()); |
| 372 __ b(&done, EQ); | 372 __ b(&done, EQ); |
| 373 } else { | 373 } else { |
| 374 ASSERT(Isolate::Current()->asserts()); | 374 ASSERT(Isolate::Current()->asserts()); |
| 375 __ CompareObject(reg, Object::null_instance()); | 375 __ CompareObject(reg, Object::null_instance()); |
| 376 __ b(&done, NE); | 376 __ b(&done, NE); |
| 377 } | 377 } |
| 378 | 378 |
| 379 __ Push(reg); // Push the source object. | 379 __ Push(reg); // Push the source object. |
| 380 compiler->GenerateRuntimeCall(token_pos, | 380 compiler->GenerateRuntimeCall(token_pos, deopt_id, |
| 381 deopt_id, | 381 kNonBoolTypeErrorRuntimeEntry, 1, locs); |
| 382 kNonBoolTypeErrorRuntimeEntry, | |
| 383 1, | |
| 384 locs); | |
| 385 // We should never return here. | 382 // We should never return here. |
| 386 __ brk(0); | 383 __ brk(0); |
| 387 __ Bind(&done); | 384 __ Bind(&done); |
| 388 } | 385 } |
| 389 | 386 |
| 390 | 387 |
| 391 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 388 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 392 const Register obj = locs()->in(0).reg(); | 389 const Register obj = locs()->in(0).reg(); |
| 393 const Register result = locs()->out(0).reg(); | 390 const Register result = locs()->out(0).reg(); |
| 394 | 391 |
| 395 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 392 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 396 ASSERT(obj == result); | 393 ASSERT(obj == result); |
| 397 } | 394 } |
| 398 | 395 |
| 399 | 396 |
| 400 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 397 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
| 401 switch (kind) { | 398 switch (kind) { |
| 402 case Token::kEQ: return EQ; | 399 case Token::kEQ: |
| 403 case Token::kNE: return NE; | 400 return EQ; |
| 404 case Token::kLT: return LT; | 401 case Token::kNE: |
| 405 case Token::kGT: return GT; | 402 return NE; |
| 406 case Token::kLTE: return LE; | 403 case Token::kLT: |
| 407 case Token::kGTE: return GE; | 404 return LT; |
| 405 case Token::kGT: |
| 406 return GT; |
| 407 case Token::kLTE: |
| 408 return LE; |
| 409 case Token::kGTE: |
| 410 return GE; |
| 408 default: | 411 default: |
| 409 UNREACHABLE(); | 412 UNREACHABLE(); |
| 410 return VS; | 413 return VS; |
| 411 } | 414 } |
| 412 } | 415 } |
| 413 | 416 |
| 414 | 417 |
| 415 static Condition FlipCondition(Condition condition) { | 418 static Condition FlipCondition(Condition condition) { |
| 416 switch (condition) { | 419 switch (condition) { |
| 417 case EQ: return EQ; | 420 case EQ: |
| 418 case NE: return NE; | 421 return EQ; |
| 419 case LT: return GT; | 422 case NE: |
| 420 case LE: return GE; | 423 return NE; |
| 421 case GT: return LT; | 424 case LT: |
| 422 case GE: return LE; | 425 return GT; |
| 423 case CC: return HI; | 426 case LE: |
| 424 case LS: return CS; | 427 return GE; |
| 425 case HI: return CC; | 428 case GT: |
| 426 case CS: return LS; | 429 return LT; |
| 430 case GE: |
| 431 return LE; |
| 432 case CC: |
| 433 return HI; |
| 434 case LS: |
| 435 return CS; |
| 436 case HI: |
| 437 return CC; |
| 438 case CS: |
| 439 return LS; |
| 427 default: | 440 default: |
| 428 UNREACHABLE(); | 441 UNREACHABLE(); |
| 429 return EQ; | 442 return EQ; |
| 430 } | 443 } |
| 431 } | 444 } |
| 432 | 445 |
| 433 | 446 |
| 434 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 447 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 435 Condition true_condition, | 448 Condition true_condition, |
| 436 BranchLabels labels) { | 449 BranchLabels labels) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 __ CompareRegisters(left.reg(), right.reg()); | 481 __ CompareRegisters(left.reg(), right.reg()); |
| 469 } | 482 } |
| 470 return true_condition; | 483 return true_condition; |
| 471 } | 484 } |
| 472 | 485 |
| 473 | 486 |
| 474 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 487 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |
| 475 bool opt) const { | 488 bool opt) const { |
| 476 const intptr_t kNumInputs = 2; | 489 const intptr_t kNumInputs = 2; |
| 477 if (operation_cid() == kDoubleCid) { | 490 if (operation_cid() == kDoubleCid) { |
| 478 const intptr_t kNumTemps = 0; | 491 const intptr_t kNumTemps = 0; |
| 479 LocationSummary* locs = new(zone) LocationSummary( | 492 LocationSummary* locs = new (zone) |
| 480 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 493 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 481 locs->set_in(0, Location::RequiresFpuRegister()); | 494 locs->set_in(0, Location::RequiresFpuRegister()); |
| 482 locs->set_in(1, Location::RequiresFpuRegister()); | 495 locs->set_in(1, Location::RequiresFpuRegister()); |
| 483 locs->set_out(0, Location::RequiresRegister()); | 496 locs->set_out(0, Location::RequiresRegister()); |
| 484 return locs; | 497 return locs; |
| 485 } | 498 } |
| 486 if (operation_cid() == kSmiCid) { | 499 if (operation_cid() == kSmiCid) { |
| 487 const intptr_t kNumTemps = 0; | 500 const intptr_t kNumTemps = 0; |
| 488 LocationSummary* locs = new(zone) LocationSummary( | 501 LocationSummary* locs = new (zone) |
| 489 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 502 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 490 locs->set_in(0, Location::RegisterOrConstant(left())); | 503 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 491 // Only one input can be a constant operand. The case of two constant | 504 // Only one input can be a constant operand. The case of two constant |
| 492 // operands should be handled by constant propagation. | 505 // operands should be handled by constant propagation. |
| 493 // Only right can be a stack slot. | 506 // Only right can be a stack slot. |
| 494 locs->set_in(1, locs->in(0).IsConstant() | 507 locs->set_in(1, locs->in(0).IsConstant() |
| 495 ? Location::RequiresRegister() | 508 ? Location::RequiresRegister() |
| 496 : Location::RegisterOrConstant(right())); | 509 : Location::RegisterOrConstant(right())); |
| 497 locs->set_out(0, Location::RequiresRegister()); | 510 locs->set_out(0, Location::RequiresRegister()); |
| 498 return locs; | 511 return locs; |
| 499 } | 512 } |
| 500 UNREACHABLE(); | 513 UNREACHABLE(); |
| 501 return NULL; | 514 return NULL; |
| 502 } | 515 } |
| 503 | 516 |
| 504 | 517 |
| 505 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 518 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 506 switch (kind) { | 519 switch (kind) { |
| 507 case Token::kEQ: return EQ; | 520 case Token::kEQ: |
| 508 case Token::kNE: return NE; | 521 return EQ; |
| 509 case Token::kLT: return LT; | 522 case Token::kNE: |
| 510 case Token::kGT: return GT; | 523 return NE; |
| 511 case Token::kLTE: return LE; | 524 case Token::kLT: |
| 512 case Token::kGTE: return GE; | 525 return LT; |
| 526 case Token::kGT: |
| 527 return GT; |
| 528 case Token::kLTE: |
| 529 return LE; |
| 530 case Token::kGTE: |
| 531 return GE; |
| 513 default: | 532 default: |
| 514 UNREACHABLE(); | 533 UNREACHABLE(); |
| 515 return VS; | 534 return VS; |
| 516 } | 535 } |
| 517 } | 536 } |
| 518 | 537 |
| 519 | 538 |
| 520 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 539 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 521 LocationSummary* locs, | 540 LocationSummary* locs, |
| 522 Token::Kind kind) { | 541 Token::Kind kind) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 535 } else { | 554 } else { |
| 536 ASSERT(operation_cid() == kDoubleCid); | 555 ASSERT(operation_cid() == kDoubleCid); |
| 537 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 556 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
| 538 } | 557 } |
| 539 } | 558 } |
| 540 | 559 |
| 541 | 560 |
| 542 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 561 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 543 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 562 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| 544 Label is_true, is_false; | 563 Label is_true, is_false; |
| 545 BranchLabels labels = { &is_true, &is_false, &is_false }; | 564 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 546 Condition true_condition = EmitComparisonCode(compiler, labels); | 565 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 547 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { | 566 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { |
| 548 // Special case for NaN comparison. Result is always false unless | 567 // Special case for NaN comparison. Result is always false unless |
| 549 // relational operator is !=. | 568 // relational operator is !=. |
| 550 __ b(&is_false, VS); | 569 __ b(&is_false, VS); |
| 551 } | 570 } |
| 552 EmitBranchOnCondition(compiler, true_condition, labels); | 571 EmitBranchOnCondition(compiler, true_condition, labels); |
| 553 // TODO(zra): instead of branching, use the csel instruction to get | 572 // TODO(zra): instead of branching, use the csel instruction to get |
| 554 // True or False into result. | 573 // True or False into result. |
| 555 const Register result = locs()->out(0).reg(); | 574 const Register result = locs()->out(0).reg(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 571 Condition true_condition = EmitComparisonCode(compiler, labels); | 590 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 572 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { | 591 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { |
| 573 // Special case for NaN comparison. Result is always false unless | 592 // Special case for NaN comparison. Result is always false unless |
| 574 // relational operator is !=. | 593 // relational operator is !=. |
| 575 __ b(labels.false_label, VS); | 594 __ b(labels.false_label, VS); |
| 576 } | 595 } |
| 577 EmitBranchOnCondition(compiler, true_condition, labels); | 596 EmitBranchOnCondition(compiler, true_condition, labels); |
| 578 } | 597 } |
| 579 | 598 |
| 580 | 599 |
| 581 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, | 600 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 582 bool opt) const { | |
| 583 const intptr_t kNumInputs = 2; | 601 const intptr_t kNumInputs = 2; |
| 584 const intptr_t kNumTemps = 0; | 602 const intptr_t kNumTemps = 0; |
| 585 LocationSummary* locs = new(zone) LocationSummary( | 603 LocationSummary* locs = new (zone) |
| 586 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 604 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 587 locs->set_in(0, Location::RequiresRegister()); | 605 locs->set_in(0, Location::RequiresRegister()); |
| 588 // Only one input can be a constant operand. The case of two constant | 606 // Only one input can be a constant operand. The case of two constant |
| 589 // operands should be handled by constant propagation. | 607 // operands should be handled by constant propagation. |
| 590 locs->set_in(1, Location::RegisterOrConstant(right())); | 608 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 591 return locs; | 609 return locs; |
| 592 } | 610 } |
| 593 | 611 |
| 594 | 612 |
| 595 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 613 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 596 BranchLabels labels) { | 614 BranchLabels labels) { |
| 597 const Register left = locs()->in(0).reg(); | 615 const Register left = locs()->in(0).reg(); |
| 598 Location right = locs()->in(1); | 616 Location right = locs()->in(1); |
| 599 if (right.IsConstant()) { | 617 if (right.IsConstant()) { |
| 600 ASSERT(right.constant().IsSmi()); | 618 ASSERT(right.constant().IsSmi()); |
| 601 const int64_t imm = | 619 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); |
| 602 reinterpret_cast<int64_t>(right.constant().raw()); | |
| 603 __ TestImmediate(left, imm); | 620 __ TestImmediate(left, imm); |
| 604 } else { | 621 } else { |
| 605 __ tst(left, Operand(right.reg())); | 622 __ tst(left, Operand(right.reg())); |
| 606 } | 623 } |
| 607 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; | 624 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |
| 608 return true_condition; | 625 return true_condition; |
| 609 } | 626 } |
| 610 | 627 |
| 611 | 628 |
| 612 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 629 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 613 // Never emitted outside of the BranchInstr. | 630 // Never emitted outside of the BranchInstr. |
| 614 UNREACHABLE(); | 631 UNREACHABLE(); |
| 615 } | 632 } |
| 616 | 633 |
| 617 | 634 |
| 618 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 635 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 619 BranchInstr* branch) { | 636 BranchInstr* branch) { |
| 620 BranchLabels labels = compiler->CreateBranchLabels(branch); | 637 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 621 Condition true_condition = EmitComparisonCode(compiler, labels); | 638 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 622 EmitBranchOnCondition(compiler, true_condition, labels); | 639 EmitBranchOnCondition(compiler, true_condition, labels); |
| 623 } | 640 } |
| 624 | 641 |
| 625 | 642 |
| 626 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 643 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
| 627 bool opt) const { | 644 bool opt) const { |
| 628 const intptr_t kNumInputs = 1; | 645 const intptr_t kNumInputs = 1; |
| 629 const intptr_t kNumTemps = 1; | 646 const intptr_t kNumTemps = 1; |
| 630 LocationSummary* locs = new(zone) LocationSummary( | 647 LocationSummary* locs = new (zone) |
| 631 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 648 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 632 locs->set_in(0, Location::RequiresRegister()); | 649 locs->set_in(0, Location::RequiresRegister()); |
| 633 locs->set_temp(0, Location::RequiresRegister()); | 650 locs->set_temp(0, Location::RequiresRegister()); |
| 634 locs->set_out(0, Location::RequiresRegister()); | 651 locs->set_out(0, Location::RequiresRegister()); |
| 635 return locs; | 652 return locs; |
| 636 } | 653 } |
| 637 | 654 |
| 638 | 655 |
| 639 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 656 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 640 BranchLabels labels) { | 657 BranchLabels labels) { |
| 641 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 658 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
| 642 const Register val_reg = locs()->in(0).reg(); | 659 const Register val_reg = locs()->in(0).reg(); |
| 643 const Register cid_reg = locs()->temp(0).reg(); | 660 const Register cid_reg = locs()->temp(0).reg(); |
| 644 | 661 |
| 645 Label* deopt = CanDeoptimize() | 662 Label* deopt = |
| 646 ? compiler->AddDeoptStub(deopt_id(), | 663 CanDeoptimize() |
| 647 ICData::kDeoptTestCids, | 664 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, |
| 648 licm_hoisted_ ? ICData::kHoisted : 0) | 665 licm_hoisted_ ? ICData::kHoisted : 0) |
| 649 : NULL; | 666 : NULL; |
| 650 | 667 |
| 651 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 668 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
| 652 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 669 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
| 653 ASSERT(data[0] == kSmiCid); | 670 ASSERT(data[0] == kSmiCid); |
| 654 bool result = data[1] == true_result; | 671 bool result = data[1] == true_result; |
| 655 __ tsti(val_reg, Immediate(kSmiTagMask)); | 672 __ tsti(val_reg, Immediate(kSmiTagMask)); |
| 656 __ b(result ? labels.true_label : labels.false_label, EQ); | 673 __ b(result ? labels.true_label : labels.false_label, EQ); |
| 657 __ LoadClassId(cid_reg, val_reg); | 674 __ LoadClassId(cid_reg, val_reg); |
| 658 | 675 |
| 659 for (intptr_t i = 2; i < data.length(); i += 2) { | 676 for (intptr_t i = 2; i < data.length(); i += 2) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 681 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 698 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 682 BranchInstr* branch) { | 699 BranchInstr* branch) { |
| 683 BranchLabels labels = compiler->CreateBranchLabels(branch); | 700 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 684 EmitComparisonCode(compiler, labels); | 701 EmitComparisonCode(compiler, labels); |
| 685 } | 702 } |
| 686 | 703 |
| 687 | 704 |
| 688 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 705 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 689 const Register result_reg = locs()->out(0).reg(); | 706 const Register result_reg = locs()->out(0).reg(); |
| 690 Label is_true, is_false, done; | 707 Label is_true, is_false, done; |
| 691 BranchLabels labels = { &is_true, &is_false, &is_false }; | 708 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 692 EmitComparisonCode(compiler, labels); | 709 EmitComparisonCode(compiler, labels); |
| 693 // TODO(zra): instead of branching, use the csel instruction to get | 710 // TODO(zra): instead of branching, use the csel instruction to get |
| 694 // True or False into result. | 711 // True or False into result. |
| 695 __ Bind(&is_false); | 712 __ Bind(&is_false); |
| 696 __ LoadObject(result_reg, Bool::False()); | 713 __ LoadObject(result_reg, Bool::False()); |
| 697 __ b(&done); | 714 __ b(&done); |
| 698 __ Bind(&is_true); | 715 __ Bind(&is_true); |
| 699 __ LoadObject(result_reg, Bool::True()); | 716 __ LoadObject(result_reg, Bool::True()); |
| 700 __ Bind(&done); | 717 __ Bind(&done); |
| 701 } | 718 } |
| 702 | 719 |
| 703 | 720 |
| 704 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 721 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
| 705 bool opt) const { | 722 bool opt) const { |
| 706 const intptr_t kNumInputs = 2; | 723 const intptr_t kNumInputs = 2; |
| 707 const intptr_t kNumTemps = 0; | 724 const intptr_t kNumTemps = 0; |
| 708 if (operation_cid() == kDoubleCid) { | 725 if (operation_cid() == kDoubleCid) { |
| 709 LocationSummary* summary = new(zone) LocationSummary( | 726 LocationSummary* summary = new (zone) |
| 710 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 727 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 711 summary->set_in(0, Location::RequiresFpuRegister()); | 728 summary->set_in(0, Location::RequiresFpuRegister()); |
| 712 summary->set_in(1, Location::RequiresFpuRegister()); | 729 summary->set_in(1, Location::RequiresFpuRegister()); |
| 713 summary->set_out(0, Location::RequiresRegister()); | 730 summary->set_out(0, Location::RequiresRegister()); |
| 714 return summary; | 731 return summary; |
| 715 } | 732 } |
| 716 ASSERT(operation_cid() == kSmiCid); | 733 ASSERT(operation_cid() == kSmiCid); |
| 717 LocationSummary* summary = new(zone) LocationSummary( | 734 LocationSummary* summary = new (zone) |
| 718 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 735 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 719 summary->set_in(0, Location::RegisterOrConstant(left())); | 736 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 720 // Only one input can be a constant operand. The case of two constant | 737 // Only one input can be a constant operand. The case of two constant |
| 721 // operands should be handled by constant propagation. | 738 // operands should be handled by constant propagation. |
| 722 summary->set_in(1, summary->in(0).IsConstant() | 739 summary->set_in(1, summary->in(0).IsConstant() |
| 723 ? Location::RequiresRegister() | 740 ? Location::RequiresRegister() |
| 724 : Location::RegisterOrConstant(right())); | 741 : Location::RegisterOrConstant(right())); |
| 725 summary->set_out(0, Location::RequiresRegister()); | 742 summary->set_out(0, Location::RequiresRegister()); |
| 726 return summary; | 743 return summary; |
| 727 } | 744 } |
| 728 | 745 |
| 729 | 746 |
| 730 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 747 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 731 BranchLabels labels) { | 748 BranchLabels labels) { |
| 732 if (operation_cid() == kSmiCid) { | 749 if (operation_cid() == kSmiCid) { |
| 733 return EmitSmiComparisonOp(compiler, locs(), kind()); | 750 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 734 } else { | 751 } else { |
| 735 ASSERT(operation_cid() == kDoubleCid); | 752 ASSERT(operation_cid() == kDoubleCid); |
| 736 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 753 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
| 737 } | 754 } |
| 738 } | 755 } |
| 739 | 756 |
| 740 | 757 |
| 741 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 758 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 742 Label is_true, is_false; | 759 Label is_true, is_false; |
| 743 BranchLabels labels = { &is_true, &is_false, &is_false }; | 760 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 744 Condition true_condition = EmitComparisonCode(compiler, labels); | 761 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 745 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { | 762 if ((operation_cid() == kDoubleCid) && (true_condition != NE)) { |
| 746 // Special case for NaN comparison. Result is always false unless | 763 // Special case for NaN comparison. Result is always false unless |
| 747 // relational operator is !=. | 764 // relational operator is !=. |
| 748 __ b(&is_false, VS); | 765 __ b(&is_false, VS); |
| 749 } | 766 } |
| 750 EmitBranchOnCondition(compiler, true_condition, labels); | 767 EmitBranchOnCondition(compiler, true_condition, labels); |
| 751 // TODO(zra): instead of branching, use the csel instruction to get | 768 // TODO(zra): instead of branching, use the csel instruction to get |
| 752 // True or False into result. | 769 // True or False into result. |
| 753 const Register result = locs()->out(0).reg(); | 770 const Register result = locs()->out(0).reg(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 781 | 798 |
| 782 | 799 |
| 783 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 800 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 784 SetupNative(); | 801 SetupNative(); |
| 785 const Register result = locs()->out(0).reg(); | 802 const Register result = locs()->out(0).reg(); |
| 786 | 803 |
| 787 // Push the result place holder initialized to NULL. | 804 // Push the result place holder initialized to NULL. |
| 788 __ PushObject(Object::null_object()); | 805 __ PushObject(Object::null_object()); |
| 789 // Pass a pointer to the first argument in R2. | 806 // Pass a pointer to the first argument in R2. |
| 790 if (!function().HasOptionalParameters()) { | 807 if (!function().HasOptionalParameters()) { |
| 791 __ AddImmediate(R2, FP, (kParamEndSlotFromFp + | 808 __ AddImmediate( |
| 792 function().NumParameters()) * kWordSize); | 809 R2, FP, (kParamEndSlotFromFp + function().NumParameters()) * kWordSize); |
| 793 } else { | 810 } else { |
| 794 __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize); | 811 __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize); |
| 795 } | 812 } |
| 796 // Compute the effective address. When running under the simulator, | 813 // Compute the effective address. When running under the simulator, |
| 797 // this is a redirection address that forces the simulator to call | 814 // this is a redirection address that forces the simulator to call |
| 798 // into the runtime system. | 815 // into the runtime system. |
| 799 uword entry; | 816 uword entry; |
| 800 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 817 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
| 801 const StubEntry* stub_entry; | 818 const StubEntry* stub_entry; |
| 802 if (link_lazily()) { | 819 if (link_lazily()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 813 } else { | 830 } else { |
| 814 // In the case of non bootstrap native methods the CallNativeCFunction | 831 // In the case of non bootstrap native methods the CallNativeCFunction |
| 815 // stub generates the redirection address when running under the simulator | 832 // stub generates the redirection address when running under the simulator |
| 816 // and hence we do not change 'entry' here. | 833 // and hence we do not change 'entry' here. |
| 817 stub_entry = StubCode::CallNativeCFunction_entry(); | 834 stub_entry = StubCode::CallNativeCFunction_entry(); |
| 818 } | 835 } |
| 819 } | 836 } |
| 820 __ LoadImmediate(R1, argc_tag); | 837 __ LoadImmediate(R1, argc_tag); |
| 821 ExternalLabel label(entry); | 838 ExternalLabel label(entry); |
| 822 __ LoadNativeEntry(R5, &label); | 839 __ LoadNativeEntry(R5, &label); |
| 823 compiler->GenerateCall(token_pos(), | 840 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, |
| 824 *stub_entry, | |
| 825 RawPcDescriptors::kOther, | |
| 826 locs()); | 841 locs()); |
| 827 __ Pop(result); | 842 __ Pop(result); |
| 828 } | 843 } |
| 829 | 844 |
| 830 | 845 |
| 831 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 846 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |
| 832 Zone* zone, bool opt) const { | 847 Zone* zone, |
| 848 bool opt) const { |
| 833 const intptr_t kNumInputs = 1; | 849 const intptr_t kNumInputs = 1; |
| 834 // TODO(fschneider): Allow immediate operands for the char code. | 850 // TODO(fschneider): Allow immediate operands for the char code. |
| 835 return LocationSummary::Make(zone, | 851 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 836 kNumInputs, | |
| 837 Location::RequiresRegister(), | |
| 838 LocationSummary::kNoCall); | 852 LocationSummary::kNoCall); |
| 839 } | 853 } |
| 840 | 854 |
| 841 | 855 |
| 842 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 856 void OneByteStringFromCharCodeInstr::EmitNativeCode( |
| 843 FlowGraphCompiler* compiler) { | 857 FlowGraphCompiler* compiler) { |
| 844 ASSERT(compiler->is_optimizing()); | 858 ASSERT(compiler->is_optimizing()); |
| 845 const Register char_code = locs()->in(0).reg(); | 859 const Register char_code = locs()->in(0).reg(); |
| 846 const Register result = locs()->out(0).reg(); | 860 const Register result = locs()->out(0).reg(); |
| 847 | 861 |
| 848 __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset())); | 862 __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset())); |
| 849 __ AddImmediate( | 863 __ AddImmediate(result, result, |
| 850 result, result, Symbols::kNullCharCodeSymbolOffset * kWordSize); | 864 Symbols::kNullCharCodeSymbolOffset * kWordSize); |
| 851 __ SmiUntag(TMP, char_code); // Untag to use scaled adress mode. | 865 __ SmiUntag(TMP, char_code); // Untag to use scaled adress mode. |
| 852 __ ldr(result, Address(result, TMP, UXTX, Address::Scaled)); | 866 __ ldr(result, Address(result, TMP, UXTX, Address::Scaled)); |
| 853 } | 867 } |
| 854 | 868 |
| 855 | 869 |
| 856 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 870 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
| 857 bool opt) const { | 871 bool opt) const { |
| 858 const intptr_t kNumInputs = 1; | 872 const intptr_t kNumInputs = 1; |
| 859 return LocationSummary::Make(zone, | 873 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 860 kNumInputs, | |
| 861 Location::RequiresRegister(), | |
| 862 LocationSummary::kNoCall); | 874 LocationSummary::kNoCall); |
| 863 } | 875 } |
| 864 | 876 |
| 865 | 877 |
| 866 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 878 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 867 ASSERT(cid_ == kOneByteStringCid); | 879 ASSERT(cid_ == kOneByteStringCid); |
| 868 const Register str = locs()->in(0).reg(); | 880 const Register str = locs()->in(0).reg(); |
| 869 const Register result = locs()->out(0).reg(); | 881 const Register result = locs()->out(0).reg(); |
| 870 __ LoadFieldFromOffset(result, str, String::length_offset()); | 882 __ LoadFieldFromOffset(result, str, String::length_offset()); |
| 871 __ ldr(TMP, FieldAddress(str, OneByteString::data_offset()), kUnsignedByte); | 883 __ ldr(TMP, FieldAddress(str, OneByteString::data_offset()), kUnsignedByte); |
| 872 __ CompareImmediate(result, Smi::RawValue(1)); | 884 __ CompareImmediate(result, Smi::RawValue(1)); |
| 873 __ LoadImmediate(result, -1); | 885 __ LoadImmediate(result, -1); |
| 874 __ csel(result, TMP, result, EQ); | 886 __ csel(result, TMP, result, EQ); |
| 875 __ SmiTag(result); | 887 __ SmiTag(result); |
| 876 } | 888 } |
| 877 | 889 |
| 878 | 890 |
| 879 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 891 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |
| 880 bool opt) const { | 892 bool opt) const { |
| 881 const intptr_t kNumInputs = 1; | 893 const intptr_t kNumInputs = 1; |
| 882 const intptr_t kNumTemps = 0; | 894 const intptr_t kNumTemps = 0; |
| 883 LocationSummary* summary = new(zone) LocationSummary( | 895 LocationSummary* summary = new (zone) |
| 884 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 896 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 885 summary->set_in(0, Location::RegisterLocation(R0)); | 897 summary->set_in(0, Location::RegisterLocation(R0)); |
| 886 summary->set_out(0, Location::RegisterLocation(R0)); | 898 summary->set_out(0, Location::RegisterLocation(R0)); |
| 887 return summary; | 899 return summary; |
| 888 } | 900 } |
| 889 | 901 |
| 890 | 902 |
| 891 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 903 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 892 const Register array = locs()->in(0).reg(); | 904 const Register array = locs()->in(0).reg(); |
| 893 __ Push(array); | 905 __ Push(array); |
| 894 const int kNumberOfArguments = 1; | 906 const int kNumberOfArguments = 1; |
| 895 const Array& kNoArgumentNames = Object::null_array(); | 907 const Array& kNoArgumentNames = Object::null_array(); |
| 896 compiler->GenerateStaticCall(deopt_id(), | 908 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), |
| 897 token_pos(), | 909 kNumberOfArguments, kNoArgumentNames, locs(), |
| 898 CallFunction(), | |
| 899 kNumberOfArguments, | |
| 900 kNoArgumentNames, | |
| 901 locs(), | |
| 902 ICData::Handle()); | 910 ICData::Handle()); |
| 903 ASSERT(locs()->out(0).reg() == R0); | 911 ASSERT(locs()->out(0).reg() == R0); |
| 904 } | 912 } |
| 905 | 913 |
| 906 | 914 |
| 907 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 915 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |
| 908 bool opt) const { | 916 bool opt) const { |
| 909 const intptr_t kNumInputs = 1; | 917 const intptr_t kNumInputs = 1; |
| 910 return LocationSummary::Make(zone, | 918 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 911 kNumInputs, | |
| 912 Location::RequiresRegister(), | |
| 913 LocationSummary::kNoCall); | 919 LocationSummary::kNoCall); |
| 914 } | 920 } |
| 915 | 921 |
| 916 | 922 |
| 917 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 923 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 918 const Register obj = locs()->in(0).reg(); | 924 const Register obj = locs()->in(0).reg(); |
| 919 const Register result = locs()->out(0).reg(); | 925 const Register result = locs()->out(0).reg(); |
| 920 if (object()->definition()->representation() == kUntagged) { | 926 if (object()->definition()->representation() == kUntagged) { |
| 921 __ LoadFromOffset(result, obj, offset()); | 927 __ LoadFromOffset(result, obj, offset()); |
| 922 } else { | 928 } else { |
| 923 ASSERT(object()->definition()->representation() == kTagged); | 929 ASSERT(object()->definition()->representation() == kTagged); |
| 924 __ LoadFieldFromOffset(result, obj, offset()); | 930 __ LoadFieldFromOffset(result, obj, offset()); |
| 925 } | 931 } |
| 926 } | 932 } |
| 927 | 933 |
| 928 | 934 |
| 929 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 935 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |
| 930 bool opt) const { | 936 bool opt) const { |
| 931 const intptr_t kNumInputs = 1; | 937 const intptr_t kNumInputs = 1; |
| 932 return LocationSummary::Make(zone, | 938 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 933 kNumInputs, | |
| 934 Location::RequiresRegister(), | |
| 935 LocationSummary::kNoCall); | 939 LocationSummary::kNoCall); |
| 936 } | 940 } |
| 937 | 941 |
| 938 | 942 |
| 939 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 943 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 940 const Register object = locs()->in(0).reg(); | 944 const Register object = locs()->in(0).reg(); |
| 941 const Register result = locs()->out(0).reg(); | 945 const Register result = locs()->out(0).reg(); |
| 942 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 946 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |
| 943 if (CompileType::Smi().IsAssignableTo(value_type) || | 947 if (CompileType::Smi().IsAssignableTo(value_type) || |
| 944 value_type.IsTypeParameter()) { | 948 value_type.IsTypeParameter()) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1024 } | 1028 } |
| 1025 | 1029 |
| 1026 | 1030 |
| 1027 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) { | 1031 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) { |
| 1028 ConstantInstr* constant = value->definition()->AsConstant(); | 1032 ConstantInstr* constant = value->definition()->AsConstant(); |
| 1029 if ((constant == NULL) || !constant->value().IsSmi()) { | 1033 if ((constant == NULL) || !constant->value().IsSmi()) { |
| 1030 return false; | 1034 return false; |
| 1031 } | 1035 } |
| 1032 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); | 1036 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); |
| 1033 const intptr_t scale = Instance::ElementSizeFor(cid); | 1037 const intptr_t scale = Instance::ElementSizeFor(cid); |
| 1034 const int64_t offset = index * scale + | 1038 const int64_t offset = |
| 1039 index * scale + |
| 1035 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); | 1040 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); |
| 1036 if (!Utils::IsInt(32, offset)) { | 1041 if (!Utils::IsInt(32, offset)) { |
| 1037 return false; | 1042 return false; |
| 1038 } | 1043 } |
| 1039 return Address::CanHoldOffset(static_cast<int32_t>(offset), | 1044 return Address::CanHoldOffset(static_cast<int32_t>(offset), Address::Offset, |
| 1040 Address::Offset, | |
| 1041 Address::OperandSizeFor(cid)); | 1045 Address::OperandSizeFor(cid)); |
| 1042 } | 1046 } |
| 1043 | 1047 |
| 1044 | 1048 |
| 1045 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 1049 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1046 bool opt) const { | 1050 bool opt) const { |
| 1047 const intptr_t kNumInputs = 2; | 1051 const intptr_t kNumInputs = 2; |
| 1048 const intptr_t kNumTemps = aligned() ? 0 : 1; | 1052 const intptr_t kNumTemps = aligned() ? 0 : 1; |
| 1049 LocationSummary* locs = new(zone) LocationSummary( | 1053 LocationSummary* locs = new (zone) |
| 1050 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1054 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1051 locs->set_in(0, Location::RequiresRegister()); | 1055 locs->set_in(0, Location::RequiresRegister()); |
| 1052 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { | 1056 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { |
| 1053 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1057 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
| 1054 } else { | 1058 } else { |
| 1055 locs->set_in(1, Location::RequiresRegister()); | 1059 locs->set_in(1, Location::RequiresRegister()); |
| 1056 } | 1060 } |
| 1057 if ((representation() == kUnboxedDouble) || | 1061 if ((representation() == kUnboxedDouble) || |
| 1058 (representation() == kUnboxedFloat32x4) || | 1062 (representation() == kUnboxedFloat32x4) || |
| 1059 (representation() == kUnboxedInt32x4) || | 1063 (representation() == kUnboxedInt32x4) || |
| 1060 (representation() == kUnboxedFloat64x2)) { | 1064 (representation() == kUnboxedFloat64x2)) { |
| 1061 locs->set_out(0, Location::RequiresFpuRegister()); | 1065 locs->set_out(0, Location::RequiresFpuRegister()); |
| 1062 } else { | 1066 } else { |
| 1063 locs->set_out(0, Location::RequiresRegister()); | 1067 locs->set_out(0, Location::RequiresRegister()); |
| 1064 } | 1068 } |
| 1065 if (!aligned()) { | 1069 if (!aligned()) { |
| 1066 locs->set_temp(0, Location::RequiresRegister()); | 1070 locs->set_temp(0, Location::RequiresRegister()); |
| 1067 } | 1071 } |
| 1068 return locs; | 1072 return locs; |
| 1069 } | 1073 } |
| 1070 | 1074 |
| 1071 | 1075 |
| 1072 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1076 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1073 // The array register points to the backing store for external arrays. | 1077 // The array register points to the backing store for external arrays. |
| 1074 const Register array = locs()->in(0).reg(); | 1078 const Register array = locs()->in(0).reg(); |
| 1075 const Location index = locs()->in(1); | 1079 const Location index = locs()->in(1); |
| 1076 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); | 1080 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |
| 1077 | 1081 |
| 1078 Address element_address(TMP); // Bad address. | 1082 Address element_address(TMP); // Bad address. |
| 1079 if (aligned()) { | 1083 if (aligned()) { |
| 1080 element_address = index.IsRegister() | 1084 element_address = |
| 1081 ? __ ElementAddressForRegIndex(true, // Load. | 1085 index.IsRegister() |
| 1082 IsExternal(), class_id(), index_scale(), | 1086 ? __ ElementAddressForRegIndex(true, // Load. |
| 1083 array, index.reg()) | 1087 IsExternal(), class_id(), |
| 1084 : __ ElementAddressForIntIndex( | 1088 index_scale(), array, index.reg()) |
| 1085 IsExternal(), class_id(), index_scale(), | 1089 : __ ElementAddressForIntIndex(IsExternal(), class_id(), |
| 1086 array, Smi::Cast(index.constant()).Value()); | 1090 index_scale(), array, |
| 1091 Smi::Cast(index.constant()).Value()); |
| 1087 // Warning: element_address may use register TMP as base. | 1092 // Warning: element_address may use register TMP as base. |
| 1088 } else { | 1093 } else { |
| 1089 if (index.IsRegister()) { | 1094 if (index.IsRegister()) { |
| 1090 __ LoadElementAddressForRegIndex(address, | 1095 __ LoadElementAddressForRegIndex(address, |
| 1091 true, // Load. | 1096 true, // Load. |
| 1092 IsExternal(), class_id(), index_scale(), | 1097 IsExternal(), class_id(), index_scale(), |
| 1093 array, index.reg()); | 1098 array, index.reg()); |
| 1094 } else { | 1099 } else { |
| 1095 __ LoadElementAddressForIntIndex(address, | 1100 __ LoadElementAddressForIntIndex(address, IsExternal(), class_id(), |
| 1096 IsExternal(), class_id(), index_scale(), | 1101 index_scale(), array, |
| 1097 array, | |
| 1098 Smi::Cast(index.constant()).Value()); | 1102 Smi::Cast(index.constant()).Value()); |
| 1099 } | 1103 } |
| 1100 } | 1104 } |
| 1101 | 1105 |
| 1102 if ((representation() == kUnboxedDouble) || | 1106 if ((representation() == kUnboxedDouble) || |
| 1103 (representation() == kUnboxedFloat32x4) || | 1107 (representation() == kUnboxedFloat32x4) || |
| 1104 (representation() == kUnboxedInt32x4) || | 1108 (representation() == kUnboxedInt32x4) || |
| 1105 (representation() == kUnboxedFloat64x2)) { | 1109 (representation() == kUnboxedFloat64x2)) { |
| 1106 const VRegister result = locs()->out(0).fpu_reg(); | 1110 const VRegister result = locs()->out(0).fpu_reg(); |
| 1107 switch (class_id()) { | 1111 switch (class_id()) { |
| 1108 ASSERT(aligned()); | 1112 ASSERT(aligned()); |
| 1109 case kTypedDataFloat32ArrayCid: | 1113 case kTypedDataFloat32ArrayCid: |
| 1110 // Load single precision float. | 1114 // Load single precision float. |
| 1111 __ fldrs(result, element_address); | 1115 __ fldrs(result, element_address); |
| 1112 break; | 1116 break; |
| 1113 case kTypedDataFloat64ArrayCid: | 1117 case kTypedDataFloat64ArrayCid: |
| 1114 // Load double precision float. | 1118 // Load double precision float. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1140 case kTypedDataUint32ArrayCid: | 1144 case kTypedDataUint32ArrayCid: |
| 1141 ASSERT(representation() == kUnboxedUint32); | 1145 ASSERT(representation() == kUnboxedUint32); |
| 1142 if (aligned()) { | 1146 if (aligned()) { |
| 1143 __ ldr(result, element_address, kUnsignedWord); | 1147 __ ldr(result, element_address, kUnsignedWord); |
| 1144 } else { | 1148 } else { |
| 1145 __ LoadUnaligned(result, address, TMP, kUnsignedWord); | 1149 __ LoadUnaligned(result, address, TMP, kUnsignedWord); |
| 1146 } | 1150 } |
| 1147 break; | 1151 break; |
| 1148 default: | 1152 default: |
| 1149 UNREACHABLE(); | 1153 UNREACHABLE(); |
| 1150 } | 1154 } |
| 1151 return; | 1155 return; |
| 1152 } | 1156 } |
| 1153 | 1157 |
| 1154 ASSERT(representation() == kTagged); | 1158 ASSERT(representation() == kTagged); |
| 1155 const Register result = locs()->out(0).reg(); | 1159 const Register result = locs()->out(0).reg(); |
| 1156 switch (class_id()) { | 1160 switch (class_id()) { |
| 1157 case kTypedDataInt8ArrayCid: | 1161 case kTypedDataInt8ArrayCid: |
| 1158 ASSERT(index_scale() == 1); | 1162 ASSERT(index_scale() == 1); |
| 1159 __ ldr(result, element_address, kByte); | 1163 __ ldr(result, element_address, kByte); |
| 1160 __ SmiTag(result); | 1164 __ SmiTag(result); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1193 __ ldr(result, element_address); | 1197 __ ldr(result, element_address); |
| 1194 break; | 1198 break; |
| 1195 } | 1199 } |
| 1196 } | 1200 } |
| 1197 | 1201 |
| 1198 | 1202 |
| 1199 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 1203 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |
| 1200 bool opt) const { | 1204 bool opt) const { |
| 1201 const intptr_t kNumInputs = 2; | 1205 const intptr_t kNumInputs = 2; |
| 1202 const intptr_t kNumTemps = 0; | 1206 const intptr_t kNumTemps = 0; |
| 1203 LocationSummary* summary = new(zone) LocationSummary( | 1207 LocationSummary* summary = new (zone) |
| 1204 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1208 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1205 summary->set_in(0, Location::RequiresRegister()); | 1209 summary->set_in(0, Location::RequiresRegister()); |
| 1206 summary->set_in(1, Location::RequiresRegister()); | 1210 summary->set_in(1, Location::RequiresRegister()); |
| 1207 summary->set_out(0, Location::RequiresRegister()); | 1211 summary->set_out(0, Location::RequiresRegister()); |
| 1208 return summary; | 1212 return summary; |
| 1209 } | 1213 } |
| 1210 | 1214 |
| 1211 | 1215 |
| 1212 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1216 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1213 // The string register points to the backing store for external strings. | 1217 // The string register points to the backing store for external strings. |
| 1214 const Register str = locs()->in(0).reg(); | 1218 const Register str = locs()->in(0).reg(); |
| 1215 const Location index = locs()->in(1); | 1219 const Location index = locs()->in(1); |
| 1216 | 1220 |
| 1217 Address element_address = __ ElementAddressForRegIndex( | 1221 Address element_address = __ ElementAddressForRegIndex( |
| 1218 true, IsExternal(), class_id(), index_scale(), str, index.reg()); | 1222 true, IsExternal(), class_id(), index_scale(), str, index.reg()); |
| 1219 // Warning: element_address may use register TMP as base. | 1223 // Warning: element_address may use register TMP as base. |
| 1220 | 1224 |
| 1221 Register result = locs()->out(0).reg(); | 1225 Register result = locs()->out(0).reg(); |
| 1222 switch (class_id()) { | 1226 switch (class_id()) { |
| 1223 case kOneByteStringCid: | 1227 case kOneByteStringCid: |
| 1224 case kExternalOneByteStringCid: | 1228 case kExternalOneByteStringCid: |
| 1225 switch (element_count()) { | 1229 switch (element_count()) { |
| 1226 case 1: __ ldr(result, element_address, kUnsignedByte); break; | 1230 case 1: |
| 1227 case 2: __ ldr(result, element_address, kUnsignedHalfword); break; | 1231 __ ldr(result, element_address, kUnsignedByte); |
| 1228 case 4: __ ldr(result, element_address, kUnsignedWord); break; | 1232 break; |
| 1229 default: UNREACHABLE(); | 1233 case 2: |
| 1234 __ ldr(result, element_address, kUnsignedHalfword); |
| 1235 break; |
| 1236 case 4: |
| 1237 __ ldr(result, element_address, kUnsignedWord); |
| 1238 break; |
| 1239 default: |
| 1240 UNREACHABLE(); |
| 1230 } | 1241 } |
| 1231 __ SmiTag(result); | 1242 __ SmiTag(result); |
| 1232 break; | 1243 break; |
| 1233 case kTwoByteStringCid: | 1244 case kTwoByteStringCid: |
| 1234 case kExternalTwoByteStringCid: | 1245 case kExternalTwoByteStringCid: |
| 1235 switch (element_count()) { | 1246 switch (element_count()) { |
| 1236 case 1: __ ldr(result, element_address, kUnsignedHalfword); break; | 1247 case 1: |
| 1237 case 2: __ ldr(result, element_address, kUnsignedWord); break; | 1248 __ ldr(result, element_address, kUnsignedHalfword); |
| 1238 default: UNREACHABLE(); | 1249 break; |
| 1250 case 2: |
| 1251 __ ldr(result, element_address, kUnsignedWord); |
| 1252 break; |
| 1253 default: |
| 1254 UNREACHABLE(); |
| 1239 } | 1255 } |
| 1240 __ SmiTag(result); | 1256 __ SmiTag(result); |
| 1241 break; | 1257 break; |
| 1242 default: | 1258 default: |
| 1243 UNREACHABLE(); | 1259 UNREACHABLE(); |
| 1244 break; | 1260 break; |
| 1245 } | 1261 } |
| 1246 } | 1262 } |
| 1247 | 1263 |
| 1248 | 1264 |
| 1249 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1265 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 1250 intptr_t idx) const { | 1266 intptr_t idx) const { |
| 1251 // Array can be a Dart object or a pointer to external data. | 1267 // Array can be a Dart object or a pointer to external data. |
| 1252 if (idx == 0) return kNoRepresentation; // Flexible input representation. | 1268 if (idx == 0) return kNoRepresentation; // Flexible input representation. |
| 1253 if (idx == 1) return kTagged; // Index is a smi. | 1269 if (idx == 1) return kTagged; // Index is a smi. |
| 1254 ASSERT(idx == 2); | 1270 ASSERT(idx == 2); |
| 1255 switch (class_id_) { | 1271 switch (class_id_) { |
| 1256 case kArrayCid: | 1272 case kArrayCid: |
| 1257 case kOneByteStringCid: | 1273 case kOneByteStringCid: |
| 1258 case kTypedDataInt8ArrayCid: | 1274 case kTypedDataInt8ArrayCid: |
| 1259 case kTypedDataUint8ArrayCid: | 1275 case kTypedDataUint8ArrayCid: |
| 1260 case kExternalTypedDataUint8ArrayCid: | 1276 case kExternalTypedDataUint8ArrayCid: |
| 1261 case kTypedDataUint8ClampedArrayCid: | 1277 case kTypedDataUint8ClampedArrayCid: |
| 1262 case kExternalTypedDataUint8ClampedArrayCid: | 1278 case kExternalTypedDataUint8ClampedArrayCid: |
| 1263 case kTypedDataInt16ArrayCid: | 1279 case kTypedDataInt16ArrayCid: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1280 UNREACHABLE(); | 1296 UNREACHABLE(); |
| 1281 return kTagged; | 1297 return kTagged; |
| 1282 } | 1298 } |
| 1283 } | 1299 } |
| 1284 | 1300 |
| 1285 | 1301 |
| 1286 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1302 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1287 bool opt) const { | 1303 bool opt) const { |
| 1288 const intptr_t kNumInputs = 3; | 1304 const intptr_t kNumInputs = 3; |
| 1289 const intptr_t kNumTemps = aligned() ? 0 : 2; | 1305 const intptr_t kNumTemps = aligned() ? 0 : 2; |
| 1290 LocationSummary* locs = new(zone) LocationSummary( | 1306 LocationSummary* locs = new (zone) |
| 1291 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1307 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1292 locs->set_in(0, Location::RequiresRegister()); | 1308 locs->set_in(0, Location::RequiresRegister()); |
| 1293 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { | 1309 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { |
| 1294 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1310 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
| 1295 } else { | 1311 } else { |
| 1296 locs->set_in(1, Location::WritableRegister()); | 1312 locs->set_in(1, Location::WritableRegister()); |
| 1297 } | 1313 } |
| 1298 switch (class_id()) { | 1314 switch (class_id()) { |
| 1299 case kArrayCid: | 1315 case kArrayCid: |
| 1300 locs->set_in(2, ShouldEmitStoreBarrier() | 1316 locs->set_in(2, ShouldEmitStoreBarrier() |
| 1301 ? Location::WritableRegister() | 1317 ? Location::WritableRegister() |
| 1302 : Location::RegisterOrConstant(value())); | 1318 : Location::RegisterOrConstant(value())); |
| 1303 break; | 1319 break; |
| 1304 case kExternalTypedDataUint8ArrayCid: | 1320 case kExternalTypedDataUint8ArrayCid: |
| 1305 case kExternalTypedDataUint8ClampedArrayCid: | 1321 case kExternalTypedDataUint8ClampedArrayCid: |
| 1306 case kTypedDataInt8ArrayCid: | 1322 case kTypedDataInt8ArrayCid: |
| 1307 case kTypedDataUint8ArrayCid: | 1323 case kTypedDataUint8ArrayCid: |
| 1308 case kTypedDataUint8ClampedArrayCid: | 1324 case kTypedDataUint8ClampedArrayCid: |
| 1309 case kOneByteStringCid: | 1325 case kOneByteStringCid: |
| 1310 case kTypedDataInt16ArrayCid: | 1326 case kTypedDataInt16ArrayCid: |
| 1311 case kTypedDataUint16ArrayCid: | 1327 case kTypedDataUint16ArrayCid: |
| 1312 case kTypedDataInt32ArrayCid: | 1328 case kTypedDataInt32ArrayCid: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1336 | 1352 |
| 1337 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1353 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1338 // The array register points to the backing store for external arrays. | 1354 // The array register points to the backing store for external arrays. |
| 1339 const Register array = locs()->in(0).reg(); | 1355 const Register array = locs()->in(0).reg(); |
| 1340 const Location index = locs()->in(1); | 1356 const Location index = locs()->in(1); |
| 1341 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); | 1357 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |
| 1342 const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg(); | 1358 const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg(); |
| 1343 | 1359 |
| 1344 Address element_address(TMP); // Bad address. | 1360 Address element_address(TMP); // Bad address. |
| 1345 if (aligned()) { | 1361 if (aligned()) { |
| 1346 element_address = index.IsRegister() | 1362 element_address = |
| 1347 ? __ ElementAddressForRegIndex(false, // Store. | 1363 index.IsRegister() |
| 1348 IsExternal(), class_id(), index_scale(), | 1364 ? __ ElementAddressForRegIndex(false, // Store. |
| 1349 array, index.reg()) | 1365 IsExternal(), class_id(), |
| 1350 : __ ElementAddressForIntIndex( | 1366 index_scale(), array, index.reg()) |
| 1351 IsExternal(), class_id(), index_scale(), | 1367 : __ ElementAddressForIntIndex(IsExternal(), class_id(), |
| 1352 array, Smi::Cast(index.constant()).Value()); | 1368 index_scale(), array, |
| 1369 Smi::Cast(index.constant()).Value()); |
| 1353 } else { | 1370 } else { |
| 1354 if (index.IsRegister()) { | 1371 if (index.IsRegister()) { |
| 1355 __ LoadElementAddressForRegIndex(address, | 1372 __ LoadElementAddressForRegIndex(address, |
| 1356 false, // Store. | 1373 false, // Store. |
| 1357 IsExternal(), class_id(), index_scale(), | 1374 IsExternal(), class_id(), index_scale(), |
| 1358 array, index.reg()); | 1375 array, index.reg()); |
| 1359 } else { | 1376 } else { |
| 1360 __ LoadElementAddressForIntIndex(address, | 1377 __ LoadElementAddressForIntIndex(address, IsExternal(), class_id(), |
| 1361 IsExternal(), class_id(), index_scale(), | 1378 index_scale(), array, |
| 1362 array, | |
| 1363 Smi::Cast(index.constant()).Value()); | 1379 Smi::Cast(index.constant()).Value()); |
| 1364 } | 1380 } |
| 1365 } | 1381 } |
| 1366 | 1382 |
| 1367 switch (class_id()) { | 1383 switch (class_id()) { |
| 1368 case kArrayCid: | 1384 case kArrayCid: |
| 1369 ASSERT(aligned()); | 1385 ASSERT(aligned()); |
| 1370 if (ShouldEmitStoreBarrier()) { | 1386 if (ShouldEmitStoreBarrier()) { |
| 1371 const Register value = locs()->in(2).reg(); | 1387 const Register value = locs()->in(2).reg(); |
| 1372 __ StoreIntoObject(array, element_address, value); | 1388 __ StoreIntoObject(array, element_address, value); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1405 value = 0xFF; | 1421 value = 0xFF; |
| 1406 } else if (value < 0) { | 1422 } else if (value < 0) { |
| 1407 value = 0; | 1423 value = 0; |
| 1408 } | 1424 } |
| 1409 __ LoadImmediate(TMP, static_cast<int8_t>(value)); | 1425 __ LoadImmediate(TMP, static_cast<int8_t>(value)); |
| 1410 __ str(TMP, element_address, kUnsignedByte); | 1426 __ str(TMP, element_address, kUnsignedByte); |
| 1411 } else { | 1427 } else { |
| 1412 const Register value = locs()->in(2).reg(); | 1428 const Register value = locs()->in(2).reg(); |
| 1413 __ CompareImmediate(value, 0x1FE); // Smi value and smi 0xFF. | 1429 __ CompareImmediate(value, 0x1FE); // Smi value and smi 0xFF. |
| 1414 // Clamp to 0x00 or 0xFF respectively. | 1430 // Clamp to 0x00 or 0xFF respectively. |
| 1415 __ csetm(TMP, GT); // TMP = value > 0x1FE ? -1 : 0. | 1431 __ csetm(TMP, GT); // TMP = value > 0x1FE ? -1 : 0. |
| 1416 __ csel(TMP, value, TMP, LS); // TMP = value in range ? value : TMP. | 1432 __ csel(TMP, value, TMP, LS); // TMP = value in range ? value : TMP. |
| 1417 __ SmiUntag(TMP); | 1433 __ SmiUntag(TMP); |
| 1418 __ str(TMP, element_address, kUnsignedByte); | 1434 __ str(TMP, element_address, kUnsignedByte); |
| 1419 } | 1435 } |
| 1420 break; | 1436 break; |
| 1421 } | 1437 } |
| 1422 case kTypedDataInt16ArrayCid: | 1438 case kTypedDataInt16ArrayCid: |
| 1423 case kTypedDataUint16ArrayCid: { | 1439 case kTypedDataUint16ArrayCid: { |
| 1424 const Register value = locs()->in(2).reg(); | 1440 const Register value = locs()->in(2).reg(); |
| 1425 __ SmiUntag(TMP, value); | 1441 __ SmiUntag(TMP, value); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1485 } | 1501 } |
| 1486 | 1502 |
| 1487 | 1503 |
| 1488 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 1504 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |
| 1489 bool opt) const { | 1505 bool opt) const { |
| 1490 const intptr_t kNumInputs = 1; | 1506 const intptr_t kNumInputs = 1; |
| 1491 | 1507 |
| 1492 const intptr_t value_cid = value()->Type()->ToCid(); | 1508 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1493 const intptr_t field_cid = field().guarded_cid(); | 1509 const intptr_t field_cid = field().guarded_cid(); |
| 1494 | 1510 |
| 1495 const bool emit_full_guard = | 1511 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); |
| 1496 !opt || (field_cid == kIllegalCid); | |
| 1497 | 1512 |
| 1498 const bool needs_value_cid_temp_reg = emit_full_guard || | 1513 const bool needs_value_cid_temp_reg = |
| 1499 ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); | 1514 emit_full_guard || ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); |
| 1500 | 1515 |
| 1501 const bool needs_field_temp_reg = emit_full_guard; | 1516 const bool needs_field_temp_reg = emit_full_guard; |
| 1502 | 1517 |
| 1503 intptr_t num_temps = 0; | 1518 intptr_t num_temps = 0; |
| 1504 if (needs_value_cid_temp_reg) { | 1519 if (needs_value_cid_temp_reg) { |
| 1505 num_temps++; | 1520 num_temps++; |
| 1506 } | 1521 } |
| 1507 if (needs_field_temp_reg) { | 1522 if (needs_field_temp_reg) { |
| 1508 num_temps++; | 1523 num_temps++; |
| 1509 } | 1524 } |
| 1510 | 1525 |
| 1511 LocationSummary* summary = new(zone) LocationSummary( | 1526 LocationSummary* summary = new (zone) |
| 1512 zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 1527 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
| 1513 summary->set_in(0, Location::RequiresRegister()); | 1528 summary->set_in(0, Location::RequiresRegister()); |
| 1514 | 1529 |
| 1515 for (intptr_t i = 0; i < num_temps; i++) { | 1530 for (intptr_t i = 0; i < num_temps; i++) { |
| 1516 summary->set_temp(i, Location::RequiresRegister()); | 1531 summary->set_temp(i, Location::RequiresRegister()); |
| 1517 } | 1532 } |
| 1518 | 1533 |
| 1519 return summary; | 1534 return summary; |
| 1520 } | 1535 } |
| 1521 | 1536 |
| 1522 | 1537 |
| 1523 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1538 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1524 ASSERT(sizeof(classid_t) == kInt32Size); | 1539 ASSERT(sizeof(classid_t) == kInt32Size); |
| 1525 const intptr_t value_cid = value()->Type()->ToCid(); | 1540 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1526 const intptr_t field_cid = field().guarded_cid(); | 1541 const intptr_t field_cid = field().guarded_cid(); |
| 1527 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1542 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
| 1528 | 1543 |
| 1529 if (field_cid == kDynamicCid) { | 1544 if (field_cid == kDynamicCid) { |
| 1530 if (Compiler::IsBackgroundCompilation()) { | 1545 if (Compiler::IsBackgroundCompilation()) { |
| 1531 // Field state changed while compiling. | 1546 // Field state changed while compiling. |
| 1532 Compiler::AbortBackgroundCompilation(deopt_id(), | 1547 Compiler::AbortBackgroundCompilation( |
| 1548 deopt_id(), |
| 1533 "GuardFieldClassInstr: field state changed while compiling"); | 1549 "GuardFieldClassInstr: field state changed while compiling"); |
| 1534 } | 1550 } |
| 1535 ASSERT(!compiler->is_optimizing()); | 1551 ASSERT(!compiler->is_optimizing()); |
| 1536 return; // Nothing to emit. | 1552 return; // Nothing to emit. |
| 1537 } | 1553 } |
| 1538 | 1554 |
| 1539 const bool emit_full_guard = | 1555 const bool emit_full_guard = |
| 1540 !compiler->is_optimizing() || (field_cid == kIllegalCid); | 1556 !compiler->is_optimizing() || (field_cid == kIllegalCid); |
| 1541 | 1557 |
| 1542 const bool needs_value_cid_temp_reg = emit_full_guard || | 1558 const bool needs_value_cid_temp_reg = |
| 1543 ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); | 1559 emit_full_guard || ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); |
| 1544 | 1560 |
| 1545 const bool needs_field_temp_reg = emit_full_guard; | 1561 const bool needs_field_temp_reg = emit_full_guard; |
| 1546 | 1562 |
| 1547 const Register value_reg = locs()->in(0).reg(); | 1563 const Register value_reg = locs()->in(0).reg(); |
| 1548 | 1564 |
| 1549 const Register value_cid_reg = needs_value_cid_temp_reg ? | 1565 const Register value_cid_reg = |
| 1550 locs()->temp(0).reg() : kNoRegister; | 1566 needs_value_cid_temp_reg ? locs()->temp(0).reg() : kNoRegister; |
| 1551 | 1567 |
| 1552 const Register field_reg = needs_field_temp_reg ? | 1568 const Register field_reg = needs_field_temp_reg |
| 1553 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; | 1569 ? locs()->temp(locs()->temp_count() - 1).reg() |
| 1570 : kNoRegister; |
| 1554 | 1571 |
| 1555 Label ok, fail_label; | 1572 Label ok, fail_label; |
| 1556 | 1573 |
| 1557 Label* deopt = compiler->is_optimizing() ? | 1574 Label* deopt = |
| 1558 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1575 compiler->is_optimizing() |
| 1576 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1577 : NULL; |
| 1559 | 1578 |
| 1560 Label* fail = (deopt != NULL) ? deopt : &fail_label; | 1579 Label* fail = (deopt != NULL) ? deopt : &fail_label; |
| 1561 | 1580 |
| 1562 if (emit_full_guard) { | 1581 if (emit_full_guard) { |
| 1563 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1582 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
| 1564 | 1583 |
| 1565 FieldAddress field_cid_operand( | 1584 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset(), |
| 1566 field_reg, Field::guarded_cid_offset(), kUnsignedWord); | 1585 kUnsignedWord); |
| 1567 FieldAddress field_nullability_operand( | 1586 FieldAddress field_nullability_operand( |
| 1568 field_reg, Field::is_nullable_offset(), kUnsignedWord); | 1587 field_reg, Field::is_nullable_offset(), kUnsignedWord); |
| 1569 | 1588 |
| 1570 if (value_cid == kDynamicCid) { | 1589 if (value_cid == kDynamicCid) { |
| 1571 LoadValueCid(compiler, value_cid_reg, value_reg); | 1590 LoadValueCid(compiler, value_cid_reg, value_reg); |
| 1572 Label skip_length_check; | 1591 Label skip_length_check; |
| 1573 __ ldr(TMP, field_cid_operand, kUnsignedWord); | 1592 __ ldr(TMP, field_cid_operand, kUnsignedWord); |
| 1574 __ CompareRegisters(value_cid_reg, TMP); | 1593 __ CompareRegisters(value_cid_reg, TMP); |
| 1575 __ b(&ok, EQ); | 1594 __ b(&ok, EQ); |
| 1576 __ ldr(TMP, field_nullability_operand, kUnsignedWord); | 1595 __ ldr(TMP, field_nullability_operand, kUnsignedWord); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1610 if (deopt == NULL) { | 1629 if (deopt == NULL) { |
| 1611 ASSERT(!compiler->is_optimizing()); | 1630 ASSERT(!compiler->is_optimizing()); |
| 1612 __ b(&ok); | 1631 __ b(&ok); |
| 1613 } | 1632 } |
| 1614 } | 1633 } |
| 1615 | 1634 |
| 1616 if (deopt == NULL) { | 1635 if (deopt == NULL) { |
| 1617 ASSERT(!compiler->is_optimizing()); | 1636 ASSERT(!compiler->is_optimizing()); |
| 1618 __ Bind(fail); | 1637 __ Bind(fail); |
| 1619 | 1638 |
| 1620 __ LoadFieldFromOffset( | 1639 __ LoadFieldFromOffset(TMP, field_reg, Field::guarded_cid_offset(), |
| 1621 TMP, field_reg, Field::guarded_cid_offset(), kUnsignedWord); | 1640 kUnsignedWord); |
| 1622 __ CompareImmediate(TMP, kDynamicCid); | 1641 __ CompareImmediate(TMP, kDynamicCid); |
| 1623 __ b(&ok, EQ); | 1642 __ b(&ok, EQ); |
| 1624 | 1643 |
| 1625 __ Push(field_reg); | 1644 __ Push(field_reg); |
| 1626 __ Push(value_reg); | 1645 __ Push(value_reg); |
| 1627 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); | 1646 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); |
| 1628 __ Drop(2); // Drop the field and the value. | 1647 __ Drop(2); // Drop the field and the value. |
| 1629 } | 1648 } |
| 1630 } else { | 1649 } else { |
| 1631 ASSERT(compiler->is_optimizing()); | 1650 ASSERT(compiler->is_optimizing()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1656 } | 1675 } |
| 1657 __ Bind(&ok); | 1676 __ Bind(&ok); |
| 1658 } | 1677 } |
| 1659 | 1678 |
| 1660 | 1679 |
| 1661 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 1680 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |
| 1662 bool opt) const { | 1681 bool opt) const { |
| 1663 const intptr_t kNumInputs = 1; | 1682 const intptr_t kNumInputs = 1; |
| 1664 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1683 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
| 1665 const intptr_t kNumTemps = 3; | 1684 const intptr_t kNumTemps = 3; |
| 1666 LocationSummary* summary = new(zone) LocationSummary( | 1685 LocationSummary* summary = new (zone) |
| 1667 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1686 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1668 summary->set_in(0, Location::RequiresRegister()); | 1687 summary->set_in(0, Location::RequiresRegister()); |
| 1669 // We need temporaries for field object, length offset and expected length. | 1688 // We need temporaries for field object, length offset and expected length. |
| 1670 summary->set_temp(0, Location::RequiresRegister()); | 1689 summary->set_temp(0, Location::RequiresRegister()); |
| 1671 summary->set_temp(1, Location::RequiresRegister()); | 1690 summary->set_temp(1, Location::RequiresRegister()); |
| 1672 summary->set_temp(2, Location::RequiresRegister()); | 1691 summary->set_temp(2, Location::RequiresRegister()); |
| 1673 return summary; | 1692 return summary; |
| 1674 } else { | 1693 } else { |
| 1675 LocationSummary* summary = new(zone) LocationSummary( | 1694 LocationSummary* summary = new (zone) |
| 1676 zone, kNumInputs, 0, LocationSummary::kNoCall); | 1695 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 1677 summary->set_in(0, Location::RequiresRegister()); | 1696 summary->set_in(0, Location::RequiresRegister()); |
| 1678 return summary; | 1697 return summary; |
| 1679 } | 1698 } |
| 1680 UNREACHABLE(); | 1699 UNREACHABLE(); |
| 1681 } | 1700 } |
| 1682 | 1701 |
| 1683 | 1702 |
| 1684 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1703 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1685 if (field().guarded_list_length() == Field::kNoFixedLength) { | 1704 if (field().guarded_list_length() == Field::kNoFixedLength) { |
| 1686 if (Compiler::IsBackgroundCompilation()) { | 1705 if (Compiler::IsBackgroundCompilation()) { |
| 1687 // Field state changed while compiling. | 1706 // Field state changed while compiling. |
| 1688 Compiler::AbortBackgroundCompilation(deopt_id(), | 1707 Compiler::AbortBackgroundCompilation( |
| 1708 deopt_id(), |
| 1689 "GuardFieldLengthInstr: field state changed while compiling"); | 1709 "GuardFieldLengthInstr: field state changed while compiling"); |
| 1690 } | 1710 } |
| 1691 ASSERT(!compiler->is_optimizing()); | 1711 ASSERT(!compiler->is_optimizing()); |
| 1692 return; // Nothing to emit. | 1712 return; // Nothing to emit. |
| 1693 } | 1713 } |
| 1694 | 1714 |
| 1695 Label* deopt = compiler->is_optimizing() ? | 1715 Label* deopt = |
| 1696 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1716 compiler->is_optimizing() |
| 1717 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1718 : NULL; |
| 1697 | 1719 |
| 1698 const Register value_reg = locs()->in(0).reg(); | 1720 const Register value_reg = locs()->in(0).reg(); |
| 1699 | 1721 |
| 1700 if (!compiler->is_optimizing() || | 1722 if (!compiler->is_optimizing() || |
| 1701 (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1723 (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
| 1702 const Register field_reg = locs()->temp(0).reg(); | 1724 const Register field_reg = locs()->temp(0).reg(); |
| 1703 const Register offset_reg = locs()->temp(1).reg(); | 1725 const Register offset_reg = locs()->temp(1).reg(); |
| 1704 const Register length_reg = locs()->temp(2).reg(); | 1726 const Register length_reg = locs()->temp(2).reg(); |
| 1705 | 1727 |
| 1706 Label ok; | 1728 Label ok; |
| 1707 | 1729 |
| 1708 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1730 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
| 1709 | 1731 |
| 1710 __ ldr(offset_reg, | 1732 __ ldr(offset_reg, |
| 1711 FieldAddress(field_reg, | 1733 FieldAddress(field_reg, |
| 1712 Field::guarded_list_length_in_object_offset_offset()), | 1734 Field::guarded_list_length_in_object_offset_offset()), |
| 1713 kByte); | 1735 kByte); |
| 1714 __ ldr(length_reg, FieldAddress(field_reg, | 1736 __ ldr(length_reg, |
| 1715 Field::guarded_list_length_offset())); | 1737 FieldAddress(field_reg, Field::guarded_list_length_offset())); |
| 1716 | 1738 |
| 1717 __ tst(offset_reg, Operand(offset_reg)); | 1739 __ tst(offset_reg, Operand(offset_reg)); |
| 1718 __ b(&ok, MI); | 1740 __ b(&ok, MI); |
| 1719 | 1741 |
| 1720 // Load the length from the value. GuardFieldClass already verified that | 1742 // Load the length from the value. GuardFieldClass already verified that |
| 1721 // value's class matches guarded class id of the field. | 1743 // value's class matches guarded class id of the field. |
| 1722 // offset_reg contains offset already corrected by -kHeapObjectTag that is | 1744 // offset_reg contains offset already corrected by -kHeapObjectTag that is |
| 1723 // why we use Address instead of FieldAddress. | 1745 // why we use Address instead of FieldAddress. |
| 1724 __ ldr(TMP, Address(value_reg, offset_reg)); | 1746 __ ldr(TMP, Address(value_reg, offset_reg)); |
| 1725 __ CompareRegisters(length_reg, TMP); | 1747 __ CompareRegisters(length_reg, TMP); |
| 1726 | 1748 |
| 1727 if (deopt == NULL) { | 1749 if (deopt == NULL) { |
| 1728 __ b(&ok, EQ); | 1750 __ b(&ok, EQ); |
| 1729 | 1751 |
| 1730 __ Push(field_reg); | 1752 __ Push(field_reg); |
| 1731 __ Push(value_reg); | 1753 __ Push(value_reg); |
| 1732 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); | 1754 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); |
| 1733 __ Drop(2); // Drop the field and the value. | 1755 __ Drop(2); // Drop the field and the value. |
| 1734 } else { | 1756 } else { |
| 1735 __ b(deopt, NE); | 1757 __ b(deopt, NE); |
| 1736 } | 1758 } |
| 1737 | 1759 |
| 1738 __ Bind(&ok); | 1760 __ Bind(&ok); |
| 1739 } else { | 1761 } else { |
| 1740 ASSERT(compiler->is_optimizing()); | 1762 ASSERT(compiler->is_optimizing()); |
| 1741 ASSERT(field().guarded_list_length() >= 0); | 1763 ASSERT(field().guarded_list_length() >= 0); |
| 1742 ASSERT(field().guarded_list_length_in_object_offset() != | 1764 ASSERT(field().guarded_list_length_in_object_offset() != |
| 1743 Field::kUnknownLengthOffset); | 1765 Field::kUnknownLengthOffset); |
| 1744 | 1766 |
| 1745 __ ldr(TMP, FieldAddress(value_reg, | 1767 __ ldr(TMP, FieldAddress(value_reg, |
| 1746 field().guarded_list_length_in_object_offset())); | 1768 field().guarded_list_length_in_object_offset())); |
| 1747 __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length())); | 1769 __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length())); |
| 1748 __ b(deopt, NE); | 1770 __ b(deopt, NE); |
| 1749 } | 1771 } |
| 1750 } | 1772 } |
| 1751 | 1773 |
| 1752 | 1774 |
| 1753 class BoxAllocationSlowPath : public SlowPathCode { | 1775 class BoxAllocationSlowPath : public SlowPathCode { |
| 1754 public: | 1776 public: |
| 1755 BoxAllocationSlowPath(Instruction* instruction, | 1777 BoxAllocationSlowPath(Instruction* instruction, |
| 1756 const Class& cls, | 1778 const Class& cls, |
| 1757 Register result) | 1779 Register result) |
| 1758 : instruction_(instruction), | 1780 : instruction_(instruction), cls_(cls), result_(result) {} |
| 1759 cls_(cls), | |
| 1760 result_(result) { } | |
| 1761 | 1781 |
| 1762 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1782 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1763 if (Assembler::EmittingComments()) { | 1783 if (Assembler::EmittingComments()) { |
| 1764 __ Comment("%s slow path allocation of %s", | 1784 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), |
| 1765 instruction_->DebugName(), | |
| 1766 String::Handle(cls_.ScrubbedName()).ToCString()); | 1785 String::Handle(cls_.ScrubbedName()).ToCString()); |
| 1767 } | 1786 } |
| 1768 __ Bind(entry_label()); | 1787 __ Bind(entry_label()); |
| 1769 const Code& stub = Code::ZoneHandle(compiler->zone(), | 1788 const Code& stub = Code::ZoneHandle( |
| 1770 StubCode::GetAllocationStubForClass(cls_)); | 1789 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); |
| 1771 const StubEntry stub_entry(stub); | 1790 const StubEntry stub_entry(stub); |
| 1772 | 1791 |
| 1773 LocationSummary* locs = instruction_->locs(); | 1792 LocationSummary* locs = instruction_->locs(); |
| 1774 | 1793 |
| 1775 locs->live_registers()->Remove(Location::RegisterLocation(result_)); | 1794 locs->live_registers()->Remove(Location::RegisterLocation(result_)); |
| 1776 | 1795 |
| 1777 compiler->SaveLiveRegisters(locs); | 1796 compiler->SaveLiveRegisters(locs); |
| 1778 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. | 1797 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. |
| 1779 stub_entry, | 1798 stub_entry, RawPcDescriptors::kOther, locs); |
| 1780 RawPcDescriptors::kOther, | |
| 1781 locs); | |
| 1782 compiler->AddStubCallTarget(stub); | 1799 compiler->AddStubCallTarget(stub); |
| 1783 __ mov(result_, R0); | 1800 __ mov(result_, R0); |
| 1784 compiler->RestoreLiveRegisters(locs); | 1801 compiler->RestoreLiveRegisters(locs); |
| 1785 __ b(exit_label()); | 1802 __ b(exit_label()); |
| 1786 } | 1803 } |
| 1787 | 1804 |
| 1788 static void Allocate(FlowGraphCompiler* compiler, | 1805 static void Allocate(FlowGraphCompiler* compiler, |
| 1789 Instruction* instruction, | 1806 Instruction* instruction, |
| 1790 const Class& cls, | 1807 const Class& cls, |
| 1791 Register result, | 1808 Register result, |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1813 StoreInstanceFieldInstr* instruction, | 1830 StoreInstanceFieldInstr* instruction, |
| 1814 Register box_reg, | 1831 Register box_reg, |
| 1815 const Class& cls, | 1832 const Class& cls, |
| 1816 Register instance_reg, | 1833 Register instance_reg, |
| 1817 intptr_t offset, | 1834 intptr_t offset, |
| 1818 Register temp) { | 1835 Register temp) { |
| 1819 Label done; | 1836 Label done; |
| 1820 __ LoadFieldFromOffset(box_reg, instance_reg, offset); | 1837 __ LoadFieldFromOffset(box_reg, instance_reg, offset); |
| 1821 __ CompareObject(box_reg, Object::null_object()); | 1838 __ CompareObject(box_reg, Object::null_object()); |
| 1822 __ b(&done, NE); | 1839 __ b(&done, NE); |
| 1823 BoxAllocationSlowPath::Allocate( | 1840 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); |
| 1824 compiler, instruction, cls, box_reg, temp); | |
| 1825 __ mov(temp, box_reg); | 1841 __ mov(temp, box_reg); |
| 1826 __ StoreIntoObjectOffset(instance_reg, offset, temp); | 1842 __ StoreIntoObjectOffset(instance_reg, offset, temp); |
| 1827 __ Bind(&done); | 1843 __ Bind(&done); |
| 1828 } | 1844 } |
| 1829 | 1845 |
| 1830 | 1846 |
| 1831 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 1847 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |
| 1832 bool opt) const { | 1848 bool opt) const { |
| 1833 const intptr_t kNumInputs = 2; | 1849 const intptr_t kNumInputs = 2; |
| 1834 const intptr_t kNumTemps = | 1850 const intptr_t kNumTemps = |
| 1835 (IsUnboxedStore() && opt) ? 2 : | 1851 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 2 : 0); |
| 1836 ((IsPotentialUnboxedStore()) ? 2 : 0); | 1852 LocationSummary* summary = new (zone) |
| 1837 LocationSummary* summary = new(zone) LocationSummary( | 1853 LocationSummary(zone, kNumInputs, kNumTemps, |
| 1838 zone, kNumInputs, kNumTemps, | 1854 ((IsUnboxedStore() && opt && is_initialization()) || |
| 1839 ((IsUnboxedStore() && opt && is_initialization()) || | 1855 IsPotentialUnboxedStore()) |
| 1840 IsPotentialUnboxedStore()) | 1856 ? LocationSummary::kCallOnSlowPath |
| 1841 ? LocationSummary::kCallOnSlowPath | 1857 : LocationSummary::kNoCall); |
| 1842 : LocationSummary::kNoCall); | |
| 1843 | 1858 |
| 1844 summary->set_in(0, Location::RequiresRegister()); | 1859 summary->set_in(0, Location::RequiresRegister()); |
| 1845 if (IsUnboxedStore() && opt) { | 1860 if (IsUnboxedStore() && opt) { |
| 1846 summary->set_in(1, Location::RequiresFpuRegister()); | 1861 summary->set_in(1, Location::RequiresFpuRegister()); |
| 1847 summary->set_temp(0, Location::RequiresRegister()); | 1862 summary->set_temp(0, Location::RequiresRegister()); |
| 1848 summary->set_temp(1, Location::RequiresRegister()); | 1863 summary->set_temp(1, Location::RequiresRegister()); |
| 1849 } else if (IsPotentialUnboxedStore()) { | 1864 } else if (IsPotentialUnboxedStore()) { |
| 1850 summary->set_in(1, ShouldEmitStoreBarrier() | 1865 summary->set_in(1, ShouldEmitStoreBarrier() ? Location::WritableRegister() |
| 1851 ? Location::WritableRegister() | 1866 : Location::RequiresRegister()); |
| 1852 : Location::RequiresRegister()); | 1867 summary->set_temp(0, Location::RequiresRegister()); |
| 1853 summary->set_temp(0, Location::RequiresRegister()); | 1868 summary->set_temp(1, Location::RequiresRegister()); |
| 1854 summary->set_temp(1, Location::RequiresRegister()); | |
| 1855 } else { | 1869 } else { |
| 1856 summary->set_in(1, ShouldEmitStoreBarrier() | 1870 summary->set_in(1, ShouldEmitStoreBarrier() |
| 1857 ? Location::WritableRegister() | 1871 ? Location::WritableRegister() |
| 1858 : Location::RegisterOrConstant(value())); | 1872 : Location::RegisterOrConstant(value())); |
| 1859 } | 1873 } |
| 1860 return summary; | 1874 return summary; |
| 1861 } | 1875 } |
| 1862 | 1876 |
| 1863 | 1877 |
| 1864 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1878 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1865 ASSERT(sizeof(classid_t) == kInt32Size); | 1879 ASSERT(sizeof(classid_t) == kInt32Size); |
| 1866 Label skip_store; | 1880 Label skip_store; |
| 1867 | 1881 |
| 1868 const Register instance_reg = locs()->in(0).reg(); | 1882 const Register instance_reg = locs()->in(0).reg(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1931 Label store_float32x4; | 1945 Label store_float32x4; |
| 1932 Label store_float64x2; | 1946 Label store_float64x2; |
| 1933 | 1947 |
| 1934 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 1948 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
| 1935 | 1949 |
| 1936 __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(), | 1950 __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset(), |
| 1937 kUnsignedWord); | 1951 kUnsignedWord); |
| 1938 __ CompareImmediate(temp2, kNullCid); | 1952 __ CompareImmediate(temp2, kNullCid); |
| 1939 __ b(&store_pointer, EQ); | 1953 __ b(&store_pointer, EQ); |
| 1940 | 1954 |
| 1941 __ LoadFromOffset( | 1955 __ LoadFromOffset(temp2, temp, Field::kind_bits_offset() - kHeapObjectTag, |
| 1942 temp2, temp, Field::kind_bits_offset() - kHeapObjectTag, | 1956 kUnsignedByte); |
| 1943 kUnsignedByte); | |
| 1944 __ tsti(temp2, Immediate(1 << Field::kUnboxingCandidateBit)); | 1957 __ tsti(temp2, Immediate(1 << Field::kUnboxingCandidateBit)); |
| 1945 __ b(&store_pointer, EQ); | 1958 __ b(&store_pointer, EQ); |
| 1946 | 1959 |
| 1947 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), | 1960 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), |
| 1948 kUnsignedWord); | 1961 kUnsignedWord); |
| 1949 __ CompareImmediate(temp2, kDoubleCid); | 1962 __ CompareImmediate(temp2, kDoubleCid); |
| 1950 __ b(&store_double, EQ); | 1963 __ b(&store_double, EQ); |
| 1951 | 1964 |
| 1952 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), | 1965 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), |
| 1953 kUnsignedWord); | 1966 kUnsignedWord); |
| 1954 __ CompareImmediate(temp2, kFloat32x4Cid); | 1967 __ CompareImmediate(temp2, kFloat32x4Cid); |
| 1955 __ b(&store_float32x4, EQ); | 1968 __ b(&store_float32x4, EQ); |
| 1956 | 1969 |
| 1957 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), | 1970 __ LoadFieldFromOffset(temp2, temp, Field::guarded_cid_offset(), |
| 1958 kUnsignedWord); | 1971 kUnsignedWord); |
| 1959 __ CompareImmediate(temp2, kFloat64x2Cid); | 1972 __ CompareImmediate(temp2, kFloat64x2Cid); |
| 1960 __ b(&store_float64x2, EQ); | 1973 __ b(&store_float64x2, EQ); |
| 1961 | 1974 |
| 1962 // Fall through. | 1975 // Fall through. |
| 1963 __ b(&store_pointer); | 1976 __ b(&store_pointer); |
| 1964 | 1977 |
| 1965 if (!compiler->is_optimizing()) { | 1978 if (!compiler->is_optimizing()) { |
| 1966 locs()->live_registers()->Add(locs()->in(0)); | 1979 locs()->live_registers()->Add(locs()->in(0)); |
| 1967 locs()->live_registers()->Add(locs()->in(1)); | 1980 locs()->live_registers()->Add(locs()->in(1)); |
| 1968 } | 1981 } |
| 1969 | 1982 |
| 1970 { | 1983 { |
| 1971 __ Bind(&store_double); | 1984 __ Bind(&store_double); |
| 1972 EnsureMutableBox(compiler, | 1985 EnsureMutableBox(compiler, this, temp, compiler->double_class(), |
| 1973 this, | 1986 instance_reg, offset_in_bytes_, temp2); |
| 1974 temp, | |
| 1975 compiler->double_class(), | |
| 1976 instance_reg, | |
| 1977 offset_in_bytes_, | |
| 1978 temp2); | |
| 1979 __ LoadDFieldFromOffset(VTMP, value_reg, Double::value_offset()); | 1987 __ LoadDFieldFromOffset(VTMP, value_reg, Double::value_offset()); |
| 1980 __ StoreDFieldToOffset(VTMP, temp, Double::value_offset()); | 1988 __ StoreDFieldToOffset(VTMP, temp, Double::value_offset()); |
| 1981 __ b(&skip_store); | 1989 __ b(&skip_store); |
| 1982 } | 1990 } |
| 1983 | 1991 |
| 1984 { | 1992 { |
| 1985 __ Bind(&store_float32x4); | 1993 __ Bind(&store_float32x4); |
| 1986 EnsureMutableBox(compiler, | 1994 EnsureMutableBox(compiler, this, temp, compiler->float32x4_class(), |
| 1987 this, | 1995 instance_reg, offset_in_bytes_, temp2); |
| 1988 temp, | |
| 1989 compiler->float32x4_class(), | |
| 1990 instance_reg, | |
| 1991 offset_in_bytes_, | |
| 1992 temp2); | |
| 1993 __ LoadQFieldFromOffset(VTMP, value_reg, Float32x4::value_offset()); | 1996 __ LoadQFieldFromOffset(VTMP, value_reg, Float32x4::value_offset()); |
| 1994 __ StoreQFieldToOffset(VTMP, temp, Float32x4::value_offset()); | 1997 __ StoreQFieldToOffset(VTMP, temp, Float32x4::value_offset()); |
| 1995 __ b(&skip_store); | 1998 __ b(&skip_store); |
| 1996 } | 1999 } |
| 1997 | 2000 |
| 1998 { | 2001 { |
| 1999 __ Bind(&store_float64x2); | 2002 __ Bind(&store_float64x2); |
| 2000 EnsureMutableBox(compiler, | 2003 EnsureMutableBox(compiler, this, temp, compiler->float64x2_class(), |
| 2001 this, | 2004 instance_reg, offset_in_bytes_, temp2); |
| 2002 temp, | |
| 2003 compiler->float64x2_class(), | |
| 2004 instance_reg, | |
| 2005 offset_in_bytes_, | |
| 2006 temp2); | |
| 2007 __ LoadQFieldFromOffset(VTMP, value_reg, Float64x2::value_offset()); | 2005 __ LoadQFieldFromOffset(VTMP, value_reg, Float64x2::value_offset()); |
| 2008 __ StoreQFieldToOffset(VTMP, temp, Float64x2::value_offset()); | 2006 __ StoreQFieldToOffset(VTMP, temp, Float64x2::value_offset()); |
| 2009 __ b(&skip_store); | 2007 __ b(&skip_store); |
| 2010 } | 2008 } |
| 2011 | 2009 |
| 2012 __ Bind(&store_pointer); | 2010 __ Bind(&store_pointer); |
| 2013 } | 2011 } |
| 2014 | 2012 |
| 2015 if (ShouldEmitStoreBarrier()) { | 2013 if (ShouldEmitStoreBarrier()) { |
| 2016 const Register value_reg = locs()->in(1).reg(); | 2014 const Register value_reg = locs()->in(1).reg(); |
| 2017 __ StoreIntoObjectOffset( | 2015 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, value_reg, |
| 2018 instance_reg, offset_in_bytes_, value_reg, CanValueBeSmi()); | 2016 CanValueBeSmi()); |
| 2019 } else { | 2017 } else { |
| 2020 if (locs()->in(1).IsConstant()) { | 2018 if (locs()->in(1).IsConstant()) { |
| 2021 __ StoreIntoObjectOffsetNoBarrier( | 2019 __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes_, |
| 2022 instance_reg, offset_in_bytes_, locs()->in(1).constant()); | 2020 locs()->in(1).constant()); |
| 2023 } else { | 2021 } else { |
| 2024 const Register value_reg = locs()->in(1).reg(); | 2022 const Register value_reg = locs()->in(1).reg(); |
| 2025 __ StoreIntoObjectOffsetNoBarrier( | 2023 __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes_, |
| 2026 instance_reg, offset_in_bytes_, value_reg); | 2024 value_reg); |
| 2027 } | 2025 } |
| 2028 } | 2026 } |
| 2029 __ Bind(&skip_store); | 2027 __ Bind(&skip_store); |
| 2030 } | 2028 } |
| 2031 | 2029 |
| 2032 | 2030 |
| 2033 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2031 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2034 bool opt) const { | 2032 bool opt) const { |
| 2035 const intptr_t kNumInputs = 1; | 2033 const intptr_t kNumInputs = 1; |
| 2036 const intptr_t kNumTemps = 0; | 2034 const intptr_t kNumTemps = 0; |
| 2037 LocationSummary* summary = new(zone) LocationSummary( | 2035 LocationSummary* summary = new (zone) |
| 2038 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2036 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2039 summary->set_in(0, Location::RequiresRegister()); | 2037 summary->set_in(0, Location::RequiresRegister()); |
| 2040 summary->set_out(0, Location::RequiresRegister()); | 2038 summary->set_out(0, Location::RequiresRegister()); |
| 2041 return summary; | 2039 return summary; |
| 2042 } | 2040 } |
| 2043 | 2041 |
| 2044 | 2042 |
| 2045 // When the parser is building an implicit static getter for optimization, | 2043 // When the parser is building an implicit static getter for optimization, |
| 2046 // it can generate a function body where deoptimization ids do not line up | 2044 // it can generate a function body where deoptimization ids do not line up |
| 2047 // with the unoptimized code. | 2045 // with the unoptimized code. |
| 2048 // | 2046 // |
| 2049 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 2047 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
| 2050 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2048 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2051 const Register field = locs()->in(0).reg(); | 2049 const Register field = locs()->in(0).reg(); |
| 2052 const Register result = locs()->out(0).reg(); | 2050 const Register result = locs()->out(0).reg(); |
| 2053 __ LoadFieldFromOffset(result, field, Field::static_value_offset()); | 2051 __ LoadFieldFromOffset(result, field, Field::static_value_offset()); |
| 2054 } | 2052 } |
| 2055 | 2053 |
| 2056 | 2054 |
| 2057 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2055 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2058 bool opt) const { | 2056 bool opt) const { |
| 2059 LocationSummary* locs = new(zone) LocationSummary( | 2057 LocationSummary* locs = |
| 2060 zone, 1, 1, LocationSummary::kNoCall); | 2058 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); |
| 2061 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 2059 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 2062 : Location::RequiresRegister()); | 2060 : Location::RequiresRegister()); |
| 2063 locs->set_temp(0, Location::RequiresRegister()); | 2061 locs->set_temp(0, Location::RequiresRegister()); |
| 2064 return locs; | 2062 return locs; |
| 2065 } | 2063 } |
| 2066 | 2064 |
| 2067 | 2065 |
| 2068 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2066 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2069 const Register value = locs()->in(0).reg(); | 2067 const Register value = locs()->in(0).reg(); |
| 2070 const Register temp = locs()->temp(0).reg(); | 2068 const Register temp = locs()->temp(0).reg(); |
| 2071 | 2069 |
| 2072 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 2070 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
| 2073 if (this->value()->NeedsStoreBuffer()) { | 2071 if (this->value()->NeedsStoreBuffer()) { |
| 2074 __ StoreIntoObjectOffset( | 2072 __ StoreIntoObjectOffset(temp, Field::static_value_offset(), value, |
| 2075 temp, Field::static_value_offset(), value, CanValueBeSmi()); | 2073 CanValueBeSmi()); |
| 2076 } else { | 2074 } else { |
| 2077 __ StoreIntoObjectOffsetNoBarrier(temp, | 2075 __ StoreIntoObjectOffsetNoBarrier(temp, Field::static_value_offset(), |
| 2078 Field::static_value_offset(), | |
| 2079 value); | 2076 value); |
| 2080 } | 2077 } |
| 2081 } | 2078 } |
| 2082 | 2079 |
| 2083 | 2080 |
| 2084 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 2081 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
| 2085 bool opt) const { | 2082 bool opt) const { |
| 2086 const intptr_t kNumInputs = 2; | 2083 const intptr_t kNumInputs = 2; |
| 2087 const intptr_t kNumTemps = 0; | 2084 const intptr_t kNumTemps = 0; |
| 2088 LocationSummary* summary = new(zone) LocationSummary( | 2085 LocationSummary* summary = new (zone) |
| 2089 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2086 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2090 summary->set_in(0, Location::RegisterLocation(R0)); | 2087 summary->set_in(0, Location::RegisterLocation(R0)); |
| 2091 summary->set_in(1, Location::RegisterLocation(R1)); | 2088 summary->set_in(1, Location::RegisterLocation(R1)); |
| 2092 summary->set_out(0, Location::RegisterLocation(R0)); | 2089 summary->set_out(0, Location::RegisterLocation(R0)); |
| 2093 return summary; | 2090 return summary; |
| 2094 } | 2091 } |
| 2095 | 2092 |
| 2096 | 2093 |
| 2097 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2094 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2098 ASSERT(locs()->in(0).reg() == R0); // Value. | 2095 ASSERT(locs()->in(0).reg() == R0); // Value. |
| 2099 ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments. | 2096 ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments. |
| 2100 | 2097 |
| 2101 compiler->GenerateInstanceOf(token_pos(), | 2098 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), negate_result(), |
| 2102 deopt_id(), | |
| 2103 type(), | |
| 2104 negate_result(), | |
| 2105 locs()); | 2099 locs()); |
| 2106 ASSERT(locs()->out(0).reg() == R0); | 2100 ASSERT(locs()->out(0).reg() == R0); |
| 2107 } | 2101 } |
| 2108 | 2102 |
| 2109 | 2103 |
| 2110 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 2104 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
| 2111 bool opt) const { | 2105 bool opt) const { |
| 2112 const intptr_t kNumInputs = 2; | 2106 const intptr_t kNumInputs = 2; |
| 2113 const intptr_t kNumTemps = 0; | 2107 const intptr_t kNumTemps = 0; |
| 2114 LocationSummary* locs = new(zone) LocationSummary( | 2108 LocationSummary* locs = new (zone) |
| 2115 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2109 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2116 locs->set_in(kElementTypePos, Location::RegisterLocation(R1)); | 2110 locs->set_in(kElementTypePos, Location::RegisterLocation(R1)); |
| 2117 locs->set_in(kLengthPos, Location::RegisterLocation(R2)); | 2111 locs->set_in(kLengthPos, Location::RegisterLocation(R2)); |
| 2118 locs->set_out(0, Location::RegisterLocation(R0)); | 2112 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2119 return locs; | 2113 return locs; |
| 2120 } | 2114 } |
| 2121 | 2115 |
| 2122 | 2116 |
| 2123 // Inlines array allocation for known constant values. | 2117 // Inlines array allocation for known constant values. |
| 2124 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 2118 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
| 2125 intptr_t num_elements, | 2119 intptr_t num_elements, |
| 2126 Label* slow_path, | 2120 Label* slow_path, |
| 2127 Label* done) { | 2121 Label* done) { |
| 2128 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. | 2122 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. |
| 2129 const Register kLengthReg = R2; | 2123 const Register kLengthReg = R2; |
| 2130 const Register kElemTypeReg = R1; | 2124 const Register kElemTypeReg = R1; |
| 2131 const intptr_t instance_size = Array::InstanceSize(num_elements); | 2125 const intptr_t instance_size = Array::InstanceSize(num_elements); |
| 2132 | 2126 |
| 2133 __ TryAllocateArray(kArrayCid, instance_size, slow_path, | 2127 __ TryAllocateArray(kArrayCid, instance_size, slow_path, |
| 2134 R0, // instance | 2128 R0, // instance |
| 2135 R3, // end address | 2129 R3, // end address |
| 2136 R6, | 2130 R6, R8); |
| 2137 R8); | |
| 2138 // R0: new object start as a tagged pointer. | 2131 // R0: new object start as a tagged pointer. |
| 2139 // R3: new object end address. | 2132 // R3: new object end address. |
| 2140 | 2133 |
| 2141 // Store the type argument field. | 2134 // Store the type argument field. |
| 2142 __ StoreIntoObjectNoBarrier(R0, | 2135 __ StoreIntoObjectNoBarrier( |
| 2143 FieldAddress(R0, Array::type_arguments_offset()), | 2136 R0, FieldAddress(R0, Array::type_arguments_offset()), kElemTypeReg); |
| 2144 kElemTypeReg); | |
| 2145 | 2137 |
| 2146 // Set the length field. | 2138 // Set the length field. |
| 2147 __ StoreIntoObjectNoBarrier(R0, | 2139 __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, Array::length_offset()), |
| 2148 FieldAddress(R0, Array::length_offset()), | |
| 2149 kLengthReg); | 2140 kLengthReg); |
| 2150 | 2141 |
| 2151 // TODO(zra): Use stp once added. | 2142 // TODO(zra): Use stp once added. |
| 2152 // Initialize all array elements to raw_null. | 2143 // Initialize all array elements to raw_null. |
| 2153 // R0: new object start as a tagged pointer. | 2144 // R0: new object start as a tagged pointer. |
| 2154 // R3: new object end address. | 2145 // R3: new object end address. |
| 2155 // R8: iterator which initially points to the start of the variable | 2146 // R8: iterator which initially points to the start of the variable |
| 2156 // data area to be initialized. | 2147 // data area to be initialized. |
| 2157 // R6: null | 2148 // R6: null |
| 2158 if (num_elements > 0) { | 2149 if (num_elements > 0) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2181 | 2172 |
| 2182 | 2173 |
| 2183 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2174 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2184 const Register kLengthReg = R2; | 2175 const Register kLengthReg = R2; |
| 2185 const Register kElemTypeReg = R1; | 2176 const Register kElemTypeReg = R1; |
| 2186 const Register kResultReg = R0; | 2177 const Register kResultReg = R0; |
| 2187 | 2178 |
| 2188 ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg); | 2179 ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg); |
| 2189 ASSERT(locs()->in(kLengthPos).reg() == kLengthReg); | 2180 ASSERT(locs()->in(kLengthPos).reg() == kLengthReg); |
| 2190 | 2181 |
| 2191 if (compiler->is_optimizing() && | 2182 if (compiler->is_optimizing() && !FLAG_precompiled_mode && |
| 2192 !FLAG_precompiled_mode && | |
| 2193 num_elements()->BindsToConstant() && | 2183 num_elements()->BindsToConstant() && |
| 2194 num_elements()->BoundConstant().IsSmi()) { | 2184 num_elements()->BoundConstant().IsSmi()) { |
| 2195 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); | 2185 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); |
| 2196 if ((length >= 0) && (length <= Array::kMaxElements)) { | 2186 if ((length >= 0) && (length <= Array::kMaxElements)) { |
| 2197 Label slow_path, done; | 2187 Label slow_path, done; |
| 2198 InlineArrayAllocation(compiler, length, &slow_path, &done); | 2188 InlineArrayAllocation(compiler, length, &slow_path, &done); |
| 2199 __ Bind(&slow_path); | 2189 __ Bind(&slow_path); |
| 2200 __ PushObject(Object::null_object()); // Make room for the result. | 2190 __ PushObject(Object::null_object()); // Make room for the result. |
| 2201 __ Push(kLengthReg); // length. | 2191 __ Push(kLengthReg); // length. |
| 2202 __ Push(kElemTypeReg); | 2192 __ Push(kElemTypeReg); |
| 2203 compiler->GenerateRuntimeCall(token_pos(), | 2193 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2204 deopt_id(), | 2194 kAllocateArrayRuntimeEntry, 2, locs()); |
| 2205 kAllocateArrayRuntimeEntry, | |
| 2206 2, | |
| 2207 locs()); | |
| 2208 __ Drop(2); | 2195 __ Drop(2); |
| 2209 __ Pop(kResultReg); | 2196 __ Pop(kResultReg); |
| 2210 __ Bind(&done); | 2197 __ Bind(&done); |
| 2211 return; | 2198 return; |
| 2212 } | 2199 } |
| 2213 } | 2200 } |
| 2214 const Code& stub = Code::ZoneHandle(compiler->zone(), | 2201 const Code& stub = Code::ZoneHandle(compiler->zone(), |
| 2215 StubCode::AllocateArray_entry()->code()); | 2202 StubCode::AllocateArray_entry()->code()); |
| 2216 compiler->AddStubCallTarget(stub); | 2203 compiler->AddStubCallTarget(stub); |
| 2217 compiler->GenerateCall(token_pos(), | 2204 compiler->GenerateCall(token_pos(), *StubCode::AllocateArray_entry(), |
| 2218 *StubCode::AllocateArray_entry(), | 2205 RawPcDescriptors::kOther, locs()); |
| 2219 RawPcDescriptors::kOther, | |
| 2220 locs()); | |
| 2221 ASSERT(locs()->out(0).reg() == kResultReg); | 2206 ASSERT(locs()->out(0).reg() == kResultReg); |
| 2222 } | 2207 } |
| 2223 | 2208 |
| 2224 | 2209 |
| 2225 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 2210 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |
| 2226 bool opt) const { | 2211 bool opt) const { |
| 2227 const intptr_t kNumInputs = 1; | 2212 const intptr_t kNumInputs = 1; |
| 2228 const intptr_t kNumTemps = | 2213 const intptr_t kNumTemps = |
| 2229 (IsUnboxedLoad() && opt) ? 1 : | 2214 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 1 : 0); |
| 2230 ((IsPotentialUnboxedLoad()) ? 1 : 0); | 2215 LocationSummary* locs = new (zone) LocationSummary( |
| 2231 LocationSummary* locs = new(zone) LocationSummary( | 2216 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) |
| 2232 zone, kNumInputs, kNumTemps, | 2217 ? LocationSummary::kNoCall |
| 2233 (opt && !IsPotentialUnboxedLoad()) | 2218 : LocationSummary::kCallOnSlowPath); |
| 2234 ? LocationSummary::kNoCall | |
| 2235 : LocationSummary::kCallOnSlowPath); | |
| 2236 | 2219 |
| 2237 locs->set_in(0, Location::RequiresRegister()); | 2220 locs->set_in(0, Location::RequiresRegister()); |
| 2238 | 2221 |
| 2239 if (IsUnboxedLoad() && opt) { | 2222 if (IsUnboxedLoad() && opt) { |
| 2240 locs->set_temp(0, Location::RequiresRegister()); | 2223 locs->set_temp(0, Location::RequiresRegister()); |
| 2241 } else if (IsPotentialUnboxedLoad()) { | 2224 } else if (IsPotentialUnboxedLoad()) { |
| 2242 locs->set_temp(0, Location::RequiresRegister()); | 2225 locs->set_temp(0, Location::RequiresRegister()); |
| 2243 } | 2226 } |
| 2244 locs->set_out(0, Location::RequiresRegister()); | 2227 locs->set_out(0, Location::RequiresRegister()); |
| 2245 return locs; | 2228 return locs; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2276 if (IsPotentialUnboxedLoad()) { | 2259 if (IsPotentialUnboxedLoad()) { |
| 2277 const Register temp = locs()->temp(0).reg(); | 2260 const Register temp = locs()->temp(0).reg(); |
| 2278 | 2261 |
| 2279 Label load_pointer; | 2262 Label load_pointer; |
| 2280 Label load_double; | 2263 Label load_double; |
| 2281 Label load_float32x4; | 2264 Label load_float32x4; |
| 2282 Label load_float64x2; | 2265 Label load_float64x2; |
| 2283 | 2266 |
| 2284 __ LoadObject(result_reg, Field::ZoneHandle(field()->Original())); | 2267 __ LoadObject(result_reg, Field::ZoneHandle(field()->Original())); |
| 2285 | 2268 |
| 2286 FieldAddress field_cid_operand( | 2269 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset(), |
| 2287 result_reg, Field::guarded_cid_offset(), kUnsignedWord); | 2270 kUnsignedWord); |
| 2288 FieldAddress field_nullability_operand( | 2271 FieldAddress field_nullability_operand( |
| 2289 result_reg, Field::is_nullable_offset(), kUnsignedWord); | 2272 result_reg, Field::is_nullable_offset(), kUnsignedWord); |
| 2290 | 2273 |
| 2291 __ ldr(temp, field_nullability_operand, kUnsignedWord); | 2274 __ ldr(temp, field_nullability_operand, kUnsignedWord); |
| 2292 __ CompareImmediate(temp, kNullCid); | 2275 __ CompareImmediate(temp, kNullCid); |
| 2293 __ b(&load_pointer, EQ); | 2276 __ b(&load_pointer, EQ); |
| 2294 | 2277 |
| 2295 __ ldr(temp, field_cid_operand, kUnsignedWord); | 2278 __ ldr(temp, field_cid_operand, kUnsignedWord); |
| 2296 __ CompareImmediate(temp, kDoubleCid); | 2279 __ CompareImmediate(temp, kDoubleCid); |
| 2297 __ b(&load_double, EQ); | 2280 __ b(&load_double, EQ); |
| 2298 | 2281 |
| 2299 __ ldr(temp, field_cid_operand, kUnsignedWord); | 2282 __ ldr(temp, field_cid_operand, kUnsignedWord); |
| 2300 __ CompareImmediate(temp, kFloat32x4Cid); | 2283 __ CompareImmediate(temp, kFloat32x4Cid); |
| 2301 __ b(&load_float32x4, EQ); | 2284 __ b(&load_float32x4, EQ); |
| 2302 | 2285 |
| 2303 __ ldr(temp, field_cid_operand, kUnsignedWord); | 2286 __ ldr(temp, field_cid_operand, kUnsignedWord); |
| 2304 __ CompareImmediate(temp, kFloat64x2Cid); | 2287 __ CompareImmediate(temp, kFloat64x2Cid); |
| 2305 __ b(&load_float64x2, EQ); | 2288 __ b(&load_float64x2, EQ); |
| 2306 | 2289 |
| 2307 // Fall through. | 2290 // Fall through. |
| 2308 __ b(&load_pointer); | 2291 __ b(&load_pointer); |
| 2309 | 2292 |
| 2310 if (!compiler->is_optimizing()) { | 2293 if (!compiler->is_optimizing()) { |
| 2311 locs()->live_registers()->Add(locs()->in(0)); | 2294 locs()->live_registers()->Add(locs()->in(0)); |
| 2312 } | 2295 } |
| 2313 | 2296 |
| 2314 { | 2297 { |
| 2315 __ Bind(&load_double); | 2298 __ Bind(&load_double); |
| 2316 BoxAllocationSlowPath::Allocate(compiler, | 2299 BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(), |
| 2317 this, | 2300 result_reg, temp); |
| 2318 compiler->double_class(), | |
| 2319 result_reg, | |
| 2320 temp); | |
| 2321 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); | 2301 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); |
| 2322 __ LoadDFieldFromOffset(VTMP, temp, Double::value_offset()); | 2302 __ LoadDFieldFromOffset(VTMP, temp, Double::value_offset()); |
| 2323 __ StoreDFieldToOffset(VTMP, result_reg, Double::value_offset()); | 2303 __ StoreDFieldToOffset(VTMP, result_reg, Double::value_offset()); |
| 2324 __ b(&done); | 2304 __ b(&done); |
| 2325 } | 2305 } |
| 2326 | 2306 |
| 2327 { | 2307 { |
| 2328 __ Bind(&load_float32x4); | 2308 __ Bind(&load_float32x4); |
| 2329 BoxAllocationSlowPath::Allocate(compiler, | 2309 BoxAllocationSlowPath::Allocate( |
| 2330 this, | 2310 compiler, this, compiler->float32x4_class(), result_reg, temp); |
| 2331 compiler->float32x4_class(), | |
| 2332 result_reg, | |
| 2333 temp); | |
| 2334 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); | 2311 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); |
| 2335 __ LoadQFieldFromOffset(VTMP, temp, Float32x4::value_offset()); | 2312 __ LoadQFieldFromOffset(VTMP, temp, Float32x4::value_offset()); |
| 2336 __ StoreQFieldToOffset(VTMP, result_reg, Float32x4::value_offset()); | 2313 __ StoreQFieldToOffset(VTMP, result_reg, Float32x4::value_offset()); |
| 2337 __ b(&done); | 2314 __ b(&done); |
| 2338 } | 2315 } |
| 2339 | 2316 |
| 2340 { | 2317 { |
| 2341 __ Bind(&load_float64x2); | 2318 __ Bind(&load_float64x2); |
| 2342 BoxAllocationSlowPath::Allocate(compiler, | 2319 BoxAllocationSlowPath::Allocate( |
| 2343 this, | 2320 compiler, this, compiler->float64x2_class(), result_reg, temp); |
| 2344 compiler->float64x2_class(), | |
| 2345 result_reg, | |
| 2346 temp); | |
| 2347 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); | 2321 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); |
| 2348 __ LoadQFieldFromOffset(VTMP, temp, Float64x2::value_offset()); | 2322 __ LoadQFieldFromOffset(VTMP, temp, Float64x2::value_offset()); |
| 2349 __ StoreQFieldToOffset(VTMP, result_reg, Float64x2::value_offset()); | 2323 __ StoreQFieldToOffset(VTMP, result_reg, Float64x2::value_offset()); |
| 2350 __ b(&done); | 2324 __ b(&done); |
| 2351 } | 2325 } |
| 2352 | 2326 |
| 2353 __ Bind(&load_pointer); | 2327 __ Bind(&load_pointer); |
| 2354 } | 2328 } |
| 2355 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); | 2329 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); |
| 2356 __ Bind(&done); | 2330 __ Bind(&done); |
| 2357 } | 2331 } |
| 2358 | 2332 |
| 2359 | 2333 |
| 2360 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2334 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
| 2361 bool opt) const { | 2335 bool opt) const { |
| 2362 const intptr_t kNumInputs = 1; | 2336 const intptr_t kNumInputs = 1; |
| 2363 const intptr_t kNumTemps = 0; | 2337 const intptr_t kNumTemps = 0; |
| 2364 LocationSummary* locs = new(zone) LocationSummary( | 2338 LocationSummary* locs = new (zone) |
| 2365 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2339 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2366 locs->set_in(0, Location::RegisterLocation(R0)); | 2340 locs->set_in(0, Location::RegisterLocation(R0)); |
| 2367 locs->set_out(0, Location::RegisterLocation(R0)); | 2341 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2368 return locs; | 2342 return locs; |
| 2369 } | 2343 } |
| 2370 | 2344 |
| 2371 | 2345 |
| 2372 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2346 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2373 const Register instantiator_reg = locs()->in(0).reg(); | 2347 const Register instantiator_reg = locs()->in(0).reg(); |
| 2374 const Register result_reg = locs()->out(0).reg(); | 2348 const Register result_reg = locs()->out(0).reg(); |
| 2375 | 2349 |
| 2376 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2350 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
| 2377 // A runtime call to instantiate the type is required. | 2351 // A runtime call to instantiate the type is required. |
| 2378 __ PushObject(Object::null_object()); // Make room for the result. | 2352 __ PushObject(Object::null_object()); // Make room for the result. |
| 2379 __ PushObject(type()); | 2353 __ PushObject(type()); |
| 2380 __ Push(instantiator_reg); // Push instantiator type arguments. | 2354 __ Push(instantiator_reg); // Push instantiator type arguments. |
| 2381 compiler->GenerateRuntimeCall(token_pos(), | 2355 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2382 deopt_id(), | 2356 kInstantiateTypeRuntimeEntry, 2, locs()); |
| 2383 kInstantiateTypeRuntimeEntry, | 2357 __ Drop(2); // Drop instantiator and uninstantiated type. |
| 2384 2, | |
| 2385 locs()); | |
| 2386 __ Drop(2); // Drop instantiator and uninstantiated type. | |
| 2387 __ Pop(result_reg); // Pop instantiated type. | 2358 __ Pop(result_reg); // Pop instantiated type. |
| 2388 ASSERT(instantiator_reg == result_reg); | 2359 ASSERT(instantiator_reg == result_reg); |
| 2389 } | 2360 } |
| 2390 | 2361 |
| 2391 | 2362 |
| 2392 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2363 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
| 2393 Zone* zone, bool opt) const { | 2364 Zone* zone, |
| 2365 bool opt) const { |
| 2394 const intptr_t kNumInputs = 1; | 2366 const intptr_t kNumInputs = 1; |
| 2395 const intptr_t kNumTemps = 0; | 2367 const intptr_t kNumTemps = 0; |
| 2396 LocationSummary* locs = new(zone) LocationSummary( | 2368 LocationSummary* locs = new (zone) |
| 2397 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2369 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2398 locs->set_in(0, Location::RegisterLocation(R0)); | 2370 locs->set_in(0, Location::RegisterLocation(R0)); |
| 2399 locs->set_out(0, Location::RegisterLocation(R0)); | 2371 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2400 return locs; | 2372 return locs; |
| 2401 } | 2373 } |
| 2402 | 2374 |
| 2403 | 2375 |
| 2404 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2376 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
| 2405 FlowGraphCompiler* compiler) { | 2377 FlowGraphCompiler* compiler) { |
| 2406 const Register instantiator_reg = locs()->in(0).reg(); | 2378 const Register instantiator_reg = locs()->in(0).reg(); |
| 2407 const Register result_reg = locs()->out(0).reg(); | 2379 const Register result_reg = locs()->out(0).reg(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2439 __ Bind(&found); | 2411 __ Bind(&found); |
| 2440 __ LoadFromOffset(R0, R2, 1 * kWordSize); // Cached instantiated args. | 2412 __ LoadFromOffset(R0, R2, 1 * kWordSize); // Cached instantiated args. |
| 2441 __ b(&type_arguments_instantiated); | 2413 __ b(&type_arguments_instantiated); |
| 2442 | 2414 |
| 2443 __ Bind(&slow_case); | 2415 __ Bind(&slow_case); |
| 2444 // Instantiate non-null type arguments. | 2416 // Instantiate non-null type arguments. |
| 2445 // A runtime call to instantiate the type arguments is required. | 2417 // A runtime call to instantiate the type arguments is required. |
| 2446 __ PushObject(Object::null_object()); // Make room for the result. | 2418 __ PushObject(Object::null_object()); // Make room for the result. |
| 2447 __ PushObject(type_arguments()); | 2419 __ PushObject(type_arguments()); |
| 2448 __ Push(instantiator_reg); // Push instantiator type arguments. | 2420 __ Push(instantiator_reg); // Push instantiator type arguments. |
| 2449 compiler->GenerateRuntimeCall(token_pos(), | 2421 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2450 deopt_id(), | 2422 kInstantiateTypeArgumentsRuntimeEntry, 2, |
| 2451 kInstantiateTypeArgumentsRuntimeEntry, | |
| 2452 2, | |
| 2453 locs()); | 2423 locs()); |
| 2454 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 2424 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 2455 __ Pop(result_reg); // Pop instantiated type arguments. | 2425 __ Pop(result_reg); // Pop instantiated type arguments. |
| 2456 __ Bind(&type_arguments_instantiated); | 2426 __ Bind(&type_arguments_instantiated); |
| 2457 } | 2427 } |
| 2458 | 2428 |
| 2459 | 2429 |
| 2460 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2430 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
| 2461 Zone* zone, | 2431 Zone* zone, |
| 2462 bool opt) const { | 2432 bool opt) const { |
| 2463 ASSERT(opt); | 2433 ASSERT(opt); |
| 2464 const intptr_t kNumInputs = 0; | 2434 const intptr_t kNumInputs = 0; |
| 2465 const intptr_t kNumTemps = 3; | 2435 const intptr_t kNumTemps = 3; |
| 2466 LocationSummary* locs = new(zone) LocationSummary( | 2436 LocationSummary* locs = new (zone) LocationSummary( |
| 2467 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2437 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2468 locs->set_temp(0, Location::RegisterLocation(R1)); | 2438 locs->set_temp(0, Location::RegisterLocation(R1)); |
| 2469 locs->set_temp(1, Location::RegisterLocation(R2)); | 2439 locs->set_temp(1, Location::RegisterLocation(R2)); |
| 2470 locs->set_temp(2, Location::RegisterLocation(R3)); | 2440 locs->set_temp(2, Location::RegisterLocation(R3)); |
| 2471 locs->set_out(0, Location::RegisterLocation(R0)); | 2441 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2472 return locs; | 2442 return locs; |
| 2473 } | 2443 } |
| 2474 | 2444 |
| 2475 | 2445 |
| 2476 class AllocateContextSlowPath : public SlowPathCode { | 2446 class AllocateContextSlowPath : public SlowPathCode { |
| 2477 public: | 2447 public: |
| 2478 explicit AllocateContextSlowPath( | 2448 explicit AllocateContextSlowPath( |
| 2479 AllocateUninitializedContextInstr* instruction) | 2449 AllocateUninitializedContextInstr* instruction) |
| 2480 : instruction_(instruction) { } | 2450 : instruction_(instruction) {} |
| 2481 | 2451 |
| 2482 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2452 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2483 __ Comment("AllocateContextSlowPath"); | 2453 __ Comment("AllocateContextSlowPath"); |
| 2484 __ Bind(entry_label()); | 2454 __ Bind(entry_label()); |
| 2485 | 2455 |
| 2486 LocationSummary* locs = instruction_->locs(); | 2456 LocationSummary* locs = instruction_->locs(); |
| 2487 locs->live_registers()->Remove(locs->out(0)); | 2457 locs->live_registers()->Remove(locs->out(0)); |
| 2488 | 2458 |
| 2489 compiler->SaveLiveRegisters(locs); | 2459 compiler->SaveLiveRegisters(locs); |
| 2490 | 2460 |
| 2491 __ LoadImmediate(R1, instruction_->num_context_variables()); | 2461 __ LoadImmediate(R1, instruction_->num_context_variables()); |
| 2492 const Code& stub = Code::ZoneHandle( | 2462 const Code& stub = Code::ZoneHandle( |
| 2493 compiler->zone(), StubCode::AllocateContext_entry()->code()); | 2463 compiler->zone(), StubCode::AllocateContext_entry()->code()); |
| 2494 compiler->AddStubCallTarget(stub); | 2464 compiler->AddStubCallTarget(stub); |
| 2495 compiler->GenerateCall(instruction_->token_pos(), | 2465 compiler->GenerateCall(instruction_->token_pos(), |
| 2496 *StubCode::AllocateContext_entry(), | 2466 *StubCode::AllocateContext_entry(), |
| 2497 RawPcDescriptors::kOther, | 2467 RawPcDescriptors::kOther, locs); |
| 2498 locs); | |
| 2499 ASSERT(instruction_->locs()->out(0).reg() == R0); | 2468 ASSERT(instruction_->locs()->out(0).reg() == R0); |
| 2500 compiler->RestoreLiveRegisters(instruction_->locs()); | 2469 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2501 __ b(exit_label()); | 2470 __ b(exit_label()); |
| 2502 } | 2471 } |
| 2503 | 2472 |
| 2504 private: | 2473 private: |
| 2505 AllocateUninitializedContextInstr* instruction_; | 2474 AllocateUninitializedContextInstr* instruction_; |
| 2506 }; | 2475 }; |
| 2507 | 2476 |
| 2508 | 2477 |
| 2509 | |
| 2510 void AllocateUninitializedContextInstr::EmitNativeCode( | 2478 void AllocateUninitializedContextInstr::EmitNativeCode( |
| 2511 FlowGraphCompiler* compiler) { | 2479 FlowGraphCompiler* compiler) { |
| 2512 Register temp0 = locs()->temp(0).reg(); | 2480 Register temp0 = locs()->temp(0).reg(); |
| 2513 Register temp1 = locs()->temp(1).reg(); | 2481 Register temp1 = locs()->temp(1).reg(); |
| 2514 Register temp2 = locs()->temp(2).reg(); | 2482 Register temp2 = locs()->temp(2).reg(); |
| 2515 Register result = locs()->out(0).reg(); | 2483 Register result = locs()->out(0).reg(); |
| 2516 // Try allocate the object. | 2484 // Try allocate the object. |
| 2517 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2485 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
| 2518 compiler->AddSlowPathCode(slow_path); | 2486 compiler->AddSlowPathCode(slow_path); |
| 2519 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2487 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
| 2520 | 2488 |
| 2521 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 2489 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
| 2522 result, // instance | 2490 result, // instance |
| 2523 temp0, | 2491 temp0, temp1, temp2); |
| 2524 temp1, | |
| 2525 temp2); | |
| 2526 | 2492 |
| 2527 // Setup up number of context variables field. | 2493 // Setup up number of context variables field. |
| 2528 __ LoadImmediate(temp0, num_context_variables()); | 2494 __ LoadImmediate(temp0, num_context_variables()); |
| 2529 __ str(temp0, FieldAddress(result, Context::num_variables_offset())); | 2495 __ str(temp0, FieldAddress(result, Context::num_variables_offset())); |
| 2530 | 2496 |
| 2531 __ Bind(slow_path->exit_label()); | 2497 __ Bind(slow_path->exit_label()); |
| 2532 } | 2498 } |
| 2533 | 2499 |
| 2534 | 2500 |
| 2535 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 2501 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |
| 2536 bool opt) const { | 2502 bool opt) const { |
| 2537 const intptr_t kNumInputs = 0; | 2503 const intptr_t kNumInputs = 0; |
| 2538 const intptr_t kNumTemps = 1; | 2504 const intptr_t kNumTemps = 1; |
| 2539 LocationSummary* locs = new(zone) LocationSummary( | 2505 LocationSummary* locs = new (zone) |
| 2540 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2506 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2541 locs->set_temp(0, Location::RegisterLocation(R1)); | 2507 locs->set_temp(0, Location::RegisterLocation(R1)); |
| 2542 locs->set_out(0, Location::RegisterLocation(R0)); | 2508 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2543 return locs; | 2509 return locs; |
| 2544 } | 2510 } |
| 2545 | 2511 |
| 2546 | 2512 |
| 2547 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2513 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2548 ASSERT(locs()->temp(0).reg() == R1); | 2514 ASSERT(locs()->temp(0).reg() == R1); |
| 2549 ASSERT(locs()->out(0).reg() == R0); | 2515 ASSERT(locs()->out(0).reg() == R0); |
| 2550 | 2516 |
| 2551 __ LoadImmediate(R1, num_context_variables()); | 2517 __ LoadImmediate(R1, num_context_variables()); |
| 2552 compiler->GenerateCall(token_pos(), | 2518 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), |
| 2553 *StubCode::AllocateContext_entry(), | 2519 RawPcDescriptors::kOther, locs()); |
| 2554 RawPcDescriptors::kOther, | |
| 2555 locs()); | |
| 2556 } | 2520 } |
| 2557 | 2521 |
| 2558 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2522 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2559 bool opt) const { | 2523 bool opt) const { |
| 2560 const intptr_t kNumInputs = 1; | 2524 const intptr_t kNumInputs = 1; |
| 2561 const intptr_t kNumTemps = 1; | 2525 const intptr_t kNumTemps = 1; |
| 2562 LocationSummary* locs = new(zone) LocationSummary( | 2526 LocationSummary* locs = new (zone) |
| 2563 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2527 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2564 locs->set_in(0, Location::RegisterLocation(R0)); | 2528 locs->set_in(0, Location::RegisterLocation(R0)); |
| 2565 locs->set_temp(0, Location::RegisterLocation(R1)); | 2529 locs->set_temp(0, Location::RegisterLocation(R1)); |
| 2566 return locs; | 2530 return locs; |
| 2567 } | 2531 } |
| 2568 | 2532 |
| 2569 | 2533 |
| 2570 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2534 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2571 Register field = locs()->in(0).reg(); | 2535 Register field = locs()->in(0).reg(); |
| 2572 Register temp = locs()->temp(0).reg(); | 2536 Register temp = locs()->temp(0).reg(); |
| 2573 Label call_runtime, no_call; | 2537 Label call_runtime, no_call; |
| 2574 | 2538 |
| 2575 __ ldr(temp, FieldAddress(field, Field::static_value_offset())); | 2539 __ ldr(temp, FieldAddress(field, Field::static_value_offset())); |
| 2576 __ CompareObject(temp, Object::sentinel()); | 2540 __ CompareObject(temp, Object::sentinel()); |
| 2577 __ b(&call_runtime, EQ); | 2541 __ b(&call_runtime, EQ); |
| 2578 | 2542 |
| 2579 __ CompareObject(temp, Object::transition_sentinel()); | 2543 __ CompareObject(temp, Object::transition_sentinel()); |
| 2580 __ b(&no_call, NE); | 2544 __ b(&no_call, NE); |
| 2581 | 2545 |
| 2582 __ Bind(&call_runtime); | 2546 __ Bind(&call_runtime); |
| 2583 __ PushObject(Object::null_object()); // Make room for (unused) result. | 2547 __ PushObject(Object::null_object()); // Make room for (unused) result. |
| 2584 __ Push(field); | 2548 __ Push(field); |
| 2585 compiler->GenerateRuntimeCall(token_pos(), | 2549 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2586 deopt_id(), | 2550 kInitStaticFieldRuntimeEntry, 1, locs()); |
| 2587 kInitStaticFieldRuntimeEntry, | |
| 2588 1, | |
| 2589 locs()); | |
| 2590 __ Drop(2); // Remove argument and result placeholder. | 2551 __ Drop(2); // Remove argument and result placeholder. |
| 2591 __ Bind(&no_call); | 2552 __ Bind(&no_call); |
| 2592 } | 2553 } |
| 2593 | 2554 |
| 2594 | 2555 |
| 2595 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2556 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
| 2596 bool opt) const { | 2557 bool opt) const { |
| 2597 const intptr_t kNumInputs = 1; | 2558 const intptr_t kNumInputs = 1; |
| 2598 const intptr_t kNumTemps = 0; | 2559 const intptr_t kNumTemps = 0; |
| 2599 LocationSummary* locs = new(zone) LocationSummary( | 2560 LocationSummary* locs = new (zone) |
| 2600 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2561 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2601 locs->set_in(0, Location::RegisterLocation(R0)); | 2562 locs->set_in(0, Location::RegisterLocation(R0)); |
| 2602 locs->set_out(0, Location::RegisterLocation(R0)); | 2563 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2603 return locs; | 2564 return locs; |
| 2604 } | 2565 } |
| 2605 | 2566 |
| 2606 | 2567 |
| 2607 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2568 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2608 const Register context_value = locs()->in(0).reg(); | 2569 const Register context_value = locs()->in(0).reg(); |
| 2609 const Register result = locs()->out(0).reg(); | 2570 const Register result = locs()->out(0).reg(); |
| 2610 | 2571 |
| 2611 __ PushObject(Object::null_object()); // Make room for the result. | 2572 __ PushObject(Object::null_object()); // Make room for the result. |
| 2612 __ Push(context_value); | 2573 __ Push(context_value); |
| 2613 compiler->GenerateRuntimeCall(token_pos(), | 2574 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2614 deopt_id(), | 2575 kCloneContextRuntimeEntry, 1, locs()); |
| 2615 kCloneContextRuntimeEntry, | 2576 __ Drop(1); // Remove argument. |
| 2616 1, | |
| 2617 locs()); | |
| 2618 __ Drop(1); // Remove argument. | |
| 2619 __ Pop(result); // Get result (cloned context). | 2577 __ Pop(result); // Get result (cloned context). |
| 2620 } | 2578 } |
| 2621 | 2579 |
| 2622 | 2580 |
| 2623 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2581 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
| 2624 bool opt) const { | 2582 bool opt) const { |
| 2625 UNREACHABLE(); | 2583 UNREACHABLE(); |
| 2626 return NULL; | 2584 return NULL; |
| 2627 } | 2585 } |
| 2628 | 2586 |
| 2629 | 2587 |
| 2630 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2588 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2631 __ Bind(compiler->GetJumpLabel(this)); | 2589 __ Bind(compiler->GetJumpLabel(this)); |
| 2632 compiler->AddExceptionHandler(catch_try_index(), | 2590 compiler->AddExceptionHandler(catch_try_index(), try_index(), |
| 2633 try_index(), | |
| 2634 compiler->assembler()->CodeSize(), | 2591 compiler->assembler()->CodeSize(), |
| 2635 catch_handler_types_, | 2592 catch_handler_types_, needs_stacktrace()); |
| 2636 needs_stacktrace()); | |
| 2637 // On lazy deoptimization we patch the optimized code here to enter the | 2593 // On lazy deoptimization we patch the optimized code here to enter the |
| 2638 // deoptimization stub. | 2594 // deoptimization stub. |
| 2639 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 2595 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |
| 2640 if (compiler->is_optimizing()) { | 2596 if (compiler->is_optimizing()) { |
| 2641 compiler->AddDeoptIndexAtCall(deopt_id); | 2597 compiler->AddDeoptIndexAtCall(deopt_id); |
| 2642 } else { | 2598 } else { |
| 2643 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 2599 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id, |
| 2644 deopt_id, | |
| 2645 TokenPosition::kNoSource); | 2600 TokenPosition::kNoSource); |
| 2646 } | 2601 } |
| 2647 if (HasParallelMove()) { | 2602 if (HasParallelMove()) { |
| 2648 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2603 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 2649 } | 2604 } |
| 2650 | 2605 |
| 2651 // Restore SP from FP as we are coming from a throw and the code for | 2606 // Restore SP from FP as we are coming from a throw and the code for |
| 2652 // popping arguments has not been run. | 2607 // popping arguments has not been run. |
| 2653 const intptr_t fp_sp_dist = | 2608 const intptr_t fp_sp_dist = |
| 2654 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 2609 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
| 2655 ASSERT(fp_sp_dist <= 0); | 2610 ASSERT(fp_sp_dist <= 0); |
| 2656 __ AddImmediate(SP, FP, fp_sp_dist); | 2611 __ AddImmediate(SP, FP, fp_sp_dist); |
| 2657 | 2612 |
| 2658 // Restore stack and initialize the two exception variables: | 2613 // Restore stack and initialize the two exception variables: |
| 2659 // exception and stack trace variables. | 2614 // exception and stack trace variables. |
| 2660 __ StoreToOffset(kExceptionObjectReg, | 2615 __ StoreToOffset(kExceptionObjectReg, FP, |
| 2661 FP, exception_var().index() * kWordSize); | 2616 exception_var().index() * kWordSize); |
| 2662 __ StoreToOffset(kStackTraceObjectReg, | 2617 __ StoreToOffset(kStackTraceObjectReg, FP, |
| 2663 FP, stacktrace_var().index() * kWordSize); | 2618 stacktrace_var().index() * kWordSize); |
| 2664 } | 2619 } |
| 2665 | 2620 |
| 2666 | 2621 |
| 2667 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 2622 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |
| 2668 bool opt) const { | 2623 bool opt) const { |
| 2669 const intptr_t kNumInputs = 0; | 2624 const intptr_t kNumInputs = 0; |
| 2670 const intptr_t kNumTemps = 1; | 2625 const intptr_t kNumTemps = 1; |
| 2671 LocationSummary* summary = new(zone) LocationSummary( | 2626 LocationSummary* summary = new (zone) LocationSummary( |
| 2672 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2627 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2673 summary->set_temp(0, Location::RequiresRegister()); | 2628 summary->set_temp(0, Location::RequiresRegister()); |
| 2674 return summary; | 2629 return summary; |
| 2675 } | 2630 } |
| 2676 | 2631 |
| 2677 | 2632 |
| 2678 class CheckStackOverflowSlowPath : public SlowPathCode { | 2633 class CheckStackOverflowSlowPath : public SlowPathCode { |
| 2679 public: | 2634 public: |
| 2680 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2635 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
| 2681 : instruction_(instruction) { } | 2636 : instruction_(instruction) {} |
| 2682 | 2637 |
| 2683 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2638 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2684 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { | 2639 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { |
| 2685 const Register value = instruction_->locs()->temp(0).reg(); | 2640 const Register value = instruction_->locs()->temp(0).reg(); |
| 2686 __ Comment("CheckStackOverflowSlowPathOsr"); | 2641 __ Comment("CheckStackOverflowSlowPathOsr"); |
| 2687 __ Bind(osr_entry_label()); | 2642 __ Bind(osr_entry_label()); |
| 2688 __ LoadImmediate(value, Thread::kOsrRequest); | 2643 __ LoadImmediate(value, Thread::kOsrRequest); |
| 2689 __ str(value, Address(THR, Thread::stack_overflow_flags_offset())); | 2644 __ str(value, Address(THR, Thread::stack_overflow_flags_offset())); |
| 2690 } | 2645 } |
| 2691 __ Comment("CheckStackOverflowSlowPath"); | 2646 __ Comment("CheckStackOverflowSlowPath"); |
| 2692 __ Bind(entry_label()); | 2647 __ Bind(entry_label()); |
| 2693 compiler->SaveLiveRegisters(instruction_->locs()); | 2648 compiler->SaveLiveRegisters(instruction_->locs()); |
| 2694 // pending_deoptimization_env_ is needed to generate a runtime call that | 2649 // pending_deoptimization_env_ is needed to generate a runtime call that |
| 2695 // may throw an exception. | 2650 // may throw an exception. |
| 2696 ASSERT(compiler->pending_deoptimization_env_ == NULL); | 2651 ASSERT(compiler->pending_deoptimization_env_ == NULL); |
| 2697 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); | 2652 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |
| 2698 compiler->pending_deoptimization_env_ = env; | 2653 compiler->pending_deoptimization_env_ = env; |
| 2699 compiler->GenerateRuntimeCall(instruction_->token_pos(), | 2654 compiler->GenerateRuntimeCall( |
| 2700 instruction_->deopt_id(), | 2655 instruction_->token_pos(), instruction_->deopt_id(), |
| 2701 kStackOverflowRuntimeEntry, | 2656 kStackOverflowRuntimeEntry, 0, instruction_->locs()); |
| 2702 0, | |
| 2703 instruction_->locs()); | |
| 2704 | 2657 |
| 2705 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { | 2658 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { |
| 2706 // In unoptimized code, record loop stack checks as possible OSR entries. | 2659 // In unoptimized code, record loop stack checks as possible OSR entries. |
| 2707 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, | 2660 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, |
| 2708 instruction_->deopt_id(), | 2661 instruction_->deopt_id(), |
| 2709 TokenPosition::kNoSource); | 2662 TokenPosition::kNoSource); |
| 2710 } | 2663 } |
| 2711 compiler->pending_deoptimization_env_ = NULL; | 2664 compiler->pending_deoptimization_env_ = NULL; |
| 2712 compiler->RestoreLiveRegisters(instruction_->locs()); | 2665 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2713 __ b(exit_label()); | 2666 __ b(exit_label()); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2734 __ CompareRegisters(CSP, TMP); | 2687 __ CompareRegisters(CSP, TMP); |
| 2735 __ b(slow_path->entry_label(), LS); | 2688 __ b(slow_path->entry_label(), LS); |
| 2736 if (compiler->CanOSRFunction() && in_loop()) { | 2689 if (compiler->CanOSRFunction() && in_loop()) { |
| 2737 const Register temp = locs()->temp(0).reg(); | 2690 const Register temp = locs()->temp(0).reg(); |
| 2738 // In unoptimized code check the usage counter to trigger OSR at loop | 2691 // In unoptimized code check the usage counter to trigger OSR at loop |
| 2739 // stack checks. Use progressively higher thresholds for more deeply | 2692 // stack checks. Use progressively higher thresholds for more deeply |
| 2740 // nested loops to attempt to hit outer loops with OSR when possible. | 2693 // nested loops to attempt to hit outer loops with OSR when possible. |
| 2741 __ LoadObject(temp, compiler->parsed_function().function()); | 2694 __ LoadObject(temp, compiler->parsed_function().function()); |
| 2742 intptr_t threshold = | 2695 intptr_t threshold = |
| 2743 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2696 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
| 2744 __ LoadFieldFromOffset( | 2697 __ LoadFieldFromOffset(temp, temp, Function::usage_counter_offset(), kWord); |
| 2745 temp, temp, Function::usage_counter_offset(), kWord); | |
| 2746 __ CompareImmediate(temp, threshold); | 2698 __ CompareImmediate(temp, threshold); |
| 2747 __ b(slow_path->osr_entry_label(), GE); | 2699 __ b(slow_path->osr_entry_label(), GE); |
| 2748 } | 2700 } |
| 2749 if (compiler->ForceSlowPathForStackOverflow()) { | 2701 if (compiler->ForceSlowPathForStackOverflow()) { |
| 2750 __ b(slow_path->entry_label()); | 2702 __ b(slow_path->entry_label()); |
| 2751 } | 2703 } |
| 2752 __ Bind(slow_path->exit_label()); | 2704 __ Bind(slow_path->exit_label()); |
| 2753 } | 2705 } |
| 2754 | 2706 |
| 2755 | 2707 |
| 2756 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2708 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
| 2757 BinarySmiOpInstr* shift_left) { | 2709 BinarySmiOpInstr* shift_left) { |
| 2758 const LocationSummary& locs = *shift_left->locs(); | 2710 const LocationSummary& locs = *shift_left->locs(); |
| 2759 const Register left = locs.in(0).reg(); | 2711 const Register left = locs.in(0).reg(); |
| 2760 const Register result = locs.out(0).reg(); | 2712 const Register result = locs.out(0).reg(); |
| 2761 Label* deopt = shift_left->CanDeoptimize() ? | 2713 Label* deopt = shift_left->CanDeoptimize() |
| 2762 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | 2714 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
| 2763 : NULL; | 2715 ICData::kDeoptBinarySmiOp) |
| 2716 : NULL; |
| 2764 if (locs.in(1).IsConstant()) { | 2717 if (locs.in(1).IsConstant()) { |
| 2765 const Object& constant = locs.in(1).constant(); | 2718 const Object& constant = locs.in(1).constant(); |
| 2766 ASSERT(constant.IsSmi()); | 2719 ASSERT(constant.IsSmi()); |
| 2767 // Immediate shift operation takes 6 bits for the count. | 2720 // Immediate shift operation takes 6 bits for the count. |
| 2768 const intptr_t kCountLimit = 0x3F; | 2721 const intptr_t kCountLimit = 0x3F; |
| 2769 const intptr_t value = Smi::Cast(constant).Value(); | 2722 const intptr_t value = Smi::Cast(constant).Value(); |
| 2770 ASSERT((0 < value) && (value < kCountLimit)); | 2723 ASSERT((0 < value) && (value < kCountLimit)); |
| 2771 if (shift_left->can_overflow()) { | 2724 if (shift_left->can_overflow()) { |
| 2772 // Check for overflow (preserve left). | 2725 // Check for overflow (preserve left). |
| 2773 __ LslImmediate(TMP, left, value); | 2726 __ LslImmediate(TMP, left, value); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2792 __ CompareRegisters(right, ZR); | 2745 __ CompareRegisters(right, ZR); |
| 2793 __ b(deopt, MI); | 2746 __ b(deopt, MI); |
| 2794 __ mov(result, ZR); | 2747 __ mov(result, ZR); |
| 2795 return; | 2748 return; |
| 2796 } | 2749 } |
| 2797 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); | 2750 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); |
| 2798 const bool right_needs_check = | 2751 const bool right_needs_check = |
| 2799 !RangeUtils::IsWithin(right_range, 0, max_right - 1); | 2752 !RangeUtils::IsWithin(right_range, 0, max_right - 1); |
| 2800 if (right_needs_check) { | 2753 if (right_needs_check) { |
| 2801 __ CompareImmediate(right, | 2754 __ CompareImmediate(right, |
| 2802 reinterpret_cast<int64_t>(Smi::New(max_right))); | 2755 reinterpret_cast<int64_t>(Smi::New(max_right))); |
| 2803 __ b(deopt, CS); | 2756 __ b(deopt, CS); |
| 2804 } | 2757 } |
| 2805 __ SmiUntag(TMP, right); | 2758 __ SmiUntag(TMP, right); |
| 2806 __ lslv(result, left, TMP); | 2759 __ lslv(result, left, TMP); |
| 2807 } | 2760 } |
| 2808 return; | 2761 return; |
| 2809 } | 2762 } |
| 2810 | 2763 |
| 2811 const bool right_needs_check = | 2764 const bool right_needs_check = |
| 2812 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); | 2765 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); |
| 2813 if (!shift_left->can_overflow()) { | 2766 if (!shift_left->can_overflow()) { |
| 2814 if (right_needs_check) { | 2767 if (right_needs_check) { |
| 2815 const bool right_may_be_negative = | 2768 const bool right_may_be_negative = |
| 2816 (right_range == NULL) || !right_range->IsPositive(); | 2769 (right_range == NULL) || !right_range->IsPositive(); |
| 2817 if (right_may_be_negative) { | 2770 if (right_may_be_negative) { |
| 2818 ASSERT(shift_left->CanDeoptimize()); | 2771 ASSERT(shift_left->CanDeoptimize()); |
| 2819 __ CompareRegisters(right, ZR); | 2772 __ CompareRegisters(right, ZR); |
| 2820 __ b(deopt, MI); | 2773 __ b(deopt, MI); |
| 2821 } | 2774 } |
| 2822 | 2775 |
| 2823 __ CompareImmediate( | 2776 __ CompareImmediate(right, |
| 2824 right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits))); | 2777 reinterpret_cast<int64_t>(Smi::New(Smi::kBits))); |
| 2825 __ csel(result, ZR, result, CS); | 2778 __ csel(result, ZR, result, CS); |
| 2826 __ SmiUntag(TMP, right); | 2779 __ SmiUntag(TMP, right); |
| 2827 __ lslv(TMP, left, TMP); | 2780 __ lslv(TMP, left, TMP); |
| 2828 __ csel(result, TMP, result, CC); | 2781 __ csel(result, TMP, result, CC); |
| 2829 } else { | 2782 } else { |
| 2830 __ SmiUntag(TMP, right); | 2783 __ SmiUntag(TMP, right); |
| 2831 __ lslv(result, left, TMP); | 2784 __ lslv(result, left, TMP); |
| 2832 } | 2785 } |
| 2833 } else { | 2786 } else { |
| 2834 if (right_needs_check) { | 2787 if (right_needs_check) { |
| 2835 ASSERT(shift_left->CanDeoptimize()); | 2788 ASSERT(shift_left->CanDeoptimize()); |
| 2836 __ CompareImmediate( | 2789 __ CompareImmediate(right, |
| 2837 right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits))); | 2790 reinterpret_cast<int64_t>(Smi::New(Smi::kBits))); |
| 2838 __ b(deopt, CS); | 2791 __ b(deopt, CS); |
| 2839 } | 2792 } |
| 2840 // Left is not a constant. | 2793 // Left is not a constant. |
| 2841 // Check if count too large for handling it inlined. | 2794 // Check if count too large for handling it inlined. |
| 2842 __ SmiUntag(TMP, right); | 2795 __ SmiUntag(TMP, right); |
| 2843 // Overflow test (preserve left, right, and TMP); | 2796 // Overflow test (preserve left, right, and TMP); |
| 2844 const Register temp = locs.temp(0).reg(); | 2797 const Register temp = locs.temp(0).reg(); |
| 2845 __ lslv(temp, left, TMP); | 2798 __ lslv(temp, left, TMP); |
| 2846 __ asrv(TMP2, temp, TMP); | 2799 __ asrv(TMP2, temp, TMP); |
| 2847 __ CompareRegisters(left, TMP2); | 2800 __ CompareRegisters(left, TMP2); |
| 2848 __ b(deopt, NE); // Overflow. | 2801 __ b(deopt, NE); // Overflow. |
| 2849 // Shift for result now we know there is no overflow. | 2802 // Shift for result now we know there is no overflow. |
| 2850 __ lslv(result, left, TMP); | 2803 __ lslv(result, left, TMP); |
| 2851 } | 2804 } |
| 2852 } | 2805 } |
| 2853 | 2806 |
| 2854 | 2807 |
| 2855 class CheckedSmiSlowPath : public SlowPathCode { | 2808 class CheckedSmiSlowPath : public SlowPathCode { |
| 2856 public: | 2809 public: |
| 2857 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) | 2810 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) |
| 2858 : instruction_(instruction), try_index_(try_index) { } | 2811 : instruction_(instruction), try_index_(try_index) {} |
| 2859 | 2812 |
| 2860 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2813 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2861 if (Assembler::EmittingComments()) { | 2814 if (Assembler::EmittingComments()) { |
| 2862 __ Comment("slow path smi operation"); | 2815 __ Comment("slow path smi operation"); |
| 2863 } | 2816 } |
| 2864 __ Bind(entry_label()); | 2817 __ Bind(entry_label()); |
| 2865 LocationSummary* locs = instruction_->locs(); | 2818 LocationSummary* locs = instruction_->locs(); |
| 2866 Register result = locs->out(0).reg(); | 2819 Register result = locs->out(0).reg(); |
| 2867 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 2820 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
| 2868 | 2821 |
| 2869 compiler->SaveLiveRegisters(locs); | 2822 compiler->SaveLiveRegisters(locs); |
| 2870 __ Push(locs->in(0).reg()); | 2823 __ Push(locs->in(0).reg()); |
| 2871 __ Push(locs->in(1).reg()); | 2824 __ Push(locs->in(1).reg()); |
| 2872 compiler->EmitMegamorphicInstanceCall( | 2825 compiler->EmitMegamorphicInstanceCall( |
| 2873 *instruction_->call()->ic_data(), | 2826 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
| 2874 instruction_->call()->ArgumentCount(), | 2827 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
| 2875 instruction_->call()->deopt_id(), | 2828 locs, try_index_, |
| 2876 instruction_->call()->token_pos(), | |
| 2877 locs, | |
| 2878 try_index_, | |
| 2879 /* slow_path_argument_count = */ 2); | 2829 /* slow_path_argument_count = */ 2); |
| 2880 __ mov(result, R0); | 2830 __ mov(result, R0); |
| 2881 compiler->RestoreLiveRegisters(locs); | 2831 compiler->RestoreLiveRegisters(locs); |
| 2882 __ b(exit_label()); | 2832 __ b(exit_label()); |
| 2883 } | 2833 } |
| 2884 | 2834 |
| 2885 private: | 2835 private: |
| 2886 CheckedSmiOpInstr* instruction_; | 2836 CheckedSmiOpInstr* instruction_; |
| 2887 intptr_t try_index_; | 2837 intptr_t try_index_; |
| 2888 }; | 2838 }; |
| 2889 | 2839 |
| 2890 | 2840 |
| 2891 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 2841 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
| 2892 bool opt) const { | 2842 bool opt) const { |
| 2893 const intptr_t kNumInputs = 2; | 2843 const intptr_t kNumInputs = 2; |
| 2894 const intptr_t kNumTemps = 0; | 2844 const intptr_t kNumTemps = 0; |
| 2895 LocationSummary* summary = new(zone) LocationSummary( | 2845 LocationSummary* summary = new (zone) LocationSummary( |
| 2896 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2846 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2897 summary->set_in(0, Location::RequiresRegister()); | 2847 summary->set_in(0, Location::RequiresRegister()); |
| 2898 summary->set_in(1, Location::RequiresRegister()); | 2848 summary->set_in(1, Location::RequiresRegister()); |
| 2899 summary->set_out(0, Location::RequiresRegister()); | 2849 summary->set_out(0, Location::RequiresRegister()); |
| 2900 return summary; | 2850 return summary; |
| 2901 } | 2851 } |
| 2902 | 2852 |
| 2903 | 2853 |
| 2904 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2854 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2905 CheckedSmiSlowPath* slow_path = | 2855 CheckedSmiSlowPath* slow_path = |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2963 | 2913 |
| 2964 class CheckedSmiComparisonSlowPath : public SlowPathCode { | 2914 class CheckedSmiComparisonSlowPath : public SlowPathCode { |
| 2965 public: | 2915 public: |
| 2966 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, | 2916 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, |
| 2967 intptr_t try_index, | 2917 intptr_t try_index, |
| 2968 BranchLabels labels, | 2918 BranchLabels labels, |
| 2969 bool merged) | 2919 bool merged) |
| 2970 : instruction_(instruction), | 2920 : instruction_(instruction), |
| 2971 try_index_(try_index), | 2921 try_index_(try_index), |
| 2972 labels_(labels), | 2922 labels_(labels), |
| 2973 merged_(merged) { } | 2923 merged_(merged) {} |
| 2974 | 2924 |
| 2975 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2925 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2976 if (Assembler::EmittingComments()) { | 2926 if (Assembler::EmittingComments()) { |
| 2977 __ Comment("slow path smi operation"); | 2927 __ Comment("slow path smi operation"); |
| 2978 } | 2928 } |
| 2979 __ Bind(entry_label()); | 2929 __ Bind(entry_label()); |
| 2980 LocationSummary* locs = instruction_->locs(); | 2930 LocationSummary* locs = instruction_->locs(); |
| 2981 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); | 2931 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); |
| 2982 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 2932 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
| 2983 | 2933 |
| 2984 compiler->SaveLiveRegisters(locs); | 2934 compiler->SaveLiveRegisters(locs); |
| 2985 __ Push(locs->in(0).reg()); | 2935 __ Push(locs->in(0).reg()); |
| 2986 __ Push(locs->in(1).reg()); | 2936 __ Push(locs->in(1).reg()); |
| 2987 compiler->EmitMegamorphicInstanceCall( | 2937 compiler->EmitMegamorphicInstanceCall( |
| 2988 *instruction_->call()->ic_data(), | 2938 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
| 2989 instruction_->call()->ArgumentCount(), | 2939 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
| 2990 instruction_->call()->deopt_id(), | 2940 locs, try_index_, |
| 2991 instruction_->call()->token_pos(), | |
| 2992 locs, | |
| 2993 try_index_, | |
| 2994 /* slow_path_argument_count = */ 2); | 2941 /* slow_path_argument_count = */ 2); |
| 2995 __ mov(result, R0); | 2942 __ mov(result, R0); |
| 2996 compiler->RestoreLiveRegisters(locs); | 2943 compiler->RestoreLiveRegisters(locs); |
| 2997 if (merged_) { | 2944 if (merged_) { |
| 2998 __ CompareObject(result, Bool::True()); | 2945 __ CompareObject(result, Bool::True()); |
| 2999 __ b(instruction_->is_negated() | 2946 __ b( |
| 3000 ? labels_.false_label : labels_.true_label, EQ); | 2947 instruction_->is_negated() ? labels_.false_label : labels_.true_label, |
| 3001 __ b(instruction_->is_negated() | 2948 EQ); |
| 3002 ? labels_.true_label : labels_.false_label); | 2949 __ b(instruction_->is_negated() ? labels_.true_label |
| 2950 : labels_.false_label); |
| 3003 } else { | 2951 } else { |
| 3004 __ b(exit_label()); | 2952 __ b(exit_label()); |
| 3005 } | 2953 } |
| 3006 } | 2954 } |
| 3007 | 2955 |
| 3008 private: | 2956 private: |
| 3009 CheckedSmiComparisonInstr* instruction_; | 2957 CheckedSmiComparisonInstr* instruction_; |
| 3010 intptr_t try_index_; | 2958 intptr_t try_index_; |
| 3011 BranchLabels labels_; | 2959 BranchLabels labels_; |
| 3012 bool merged_; | 2960 bool merged_; |
| 3013 }; | 2961 }; |
| 3014 | 2962 |
| 3015 | 2963 |
| 3016 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 2964 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
| 3017 Zone* zone, bool opt) const { | 2965 Zone* zone, |
| 2966 bool opt) const { |
| 3018 const intptr_t kNumInputs = 2; | 2967 const intptr_t kNumInputs = 2; |
| 3019 const intptr_t kNumTemps = 1; | 2968 const intptr_t kNumTemps = 1; |
| 3020 LocationSummary* summary = new(zone) LocationSummary( | 2969 LocationSummary* summary = new (zone) LocationSummary( |
| 3021 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2970 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3022 summary->set_in(0, Location::RequiresRegister()); | 2971 summary->set_in(0, Location::RequiresRegister()); |
| 3023 summary->set_in(1, Location::RequiresRegister()); | 2972 summary->set_in(1, Location::RequiresRegister()); |
| 3024 summary->set_temp(0, Location::RequiresRegister()); | 2973 summary->set_temp(0, Location::RequiresRegister()); |
| 3025 summary->set_out(0, Location::RequiresRegister()); | 2974 summary->set_out(0, Location::RequiresRegister()); |
| 3026 return summary; | 2975 return summary; |
| 3027 } | 2976 } |
| 3028 | 2977 |
| 3029 | 2978 |
| 3030 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 2979 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
| 3031 FlowGraphCompiler* compiler, BranchLabels labels) { | 2980 FlowGraphCompiler* compiler, |
| 2981 BranchLabels labels) { |
| 3032 return EmitSmiComparisonOp(compiler, locs(), kind()); | 2982 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 3033 } | 2983 } |
| 3034 | 2984 |
| 3035 | 2985 |
| 3036 #define EMIT_SMI_CHECK \ | 2986 #define EMIT_SMI_CHECK \ |
| 3037 Register left = locs()->in(0).reg(); \ | 2987 Register left = locs()->in(0).reg(); \ |
| 3038 Register right = locs()->in(1).reg(); \ | 2988 Register right = locs()->in(1).reg(); \ |
| 3039 Register temp = locs()->temp(0).reg(); \ | 2989 Register temp = locs()->temp(0).reg(); \ |
| 3040 intptr_t left_cid = this->left()->Type()->ToCid(); \ | 2990 intptr_t left_cid = this->left()->Type()->ToCid(); \ |
| 3041 intptr_t right_cid = this->right()->Type()->ToCid(); \ | 2991 intptr_t right_cid = this->right()->Type()->ToCid(); \ |
| 3042 if (this->left()->definition() == this->right()->definition()) { \ | 2992 if (this->left()->definition() == this->right()->definition()) { \ |
| 3043 __ tsti(left, Immediate(kSmiTagMask)); \ | 2993 __ tsti(left, Immediate(kSmiTagMask)); \ |
| 3044 } else if (left_cid == kSmiCid) { \ | 2994 } else if (left_cid == kSmiCid) { \ |
| 3045 __ tsti(right, Immediate(kSmiTagMask)); \ | 2995 __ tsti(right, Immediate(kSmiTagMask)); \ |
| 3046 } else if (right_cid == kSmiCid) { \ | 2996 } else if (right_cid == kSmiCid) { \ |
| 3047 __ tsti(left, Immediate(kSmiTagMask)); \ | 2997 __ tsti(left, Immediate(kSmiTagMask)); \ |
| 3048 } else { \ | 2998 } else { \ |
| 3049 __ orr(temp, left, Operand(right)); \ | 2999 __ orr(temp, left, Operand(right)); \ |
| 3050 __ tsti(temp, Immediate(kSmiTagMask)); \ | 3000 __ tsti(temp, Immediate(kSmiTagMask)); \ |
| 3051 } \ | 3001 } \ |
| 3052 __ b(slow_path->entry_label(), NE) | 3002 __ b(slow_path->entry_label(), NE) |
| 3053 | 3003 |
| 3054 | 3004 |
| 3055 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3005 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 3056 BranchInstr* branch) { | 3006 BranchInstr* branch) { |
| 3057 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3007 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 3058 CheckedSmiComparisonSlowPath* slow_path = | 3008 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
| 3059 new CheckedSmiComparisonSlowPath(this, | 3009 this, compiler->CurrentTryIndex(), labels, |
| 3060 compiler->CurrentTryIndex(), | 3010 /* merged = */ true); |
| 3061 labels, | |
| 3062 /* merged = */ true); | |
| 3063 compiler->AddSlowPathCode(slow_path); | 3011 compiler->AddSlowPathCode(slow_path); |
| 3064 EMIT_SMI_CHECK; | 3012 EMIT_SMI_CHECK; |
| 3065 Condition true_condition = EmitComparisonCode(compiler, labels); | 3013 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3066 EmitBranchOnCondition(compiler, true_condition, labels); | 3014 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3067 __ Bind(slow_path->exit_label()); | 3015 __ Bind(slow_path->exit_label()); |
| 3068 } | 3016 } |
| 3069 | 3017 |
| 3070 | 3018 |
| 3071 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3019 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3072 Label true_label, false_label, done; | 3020 Label true_label, false_label, done; |
| 3073 BranchLabels labels = { &true_label, &false_label, &false_label }; | 3021 BranchLabels labels = {&true_label, &false_label, &false_label}; |
| 3074 CheckedSmiComparisonSlowPath* slow_path = | 3022 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
| 3075 new CheckedSmiComparisonSlowPath(this, | 3023 this, compiler->CurrentTryIndex(), labels, |
| 3076 compiler->CurrentTryIndex(), | 3024 /* merged = */ false); |
| 3077 labels, | |
| 3078 /* merged = */ false); | |
| 3079 compiler->AddSlowPathCode(slow_path); | 3025 compiler->AddSlowPathCode(slow_path); |
| 3080 EMIT_SMI_CHECK; | 3026 EMIT_SMI_CHECK; |
| 3081 Condition true_condition = | 3027 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3082 EmitComparisonCode(compiler, labels); | |
| 3083 EmitBranchOnCondition(compiler, true_condition, labels); | 3028 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3084 Register result = locs()->out(0).reg(); | 3029 Register result = locs()->out(0).reg(); |
| 3085 __ Bind(&false_label); | 3030 __ Bind(&false_label); |
| 3086 __ LoadObject(result, Bool::False()); | 3031 __ LoadObject(result, Bool::False()); |
| 3087 __ b(&done); | 3032 __ b(&done); |
| 3088 __ Bind(&true_label); | 3033 __ Bind(&true_label); |
| 3089 __ LoadObject(result, Bool::True()); | 3034 __ LoadObject(result, Bool::True()); |
| 3090 __ Bind(&done); | 3035 __ Bind(&done); |
| 3091 __ Bind(slow_path->exit_label()); | 3036 __ Bind(slow_path->exit_label()); |
| 3092 } | 3037 } |
| 3093 | 3038 |
| 3094 | 3039 |
| 3095 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 3040 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 3096 bool opt) const { | 3041 bool opt) const { |
| 3097 const intptr_t kNumInputs = 2; | 3042 const intptr_t kNumInputs = 2; |
| 3098 const intptr_t kNumTemps = | 3043 const intptr_t kNumTemps = (((op_kind() == Token::kSHL) && can_overflow()) || |
| 3099 (((op_kind() == Token::kSHL) && can_overflow()) || | 3044 (op_kind() == Token::kSHR)) |
| 3100 (op_kind() == Token::kSHR)) ? 1 : 0; | 3045 ? 1 |
| 3101 LocationSummary* summary = new(zone) LocationSummary( | 3046 : 0; |
| 3102 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3047 LocationSummary* summary = new (zone) |
| 3048 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3103 if (op_kind() == Token::kTRUNCDIV) { | 3049 if (op_kind() == Token::kTRUNCDIV) { |
| 3104 summary->set_in(0, Location::RequiresRegister()); | 3050 summary->set_in(0, Location::RequiresRegister()); |
| 3105 if (RightIsPowerOfTwoConstant()) { | 3051 if (RightIsPowerOfTwoConstant()) { |
| 3106 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 3052 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
| 3107 summary->set_in(1, Location::Constant(right_constant)); | 3053 summary->set_in(1, Location::Constant(right_constant)); |
| 3108 } else { | 3054 } else { |
| 3109 summary->set_in(1, Location::RequiresRegister()); | 3055 summary->set_in(1, Location::RequiresRegister()); |
| 3110 } | 3056 } |
| 3111 summary->set_out(0, Location::RequiresRegister()); | 3057 summary->set_out(0, Location::RequiresRegister()); |
| 3112 return summary; | 3058 return summary; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3208 __ OrImmediate(result, left, imm); | 3154 __ OrImmediate(result, left, imm); |
| 3209 break; | 3155 break; |
| 3210 case Token::kBIT_XOR: | 3156 case Token::kBIT_XOR: |
| 3211 // No overflow check. | 3157 // No overflow check. |
| 3212 __ XorImmediate(result, left, imm); | 3158 __ XorImmediate(result, left, imm); |
| 3213 break; | 3159 break; |
| 3214 case Token::kSHR: { | 3160 case Token::kSHR: { |
| 3215 // Asr operation masks the count to 6 bits. | 3161 // Asr operation masks the count to 6 bits. |
| 3216 const intptr_t kCountLimit = 0x3F; | 3162 const intptr_t kCountLimit = 0x3F; |
| 3217 intptr_t value = Smi::Cast(constant).Value(); | 3163 intptr_t value = Smi::Cast(constant).Value(); |
| 3218 __ AsrImmediate( | 3164 __ AsrImmediate(result, left, |
| 3219 result, left, Utils::Minimum(value + kSmiTagSize, kCountLimit)); | 3165 Utils::Minimum(value + kSmiTagSize, kCountLimit)); |
| 3220 __ SmiTag(result); | 3166 __ SmiTag(result); |
| 3221 break; | 3167 break; |
| 3222 } | 3168 } |
| 3223 default: | 3169 default: |
| 3224 UNREACHABLE(); | 3170 UNREACHABLE(); |
| 3225 break; | 3171 break; |
| 3226 } | 3172 } |
| 3227 return; | 3173 return; |
| 3228 } | 3174 } |
| 3229 | 3175 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3246 __ subs(result, left, Operand(right)); | 3192 __ subs(result, left, Operand(right)); |
| 3247 __ b(deopt, VS); | 3193 __ b(deopt, VS); |
| 3248 } | 3194 } |
| 3249 break; | 3195 break; |
| 3250 } | 3196 } |
| 3251 case Token::kMUL: { | 3197 case Token::kMUL: { |
| 3252 __ SmiUntag(TMP, left); | 3198 __ SmiUntag(TMP, left); |
| 3253 if (deopt == NULL) { | 3199 if (deopt == NULL) { |
| 3254 __ mul(result, TMP, right); | 3200 __ mul(result, TMP, right); |
| 3255 } else { | 3201 } else { |
| 3256 __ mul(result, TMP, right); | 3202 __ mul(result, TMP, right); |
| 3257 __ smulh(TMP, TMP, right); | 3203 __ smulh(TMP, TMP, right); |
| 3258 // TMP: result bits 64..127. | 3204 // TMP: result bits 64..127. |
| 3259 __ cmp(TMP, Operand(result, ASR, 63)); | 3205 __ cmp(TMP, Operand(result, ASR, 63)); |
| 3260 __ b(deopt, NE); | 3206 __ b(deopt, NE); |
| 3261 } | 3207 } |
| 3262 break; | 3208 break; |
| 3263 } | 3209 } |
| 3264 case Token::kBIT_AND: { | 3210 case Token::kBIT_AND: { |
| 3265 // No overflow check. | 3211 // No overflow check. |
| 3266 __ and_(result, left, Operand(right)); | 3212 __ and_(result, left, Operand(right)); |
| 3267 break; | 3213 break; |
| 3268 } | 3214 } |
| 3269 case Token::kBIT_OR: { | 3215 case Token::kBIT_OR: { |
| 3270 // No overflow check. | 3216 // No overflow check. |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3369 } | 3315 } |
| 3370 | 3316 |
| 3371 | 3317 |
| 3372 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3318 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
| 3373 bool opt) const { | 3319 bool opt) const { |
| 3374 intptr_t left_cid = left()->Type()->ToCid(); | 3320 intptr_t left_cid = left()->Type()->ToCid(); |
| 3375 intptr_t right_cid = right()->Type()->ToCid(); | 3321 intptr_t right_cid = right()->Type()->ToCid(); |
| 3376 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3322 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
| 3377 const intptr_t kNumInputs = 2; | 3323 const intptr_t kNumInputs = 2; |
| 3378 const intptr_t kNumTemps = 0; | 3324 const intptr_t kNumTemps = 0; |
| 3379 LocationSummary* summary = new(zone) LocationSummary( | 3325 LocationSummary* summary = new (zone) |
| 3380 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3326 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3381 summary->set_in(0, Location::RequiresRegister()); | 3327 summary->set_in(0, Location::RequiresRegister()); |
| 3382 summary->set_in(1, Location::RequiresRegister()); | 3328 summary->set_in(1, Location::RequiresRegister()); |
| 3383 return summary; | 3329 return summary; |
| 3384 } | 3330 } |
| 3385 | 3331 |
| 3386 | 3332 |
| 3387 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3333 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3388 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3334 Label* deopt = |
| 3389 ICData::kDeoptBinaryDoubleOp, | 3335 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
| 3390 licm_hoisted_ ? ICData::kHoisted : 0); | 3336 licm_hoisted_ ? ICData::kHoisted : 0); |
| 3391 intptr_t left_cid = left()->Type()->ToCid(); | 3337 intptr_t left_cid = left()->Type()->ToCid(); |
| 3392 intptr_t right_cid = right()->Type()->ToCid(); | 3338 intptr_t right_cid = right()->Type()->ToCid(); |
| 3393 const Register left = locs()->in(0).reg(); | 3339 const Register left = locs()->in(0).reg(); |
| 3394 const Register right = locs()->in(1).reg(); | 3340 const Register right = locs()->in(1).reg(); |
| 3395 if (this->left()->definition() == this->right()->definition()) { | 3341 if (this->left()->definition() == this->right()->definition()) { |
| 3396 __ tsti(left, Immediate(kSmiTagMask)); | 3342 __ tsti(left, Immediate(kSmiTagMask)); |
| 3397 } else if (left_cid == kSmiCid) { | 3343 } else if (left_cid == kSmiCid) { |
| 3398 __ tsti(right, Immediate(kSmiTagMask)); | 3344 __ tsti(right, Immediate(kSmiTagMask)); |
| 3399 } else if (right_cid == kSmiCid) { | 3345 } else if (right_cid == kSmiCid) { |
| 3400 __ tsti(left, Immediate(kSmiTagMask)); | 3346 __ tsti(left, Immediate(kSmiTagMask)); |
| 3401 } else { | 3347 } else { |
| 3402 __ orr(TMP, left, Operand(right)); | 3348 __ orr(TMP, left, Operand(right)); |
| 3403 __ tsti(TMP, Immediate(kSmiTagMask)); | 3349 __ tsti(TMP, Immediate(kSmiTagMask)); |
| 3404 } | 3350 } |
| 3405 __ b(deopt, EQ); | 3351 __ b(deopt, EQ); |
| 3406 } | 3352 } |
| 3407 | 3353 |
| 3408 | 3354 |
| 3409 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, | 3355 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3410 bool opt) const { | |
| 3411 const intptr_t kNumInputs = 1; | 3356 const intptr_t kNumInputs = 1; |
| 3412 const intptr_t kNumTemps = 1; | 3357 const intptr_t kNumTemps = 1; |
| 3413 LocationSummary* summary = new(zone) LocationSummary( | 3358 LocationSummary* summary = new (zone) LocationSummary( |
| 3414 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3359 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3415 summary->set_in(0, Location::RequiresFpuRegister()); | 3360 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3416 summary->set_temp(0, Location::RequiresRegister()); | 3361 summary->set_temp(0, Location::RequiresRegister()); |
| 3417 summary->set_out(0, Location::RequiresRegister()); | 3362 summary->set_out(0, Location::RequiresRegister()); |
| 3418 return summary; | 3363 return summary; |
| 3419 } | 3364 } |
| 3420 | 3365 |
| 3421 | 3366 |
| 3422 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3367 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3423 const Register out_reg = locs()->out(0).reg(); | 3368 const Register out_reg = locs()->out(0).reg(); |
| 3424 const Register temp_reg = locs()->temp(0).reg(); | 3369 const Register temp_reg = locs()->temp(0).reg(); |
| 3425 const VRegister value = locs()->in(0).fpu_reg(); | 3370 const VRegister value = locs()->in(0).fpu_reg(); |
| 3426 | 3371 |
| 3427 BoxAllocationSlowPath::Allocate( | 3372 BoxAllocationSlowPath::Allocate(compiler, this, |
| 3428 compiler, | 3373 compiler->BoxClassFor(from_representation()), |
| 3429 this, | 3374 out_reg, temp_reg); |
| 3430 compiler->BoxClassFor(from_representation()), | |
| 3431 out_reg, | |
| 3432 temp_reg); | |
| 3433 | 3375 |
| 3434 switch (from_representation()) { | 3376 switch (from_representation()) { |
| 3435 case kUnboxedDouble: | 3377 case kUnboxedDouble: |
| 3436 __ StoreDFieldToOffset(value, out_reg, ValueOffset()); | 3378 __ StoreDFieldToOffset(value, out_reg, ValueOffset()); |
| 3437 break; | 3379 break; |
| 3438 case kUnboxedFloat32x4: | 3380 case kUnboxedFloat32x4: |
| 3439 case kUnboxedFloat64x2: | 3381 case kUnboxedFloat64x2: |
| 3440 case kUnboxedInt32x4: | 3382 case kUnboxedInt32x4: |
| 3441 __ StoreQFieldToOffset(value, out_reg, ValueOffset()); | 3383 __ StoreQFieldToOffset(value, out_reg, ValueOffset()); |
| 3442 break; | 3384 break; |
| 3443 default: | 3385 default: |
| 3444 UNREACHABLE(); | 3386 UNREACHABLE(); |
| 3445 break; | 3387 break; |
| 3446 } | 3388 } |
| 3447 } | 3389 } |
| 3448 | 3390 |
| 3449 | 3391 |
| 3450 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, | 3392 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3451 bool opt) const { | |
| 3452 const intptr_t kNumInputs = 1; | 3393 const intptr_t kNumInputs = 1; |
| 3453 const intptr_t kNumTemps = 0; | 3394 const intptr_t kNumTemps = 0; |
| 3454 LocationSummary* summary = new(zone) LocationSummary( | 3395 LocationSummary* summary = new (zone) |
| 3455 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3396 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3456 summary->set_in(0, Location::RequiresRegister()); | 3397 summary->set_in(0, Location::RequiresRegister()); |
| 3457 summary->set_out(0, Location::RequiresFpuRegister()); | 3398 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3458 return summary; | 3399 return summary; |
| 3459 } | 3400 } |
| 3460 | 3401 |
| 3461 | 3402 |
| 3462 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { | 3403 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |
| 3463 const Register box = locs()->in(0).reg(); | 3404 const Register box = locs()->in(0).reg(); |
| 3464 | 3405 |
| 3465 switch (representation()) { | 3406 switch (representation()) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3515 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3456 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3516 const intptr_t value_cid = value()->Type()->ToCid(); | 3457 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3517 const intptr_t box_cid = BoxCid(); | 3458 const intptr_t box_cid = BoxCid(); |
| 3518 | 3459 |
| 3519 if (value_cid == box_cid) { | 3460 if (value_cid == box_cid) { |
| 3520 EmitLoadFromBox(compiler); | 3461 EmitLoadFromBox(compiler); |
| 3521 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 3462 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
| 3522 EmitSmiConversion(compiler); | 3463 EmitSmiConversion(compiler); |
| 3523 } else { | 3464 } else { |
| 3524 const Register box = locs()->in(0).reg(); | 3465 const Register box = locs()->in(0).reg(); |
| 3525 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), | 3466 Label* deopt = |
| 3526 ICData::kDeoptCheckClass); | 3467 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass); |
| 3527 Label is_smi; | 3468 Label is_smi; |
| 3528 | 3469 |
| 3529 if ((value()->Type()->ToNullableCid() == box_cid) && | 3470 if ((value()->Type()->ToNullableCid() == box_cid) && |
| 3530 value()->Type()->is_nullable()) { | 3471 value()->Type()->is_nullable()) { |
| 3531 __ CompareObject(box, Object::null_object()); | 3472 __ CompareObject(box, Object::null_object()); |
| 3532 __ b(deopt, EQ); | 3473 __ b(deopt, EQ); |
| 3533 } else { | 3474 } else { |
| 3534 __ tsti(box, Immediate(kSmiTagMask)); | 3475 __ tsti(box, Immediate(kSmiTagMask)); |
| 3535 __ b(CanConvertSmi() ? &is_smi : deopt, EQ); | 3476 __ b(CanConvertSmi() ? &is_smi : deopt, EQ); |
| 3536 __ CompareClassId(box, box_cid); | 3477 __ CompareClassId(box, box_cid); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3549 } | 3490 } |
| 3550 } | 3491 } |
| 3551 | 3492 |
| 3552 | 3493 |
| 3553 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 3494 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 3554 bool opt) const { | 3495 bool opt) const { |
| 3555 ASSERT((from_representation() == kUnboxedInt32) || | 3496 ASSERT((from_representation() == kUnboxedInt32) || |
| 3556 (from_representation() == kUnboxedUint32)); | 3497 (from_representation() == kUnboxedUint32)); |
| 3557 const intptr_t kNumInputs = 1; | 3498 const intptr_t kNumInputs = 1; |
| 3558 const intptr_t kNumTemps = 0; | 3499 const intptr_t kNumTemps = 0; |
| 3559 LocationSummary* summary = new(zone) LocationSummary( | 3500 LocationSummary* summary = new (zone) |
| 3560 zone, | 3501 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3561 kNumInputs, | |
| 3562 kNumTemps, | |
| 3563 LocationSummary::kNoCall); | |
| 3564 summary->set_in(0, Location::RequiresRegister()); | 3502 summary->set_in(0, Location::RequiresRegister()); |
| 3565 summary->set_out(0, Location::RequiresRegister()); | 3503 summary->set_out(0, Location::RequiresRegister()); |
| 3566 return summary; | 3504 return summary; |
| 3567 } | 3505 } |
| 3568 | 3506 |
| 3569 | 3507 |
| 3570 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3508 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3571 Register value = locs()->in(0).reg(); | 3509 Register value = locs()->in(0).reg(); |
| 3572 Register out = locs()->out(0).reg(); | 3510 Register out = locs()->out(0).reg(); |
| 3573 ASSERT(value != out); | 3511 ASSERT(value != out); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3584 } | 3522 } |
| 3585 | 3523 |
| 3586 | 3524 |
| 3587 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr) | 3525 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr) |
| 3588 | 3526 |
| 3589 | 3527 |
| 3590 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 3528 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 3591 bool opt) const { | 3529 bool opt) const { |
| 3592 const intptr_t kNumInputs = 1; | 3530 const intptr_t kNumInputs = 1; |
| 3593 const intptr_t kNumTemps = 0; | 3531 const intptr_t kNumTemps = 0; |
| 3594 LocationSummary* summary = new(zone) LocationSummary( | 3532 LocationSummary* summary = new (zone) |
| 3595 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3533 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3596 summary->set_in(0, Location::RequiresRegister()); | 3534 summary->set_in(0, Location::RequiresRegister()); |
| 3597 summary->set_out(0, Location::RequiresRegister()); | 3535 summary->set_out(0, Location::RequiresRegister()); |
| 3598 return summary; | 3536 return summary; |
| 3599 } | 3537 } |
| 3600 | 3538 |
| 3601 | 3539 |
| 3602 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3540 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3603 const intptr_t value_cid = value()->Type()->ToCid(); | 3541 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3604 const Register out = locs()->out(0).reg(); | 3542 const Register out = locs()->out(0).reg(); |
| 3605 const Register value = locs()->in(0).reg(); | 3543 const Register value = locs()->in(0).reg(); |
| 3606 Label* deopt = CanDeoptimize() ? | 3544 Label* deopt = |
| 3607 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL; | 3545 CanDeoptimize() |
| 3546 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) |
| 3547 : NULL; |
| 3608 | 3548 |
| 3609 if (value_cid == kSmiCid) { | 3549 if (value_cid == kSmiCid) { |
| 3610 __ SmiUntag(out, value); | 3550 __ SmiUntag(out, value); |
| 3611 } else if (value_cid == kMintCid) { | 3551 } else if (value_cid == kMintCid) { |
| 3612 __ LoadFieldFromOffset(out, value, Mint::value_offset()); | 3552 __ LoadFieldFromOffset(out, value, Mint::value_offset()); |
| 3613 } else if (!CanDeoptimize()) { | 3553 } else if (!CanDeoptimize()) { |
| 3614 // Type information is not conclusive, but range analysis found | 3554 // Type information is not conclusive, but range analysis found |
| 3615 // the value to be in int64 range. Therefore it must be a smi | 3555 // the value to be in int64 range. Therefore it must be a smi |
| 3616 // or mint value. | 3556 // or mint value. |
| 3617 ASSERT(is_truncating()); | 3557 ASSERT(is_truncating()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3639 __ cmp(out, Operand(out, SXTW, 0)); | 3579 __ cmp(out, Operand(out, SXTW, 0)); |
| 3640 __ b(deopt, NE); | 3580 __ b(deopt, NE); |
| 3641 } | 3581 } |
| 3642 } | 3582 } |
| 3643 | 3583 |
| 3644 | 3584 |
| 3645 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 3585 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 3646 bool opt) const { | 3586 bool opt) const { |
| 3647 const intptr_t kNumInputs = 2; | 3587 const intptr_t kNumInputs = 2; |
| 3648 const intptr_t kNumTemps = 0; | 3588 const intptr_t kNumTemps = 0; |
| 3649 LocationSummary* summary = new(zone) LocationSummary( | 3589 LocationSummary* summary = new (zone) |
| 3650 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3590 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3651 summary->set_in(0, Location::RequiresFpuRegister()); | 3591 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3652 summary->set_in(1, Location::RequiresFpuRegister()); | 3592 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3653 summary->set_out(0, Location::RequiresFpuRegister()); | 3593 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3654 return summary; | 3594 return summary; |
| 3655 } | 3595 } |
| 3656 | 3596 |
| 3657 | 3597 |
| 3658 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3598 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3659 const VRegister left = locs()->in(0).fpu_reg(); | 3599 const VRegister left = locs()->in(0).fpu_reg(); |
| 3660 const VRegister right = locs()->in(1).fpu_reg(); | 3600 const VRegister right = locs()->in(1).fpu_reg(); |
| 3661 const VRegister result = locs()->out(0).fpu_reg(); | 3601 const VRegister result = locs()->out(0).fpu_reg(); |
| 3662 switch (op_kind()) { | 3602 switch (op_kind()) { |
| 3663 case Token::kADD: __ faddd(result, left, right); break; | 3603 case Token::kADD: |
| 3664 case Token::kSUB: __ fsubd(result, left, right); break; | 3604 __ faddd(result, left, right); |
| 3665 case Token::kMUL: __ fmuld(result, left, right); break; | 3605 break; |
| 3666 case Token::kDIV: __ fdivd(result, left, right); break; | 3606 case Token::kSUB: |
| 3667 default: UNREACHABLE(); | 3607 __ fsubd(result, left, right); |
| 3608 break; |
| 3609 case Token::kMUL: |
| 3610 __ fmuld(result, left, right); |
| 3611 break; |
| 3612 case Token::kDIV: |
| 3613 __ fdivd(result, left, right); |
| 3614 break; |
| 3615 default: |
| 3616 UNREACHABLE(); |
| 3668 } | 3617 } |
| 3669 } | 3618 } |
| 3670 | 3619 |
| 3671 | 3620 |
| 3672 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 3621 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |
| 3673 bool opt) const { | 3622 bool opt) const { |
| 3674 const intptr_t kNumInputs = 1; | 3623 const intptr_t kNumInputs = 1; |
| 3675 const intptr_t kNumTemps = | 3624 const intptr_t kNumTemps = |
| 3676 op_kind() == MethodRecognizer::kDouble_getIsInfinite ? 1 : 0; | 3625 op_kind() == MethodRecognizer::kDouble_getIsInfinite ? 1 : 0; |
| 3677 LocationSummary* summary = new(zone) LocationSummary( | 3626 LocationSummary* summary = new (zone) |
| 3678 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3627 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3679 summary->set_in(0, Location::RequiresFpuRegister()); | 3628 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3680 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 3629 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
| 3681 summary->set_temp(0, Location::RequiresRegister()); | 3630 summary->set_temp(0, Location::RequiresRegister()); |
| 3682 } | 3631 } |
| 3683 summary->set_out(0, Location::RequiresRegister()); | 3632 summary->set_out(0, Location::RequiresRegister()); |
| 3684 return summary; | 3633 return summary; |
| 3685 } | 3634 } |
| 3686 | 3635 |
| 3687 | 3636 |
| 3688 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 3637 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 3711 ASSERT(compiler->is_optimizing()); | 3660 ASSERT(compiler->is_optimizing()); |
| 3712 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3661 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 3713 Condition true_condition = EmitComparisonCode(compiler, labels); | 3662 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3714 EmitBranchOnCondition(compiler, true_condition, labels); | 3663 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3715 } | 3664 } |
| 3716 | 3665 |
| 3717 | 3666 |
| 3718 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3667 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3719 ASSERT(compiler->is_optimizing()); | 3668 ASSERT(compiler->is_optimizing()); |
| 3720 Label is_true, is_false; | 3669 Label is_true, is_false; |
| 3721 BranchLabels labels = { &is_true, &is_false, &is_false }; | 3670 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 3722 Condition true_condition = EmitComparisonCode(compiler, labels); | 3671 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3723 const Register result = locs()->out(0).reg(); | 3672 const Register result = locs()->out(0).reg(); |
| 3724 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { | 3673 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { |
| 3725 __ LoadObject(result, Bool::False()); | 3674 __ LoadObject(result, Bool::False()); |
| 3726 __ LoadObject(TMP, Bool::True()); | 3675 __ LoadObject(TMP, Bool::True()); |
| 3727 __ csel(result, TMP, result, true_condition); | 3676 __ csel(result, TMP, result, true_condition); |
| 3728 } else { | 3677 } else { |
| 3729 __ LoadObject(result, Bool::False()); | 3678 __ LoadObject(result, Bool::False()); |
| 3730 __ LoadObject(TMP, Bool::True()); | 3679 __ LoadObject(TMP, Bool::True()); |
| 3731 __ csel(result, TMP, result, true_condition); | 3680 __ csel(result, TMP, result, true_condition); |
| 3732 } | 3681 } |
| 3733 } | 3682 } |
| 3734 | 3683 |
| 3735 | 3684 |
| 3736 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 3685 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 3737 bool opt) const { | 3686 bool opt) const { |
| 3738 const intptr_t kNumInputs = 2; | 3687 const intptr_t kNumInputs = 2; |
| 3739 const intptr_t kNumTemps = 0; | 3688 const intptr_t kNumTemps = 0; |
| 3740 LocationSummary* summary = new(zone) LocationSummary( | 3689 LocationSummary* summary = new (zone) |
| 3741 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3690 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3742 summary->set_in(0, Location::RequiresFpuRegister()); | 3691 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3743 summary->set_in(1, Location::RequiresFpuRegister()); | 3692 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3744 summary->set_out(0, Location::RequiresFpuRegister()); | 3693 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3745 return summary; | 3694 return summary; |
| 3746 } | 3695 } |
| 3747 | 3696 |
| 3748 | 3697 |
| 3749 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3698 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3750 const VRegister left = locs()->in(0).fpu_reg(); | 3699 const VRegister left = locs()->in(0).fpu_reg(); |
| 3751 const VRegister right = locs()->in(1).fpu_reg(); | 3700 const VRegister right = locs()->in(1).fpu_reg(); |
| 3752 const VRegister result = locs()->out(0).fpu_reg(); | 3701 const VRegister result = locs()->out(0).fpu_reg(); |
| 3753 | 3702 |
| 3754 switch (op_kind()) { | 3703 switch (op_kind()) { |
| 3755 case Token::kADD: __ vadds(result, left, right); break; | 3704 case Token::kADD: |
| 3756 case Token::kSUB: __ vsubs(result, left, right); break; | 3705 __ vadds(result, left, right); |
| 3757 case Token::kMUL: __ vmuls(result, left, right); break; | 3706 break; |
| 3758 case Token::kDIV: __ vdivs(result, left, right); break; | 3707 case Token::kSUB: |
| 3759 default: UNREACHABLE(); | 3708 __ vsubs(result, left, right); |
| 3709 break; |
| 3710 case Token::kMUL: |
| 3711 __ vmuls(result, left, right); |
| 3712 break; |
| 3713 case Token::kDIV: |
| 3714 __ vdivs(result, left, right); |
| 3715 break; |
| 3716 default: |
| 3717 UNREACHABLE(); |
| 3760 } | 3718 } |
| 3761 } | 3719 } |
| 3762 | 3720 |
| 3763 | 3721 |
| 3764 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, | 3722 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, |
| 3765 bool opt) const { | 3723 bool opt) const { |
| 3766 const intptr_t kNumInputs = 2; | 3724 const intptr_t kNumInputs = 2; |
| 3767 const intptr_t kNumTemps = 0; | 3725 const intptr_t kNumTemps = 0; |
| 3768 LocationSummary* summary = new(zone) LocationSummary( | 3726 LocationSummary* summary = new (zone) |
| 3769 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3727 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3770 summary->set_in(0, Location::RequiresFpuRegister()); | 3728 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3771 summary->set_in(1, Location::RequiresFpuRegister()); | 3729 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3772 summary->set_out(0, Location::RequiresFpuRegister()); | 3730 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3773 return summary; | 3731 return summary; |
| 3774 } | 3732 } |
| 3775 | 3733 |
| 3776 | 3734 |
| 3777 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3735 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3778 const VRegister left = locs()->in(0).fpu_reg(); | 3736 const VRegister left = locs()->in(0).fpu_reg(); |
| 3779 const VRegister right = locs()->in(1).fpu_reg(); | 3737 const VRegister right = locs()->in(1).fpu_reg(); |
| 3780 const VRegister result = locs()->out(0).fpu_reg(); | 3738 const VRegister result = locs()->out(0).fpu_reg(); |
| 3781 | 3739 |
| 3782 switch (op_kind()) { | 3740 switch (op_kind()) { |
| 3783 case Token::kADD: __ vaddd(result, left, right); break; | 3741 case Token::kADD: |
| 3784 case Token::kSUB: __ vsubd(result, left, right); break; | 3742 __ vaddd(result, left, right); |
| 3785 case Token::kMUL: __ vmuld(result, left, right); break; | 3743 break; |
| 3786 case Token::kDIV: __ vdivd(result, left, right); break; | 3744 case Token::kSUB: |
| 3787 default: UNREACHABLE(); | 3745 __ vsubd(result, left, right); |
| 3746 break; |
| 3747 case Token::kMUL: |
| 3748 __ vmuld(result, left, right); |
| 3749 break; |
| 3750 case Token::kDIV: |
| 3751 __ vdivd(result, left, right); |
| 3752 break; |
| 3753 default: |
| 3754 UNREACHABLE(); |
| 3788 } | 3755 } |
| 3789 } | 3756 } |
| 3790 | 3757 |
| 3791 | 3758 |
| 3792 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, | 3759 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 3793 bool opt) const { | 3760 bool opt) const { |
| 3794 const intptr_t kNumInputs = 1; | 3761 const intptr_t kNumInputs = 1; |
| 3795 const intptr_t kNumTemps = 0; | 3762 const intptr_t kNumTemps = 0; |
| 3796 LocationSummary* summary = new LocationSummary( | 3763 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 3797 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3764 LocationSummary::kNoCall); |
| 3798 summary->set_in(0, Location::RequiresFpuRegister()); | 3765 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3799 summary->set_out(0, Location::RequiresFpuRegister()); | 3766 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3800 return summary; | 3767 return summary; |
| 3801 } | 3768 } |
| 3802 | 3769 |
| 3803 | 3770 |
| 3804 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3771 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3805 const VRegister value = locs()->in(0).fpu_reg(); | 3772 const VRegister value = locs()->in(0).fpu_reg(); |
| 3806 const VRegister result = locs()->out(0).fpu_reg(); | 3773 const VRegister result = locs()->out(0).fpu_reg(); |
| 3807 | 3774 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3823 __ fcvtds(result, result); | 3790 __ fcvtds(result, result); |
| 3824 break; | 3791 break; |
| 3825 case MethodRecognizer::kInt32x4Shuffle: | 3792 case MethodRecognizer::kInt32x4Shuffle: |
| 3826 case MethodRecognizer::kFloat32x4Shuffle: | 3793 case MethodRecognizer::kFloat32x4Shuffle: |
| 3827 if (mask_ == 0x00) { | 3794 if (mask_ == 0x00) { |
| 3828 __ vdups(result, value, 0); | 3795 __ vdups(result, value, 0); |
| 3829 } else if (mask_ == 0x55) { | 3796 } else if (mask_ == 0x55) { |
| 3830 __ vdups(result, value, 1); | 3797 __ vdups(result, value, 1); |
| 3831 } else if (mask_ == 0xAA) { | 3798 } else if (mask_ == 0xAA) { |
| 3832 __ vdups(result, value, 2); | 3799 __ vdups(result, value, 2); |
| 3833 } else if (mask_ == 0xFF) { | 3800 } else if (mask_ == 0xFF) { |
| 3834 __ vdups(result, value, 3); | 3801 __ vdups(result, value, 3); |
| 3835 } else { | 3802 } else { |
| 3836 __ vinss(result, 0, value, mask_ & 0x3); | 3803 __ vinss(result, 0, value, mask_ & 0x3); |
| 3837 __ vinss(result, 1, value, (mask_ >> 2) & 0x3); | 3804 __ vinss(result, 1, value, (mask_ >> 2) & 0x3); |
| 3838 __ vinss(result, 2, value, (mask_ >> 4) & 0x3); | 3805 __ vinss(result, 2, value, (mask_ >> 4) & 0x3); |
| 3839 __ vinss(result, 3, value, (mask_ >> 6) & 0x3); | 3806 __ vinss(result, 3, value, (mask_ >> 6) & 0x3); |
| 3840 } | 3807 } |
| 3841 break; | 3808 break; |
| 3842 default: UNREACHABLE(); | 3809 default: |
| 3810 UNREACHABLE(); |
| 3843 } | 3811 } |
| 3844 } | 3812 } |
| 3845 | 3813 |
| 3846 | 3814 |
| 3847 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 3815 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |
| 3848 bool opt) const { | 3816 bool opt) const { |
| 3849 const intptr_t kNumInputs = 2; | 3817 const intptr_t kNumInputs = 2; |
| 3850 const intptr_t kNumTemps = 0; | 3818 const intptr_t kNumTemps = 0; |
| 3851 LocationSummary* summary = new LocationSummary( | 3819 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 3852 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3820 LocationSummary::kNoCall); |
| 3853 summary->set_in(0, Location::RequiresFpuRegister()); | 3821 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3854 summary->set_in(1, Location::RequiresFpuRegister()); | 3822 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3855 summary->set_out(0, Location::RequiresFpuRegister()); | 3823 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3856 return summary; | 3824 return summary; |
| 3857 } | 3825 } |
| 3858 | 3826 |
| 3859 | 3827 |
| 3860 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3828 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3861 const VRegister left = locs()->in(0).fpu_reg(); | 3829 const VRegister left = locs()->in(0).fpu_reg(); |
| 3862 const VRegister right = locs()->in(1).fpu_reg(); | 3830 const VRegister right = locs()->in(1).fpu_reg(); |
| 3863 const VRegister result = locs()->out(0).fpu_reg(); | 3831 const VRegister result = locs()->out(0).fpu_reg(); |
| 3864 | 3832 |
| 3865 switch (op_kind()) { | 3833 switch (op_kind()) { |
| 3866 case MethodRecognizer::kFloat32x4ShuffleMix: | 3834 case MethodRecognizer::kFloat32x4ShuffleMix: |
| 3867 case MethodRecognizer::kInt32x4ShuffleMix: | 3835 case MethodRecognizer::kInt32x4ShuffleMix: |
| 3868 __ vinss(result, 0, left, mask_ & 0x3); | 3836 __ vinss(result, 0, left, mask_ & 0x3); |
| 3869 __ vinss(result, 1, left, (mask_ >> 2) & 0x3); | 3837 __ vinss(result, 1, left, (mask_ >> 2) & 0x3); |
| 3870 __ vinss(result, 2, right, (mask_ >> 4) & 0x3); | 3838 __ vinss(result, 2, right, (mask_ >> 4) & 0x3); |
| 3871 __ vinss(result, 3, right, (mask_ >> 6) & 0x3); | 3839 __ vinss(result, 3, right, (mask_ >> 6) & 0x3); |
| 3872 break; | 3840 break; |
| 3873 default: UNREACHABLE(); | 3841 default: |
| 3842 UNREACHABLE(); |
| 3874 } | 3843 } |
| 3875 } | 3844 } |
| 3876 | 3845 |
| 3877 | 3846 |
| 3878 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, | 3847 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, |
| 3879 bool opt) const { | 3848 bool opt) const { |
| 3880 const intptr_t kNumInputs = 1; | 3849 const intptr_t kNumInputs = 1; |
| 3881 const intptr_t kNumTemps = 1; | 3850 const intptr_t kNumTemps = 1; |
| 3882 LocationSummary* summary = new LocationSummary( | 3851 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 3883 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3852 LocationSummary::kNoCall); |
| 3884 summary->set_in(0, Location::RequiresFpuRegister()); | 3853 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3885 summary->set_temp(0, Location::RequiresRegister()); | 3854 summary->set_temp(0, Location::RequiresRegister()); |
| 3886 summary->set_out(0, Location::RequiresRegister()); | 3855 summary->set_out(0, Location::RequiresRegister()); |
| 3887 return summary; | 3856 return summary; |
| 3888 } | 3857 } |
| 3889 | 3858 |
| 3890 | 3859 |
| 3891 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3860 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3892 const VRegister value = locs()->in(0).fpu_reg(); | 3861 const VRegister value = locs()->in(0).fpu_reg(); |
| 3893 const Register out = locs()->out(0).reg(); | 3862 const Register out = locs()->out(0).reg(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3907 // W lane. | 3876 // W lane. |
| 3908 __ vmovrs(temp, value, 3); | 3877 __ vmovrs(temp, value, 3); |
| 3909 __ LsrImmediate(temp, temp, 31); | 3878 __ LsrImmediate(temp, temp, 31); |
| 3910 __ orr(out, out, Operand(temp, LSL, 3)); | 3879 __ orr(out, out, Operand(temp, LSL, 3)); |
| 3911 // Tag. | 3880 // Tag. |
| 3912 __ SmiTag(out); | 3881 __ SmiTag(out); |
| 3913 } | 3882 } |
| 3914 | 3883 |
| 3915 | 3884 |
| 3916 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 3885 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
| 3917 Zone* zone, bool opt) const { | 3886 Zone* zone, |
| 3887 bool opt) const { |
| 3918 const intptr_t kNumInputs = 4; | 3888 const intptr_t kNumInputs = 4; |
| 3919 const intptr_t kNumTemps = 0; | 3889 const intptr_t kNumTemps = 0; |
| 3920 LocationSummary* summary = new(zone) LocationSummary( | 3890 LocationSummary* summary = new (zone) |
| 3921 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3891 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3922 summary->set_in(0, Location::RequiresFpuRegister()); | 3892 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3923 summary->set_in(1, Location::RequiresFpuRegister()); | 3893 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3924 summary->set_in(2, Location::RequiresFpuRegister()); | 3894 summary->set_in(2, Location::RequiresFpuRegister()); |
| 3925 summary->set_in(3, Location::RequiresFpuRegister()); | 3895 summary->set_in(3, Location::RequiresFpuRegister()); |
| 3926 summary->set_out(0, Location::RequiresFpuRegister()); | 3896 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3927 return summary; | 3897 return summary; |
| 3928 } | 3898 } |
| 3929 | 3899 |
| 3930 | 3900 |
| 3931 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3901 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3943 __ vinss(r, 2, VTMP, 0); | 3913 __ vinss(r, 2, VTMP, 0); |
| 3944 __ fcvtsd(VTMP, v3); | 3914 __ fcvtsd(VTMP, v3); |
| 3945 __ vinss(r, 3, VTMP, 0); | 3915 __ vinss(r, 3, VTMP, 0); |
| 3946 } | 3916 } |
| 3947 | 3917 |
| 3948 | 3918 |
| 3949 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, | 3919 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, |
| 3950 bool opt) const { | 3920 bool opt) const { |
| 3951 const intptr_t kNumInputs = 0; | 3921 const intptr_t kNumInputs = 0; |
| 3952 const intptr_t kNumTemps = 0; | 3922 const intptr_t kNumTemps = 0; |
| 3953 LocationSummary* summary = new(zone) LocationSummary( | 3923 LocationSummary* summary = new (zone) |
| 3954 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3924 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3955 summary->set_out(0, Location::RequiresFpuRegister()); | 3925 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3956 return summary; | 3926 return summary; |
| 3957 } | 3927 } |
| 3958 | 3928 |
| 3959 | 3929 |
| 3960 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3930 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3961 const VRegister v = locs()->out(0).fpu_reg(); | 3931 const VRegister v = locs()->out(0).fpu_reg(); |
| 3962 __ veor(v, v, v); | 3932 __ veor(v, v, v); |
| 3963 } | 3933 } |
| 3964 | 3934 |
| 3965 | 3935 |
| 3966 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, | 3936 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, |
| 3967 bool opt) const { | 3937 bool opt) const { |
| 3968 const intptr_t kNumInputs = 1; | 3938 const intptr_t kNumInputs = 1; |
| 3969 const intptr_t kNumTemps = 0; | 3939 const intptr_t kNumTemps = 0; |
| 3970 LocationSummary* summary = new(zone) LocationSummary( | 3940 LocationSummary* summary = new (zone) |
| 3971 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3941 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3972 summary->set_in(0, Location::RequiresFpuRegister()); | 3942 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3973 summary->set_out(0, Location::RequiresFpuRegister()); | 3943 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3974 return summary; | 3944 return summary; |
| 3975 } | 3945 } |
| 3976 | 3946 |
| 3977 | 3947 |
| 3978 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3948 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3979 const VRegister value = locs()->in(0).fpu_reg(); | 3949 const VRegister value = locs()->in(0).fpu_reg(); |
| 3980 const VRegister result = locs()->out(0).fpu_reg(); | 3950 const VRegister result = locs()->out(0).fpu_reg(); |
| 3981 | 3951 |
| 3982 // Convert to Float32. | 3952 // Convert to Float32. |
| 3983 __ fcvtsd(VTMP, value); | 3953 __ fcvtsd(VTMP, value); |
| 3984 | 3954 |
| 3985 // Splat across all lanes. | 3955 // Splat across all lanes. |
| 3986 __ vdups(result, VTMP, 0); | 3956 __ vdups(result, VTMP, 0); |
| 3987 } | 3957 } |
| 3988 | 3958 |
| 3989 | 3959 |
| 3990 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, | 3960 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, |
| 3991 bool opt) const { | 3961 bool opt) const { |
| 3992 const intptr_t kNumInputs = 2; | 3962 const intptr_t kNumInputs = 2; |
| 3993 const intptr_t kNumTemps = 0; | 3963 const intptr_t kNumTemps = 0; |
| 3994 LocationSummary* summary = new(zone) LocationSummary( | 3964 LocationSummary* summary = new (zone) |
| 3995 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3965 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3996 summary->set_in(0, Location::RequiresFpuRegister()); | 3966 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3997 summary->set_in(1, Location::RequiresFpuRegister()); | 3967 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3998 summary->set_out(0, Location::RequiresFpuRegister()); | 3968 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3999 return summary; | 3969 return summary; |
| 4000 } | 3970 } |
| 4001 | 3971 |
| 4002 | 3972 |
| 4003 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3973 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4004 const VRegister left = locs()->in(0).fpu_reg(); | 3974 const VRegister left = locs()->in(0).fpu_reg(); |
| 4005 const VRegister right = locs()->in(1).fpu_reg(); | 3975 const VRegister right = locs()->in(1).fpu_reg(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4020 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: | 3990 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: |
| 4021 __ vcges(result, left, right); | 3991 __ vcges(result, left, right); |
| 4022 break; | 3992 break; |
| 4023 case MethodRecognizer::kFloat32x4LessThan: | 3993 case MethodRecognizer::kFloat32x4LessThan: |
| 4024 __ vcgts(result, right, left); | 3994 __ vcgts(result, right, left); |
| 4025 break; | 3995 break; |
| 4026 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 3996 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
| 4027 __ vcges(result, right, left); | 3997 __ vcges(result, right, left); |
| 4028 break; | 3998 break; |
| 4029 | 3999 |
| 4030 default: UNREACHABLE(); | 4000 default: |
| 4001 UNREACHABLE(); |
| 4031 } | 4002 } |
| 4032 } | 4003 } |
| 4033 | 4004 |
| 4034 | 4005 |
| 4035 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, | 4006 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, |
| 4036 bool opt) const { | 4007 bool opt) const { |
| 4037 const intptr_t kNumInputs = 2; | 4008 const intptr_t kNumInputs = 2; |
| 4038 const intptr_t kNumTemps = 0; | 4009 const intptr_t kNumTemps = 0; |
| 4039 LocationSummary* summary = new(zone) LocationSummary( | 4010 LocationSummary* summary = new (zone) |
| 4040 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4011 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4041 summary->set_in(0, Location::RequiresFpuRegister()); | 4012 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4042 summary->set_in(1, Location::RequiresFpuRegister()); | 4013 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4043 summary->set_out(0, Location::RequiresFpuRegister()); | 4014 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4044 return summary; | 4015 return summary; |
| 4045 } | 4016 } |
| 4046 | 4017 |
| 4047 | 4018 |
| 4048 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4019 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4049 const VRegister left = locs()->in(0).fpu_reg(); | 4020 const VRegister left = locs()->in(0).fpu_reg(); |
| 4050 const VRegister right = locs()->in(1).fpu_reg(); | 4021 const VRegister right = locs()->in(1).fpu_reg(); |
| 4051 const VRegister result = locs()->out(0).fpu_reg(); | 4022 const VRegister result = locs()->out(0).fpu_reg(); |
| 4052 | 4023 |
| 4053 switch (op_kind()) { | 4024 switch (op_kind()) { |
| 4054 case MethodRecognizer::kFloat32x4Min: | 4025 case MethodRecognizer::kFloat32x4Min: |
| 4055 __ vmins(result, left, right); | 4026 __ vmins(result, left, right); |
| 4056 break; | 4027 break; |
| 4057 case MethodRecognizer::kFloat32x4Max: | 4028 case MethodRecognizer::kFloat32x4Max: |
| 4058 __ vmaxs(result, left, right); | 4029 __ vmaxs(result, left, right); |
| 4059 break; | 4030 break; |
| 4060 default: UNREACHABLE(); | 4031 default: |
| 4032 UNREACHABLE(); |
| 4061 } | 4033 } |
| 4062 } | 4034 } |
| 4063 | 4035 |
| 4064 | 4036 |
| 4065 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, | 4037 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, |
| 4066 bool opt) const { | 4038 bool opt) const { |
| 4067 const intptr_t kNumInputs = 1; | 4039 const intptr_t kNumInputs = 1; |
| 4068 const intptr_t kNumTemps = 0; | 4040 const intptr_t kNumTemps = 0; |
| 4069 LocationSummary* summary = new(zone) LocationSummary( | 4041 LocationSummary* summary = new (zone) |
| 4070 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4042 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4071 summary->set_in(0, Location::RequiresFpuRegister()); | 4043 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4072 summary->set_out(0, Location::RequiresFpuRegister()); | 4044 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4073 return summary; | 4045 return summary; |
| 4074 } | 4046 } |
| 4075 | 4047 |
| 4076 | 4048 |
| 4077 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4049 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4078 const VRegister left = locs()->in(0).fpu_reg(); | 4050 const VRegister left = locs()->in(0).fpu_reg(); |
| 4079 const VRegister result = locs()->out(0).fpu_reg(); | 4051 const VRegister result = locs()->out(0).fpu_reg(); |
| 4080 | 4052 |
| 4081 switch (op_kind()) { | 4053 switch (op_kind()) { |
| 4082 case MethodRecognizer::kFloat32x4Sqrt: | 4054 case MethodRecognizer::kFloat32x4Sqrt: |
| 4083 __ vsqrts(result, left); | 4055 __ vsqrts(result, left); |
| 4084 break; | 4056 break; |
| 4085 case MethodRecognizer::kFloat32x4Reciprocal: | 4057 case MethodRecognizer::kFloat32x4Reciprocal: |
| 4086 __ VRecps(result, left); | 4058 __ VRecps(result, left); |
| 4087 break; | 4059 break; |
| 4088 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 4060 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
| 4089 __ VRSqrts(result, left); | 4061 __ VRSqrts(result, left); |
| 4090 break; | 4062 break; |
| 4091 default: UNREACHABLE(); | 4063 default: |
| 4064 UNREACHABLE(); |
| 4092 } | 4065 } |
| 4093 } | 4066 } |
| 4094 | 4067 |
| 4095 | 4068 |
| 4096 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, | 4069 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, |
| 4097 bool opt) const { | 4070 bool opt) const { |
| 4098 const intptr_t kNumInputs = 2; | 4071 const intptr_t kNumInputs = 2; |
| 4099 const intptr_t kNumTemps = 0; | 4072 const intptr_t kNumTemps = 0; |
| 4100 LocationSummary* summary = new(zone) LocationSummary( | 4073 LocationSummary* summary = new (zone) |
| 4101 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4074 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4102 summary->set_in(0, Location::RequiresFpuRegister()); | 4075 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4103 summary->set_in(1, Location::RequiresFpuRegister()); | 4076 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4104 summary->set_out(0, Location::RequiresFpuRegister()); | 4077 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4105 return summary; | 4078 return summary; |
| 4106 } | 4079 } |
| 4107 | 4080 |
| 4108 | 4081 |
| 4109 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4082 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4110 const VRegister left = locs()->in(0).fpu_reg(); | 4083 const VRegister left = locs()->in(0).fpu_reg(); |
| 4111 const VRegister right = locs()->in(1).fpu_reg(); | 4084 const VRegister right = locs()->in(1).fpu_reg(); |
| 4112 const VRegister result = locs()->out(0).fpu_reg(); | 4085 const VRegister result = locs()->out(0).fpu_reg(); |
| 4113 | 4086 |
| 4114 switch (op_kind()) { | 4087 switch (op_kind()) { |
| 4115 case MethodRecognizer::kFloat32x4Scale: | 4088 case MethodRecognizer::kFloat32x4Scale: |
| 4116 __ fcvtsd(VTMP, left); | 4089 __ fcvtsd(VTMP, left); |
| 4117 __ vdups(result, VTMP, 0); | 4090 __ vdups(result, VTMP, 0); |
| 4118 __ vmuls(result, result, right); | 4091 __ vmuls(result, result, right); |
| 4119 break; | 4092 break; |
| 4120 default: UNREACHABLE(); | 4093 default: |
| 4094 UNREACHABLE(); |
| 4121 } | 4095 } |
| 4122 } | 4096 } |
| 4123 | 4097 |
| 4124 | 4098 |
| 4125 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4099 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, |
| 4126 bool opt) const { | 4100 bool opt) const { |
| 4127 const intptr_t kNumInputs = 1; | 4101 const intptr_t kNumInputs = 1; |
| 4128 const intptr_t kNumTemps = 0; | 4102 const intptr_t kNumTemps = 0; |
| 4129 LocationSummary* summary = new LocationSummary( | 4103 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4130 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4104 LocationSummary::kNoCall); |
| 4131 summary->set_in(0, Location::RequiresFpuRegister()); | 4105 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4132 summary->set_out(0, Location::RequiresFpuRegister()); | 4106 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4133 return summary; | 4107 return summary; |
| 4134 } | 4108 } |
| 4135 | 4109 |
| 4136 | 4110 |
| 4137 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4111 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4138 const VRegister left = locs()->in(0).fpu_reg(); | 4112 const VRegister left = locs()->in(0).fpu_reg(); |
| 4139 const VRegister result = locs()->out(0).fpu_reg(); | 4113 const VRegister result = locs()->out(0).fpu_reg(); |
| 4140 | 4114 |
| 4141 switch (op_kind()) { | 4115 switch (op_kind()) { |
| 4142 case MethodRecognizer::kFloat32x4Negate: | 4116 case MethodRecognizer::kFloat32x4Negate: |
| 4143 __ vnegs(result, left); | 4117 __ vnegs(result, left); |
| 4144 break; | 4118 break; |
| 4145 case MethodRecognizer::kFloat32x4Absolute: | 4119 case MethodRecognizer::kFloat32x4Absolute: |
| 4146 __ vabss(result, left); | 4120 __ vabss(result, left); |
| 4147 break; | 4121 break; |
| 4148 default: UNREACHABLE(); | 4122 default: |
| 4123 UNREACHABLE(); |
| 4149 } | 4124 } |
| 4150 } | 4125 } |
| 4151 | 4126 |
| 4152 | 4127 |
| 4153 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, | 4128 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, |
| 4154 bool opt) const { | 4129 bool opt) const { |
| 4155 const intptr_t kNumInputs = 3; | 4130 const intptr_t kNumInputs = 3; |
| 4156 const intptr_t kNumTemps = 0; | 4131 const intptr_t kNumTemps = 0; |
| 4157 LocationSummary* summary = new(zone) LocationSummary( | 4132 LocationSummary* summary = new (zone) |
| 4158 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4133 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4159 summary->set_in(0, Location::RequiresFpuRegister()); | 4134 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4160 summary->set_in(1, Location::RequiresFpuRegister()); | 4135 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4161 summary->set_in(2, Location::RequiresFpuRegister()); | 4136 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4162 summary->set_out(0, Location::RequiresFpuRegister()); | 4137 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4163 return summary; | 4138 return summary; |
| 4164 } | 4139 } |
| 4165 | 4140 |
| 4166 | 4141 |
| 4167 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4142 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4168 const VRegister left = locs()->in(0).fpu_reg(); | 4143 const VRegister left = locs()->in(0).fpu_reg(); |
| 4169 const VRegister lower = locs()->in(1).fpu_reg(); | 4144 const VRegister lower = locs()->in(1).fpu_reg(); |
| 4170 const VRegister upper = locs()->in(2).fpu_reg(); | 4145 const VRegister upper = locs()->in(2).fpu_reg(); |
| 4171 const VRegister result = locs()->out(0).fpu_reg(); | 4146 const VRegister result = locs()->out(0).fpu_reg(); |
| 4172 __ vmins(result, left, upper); | 4147 __ vmins(result, left, upper); |
| 4173 __ vmaxs(result, result, lower); | 4148 __ vmaxs(result, result, lower); |
| 4174 } | 4149 } |
| 4175 | 4150 |
| 4176 | 4151 |
| 4177 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, | 4152 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, |
| 4178 bool opt) const { | 4153 bool opt) const { |
| 4179 const intptr_t kNumInputs = 2; | 4154 const intptr_t kNumInputs = 2; |
| 4180 const intptr_t kNumTemps = 0; | 4155 const intptr_t kNumTemps = 0; |
| 4181 LocationSummary* summary = new LocationSummary( | 4156 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4182 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4157 LocationSummary::kNoCall); |
| 4183 summary->set_in(0, Location::RequiresFpuRegister()); | 4158 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4184 summary->set_in(1, Location::RequiresFpuRegister()); | 4159 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4185 summary->set_out(0, Location::RequiresFpuRegister()); | 4160 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4186 return summary; | 4161 return summary; |
| 4187 } | 4162 } |
| 4188 | 4163 |
| 4189 | 4164 |
| 4190 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4165 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4191 const VRegister replacement = locs()->in(0).fpu_reg(); | 4166 const VRegister replacement = locs()->in(0).fpu_reg(); |
| 4192 const VRegister value = locs()->in(1).fpu_reg(); | 4167 const VRegister value = locs()->in(1).fpu_reg(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4203 break; | 4178 break; |
| 4204 case MethodRecognizer::kFloat32x4WithY: | 4179 case MethodRecognizer::kFloat32x4WithY: |
| 4205 __ vinss(result, 1, VTMP, 0); | 4180 __ vinss(result, 1, VTMP, 0); |
| 4206 break; | 4181 break; |
| 4207 case MethodRecognizer::kFloat32x4WithZ: | 4182 case MethodRecognizer::kFloat32x4WithZ: |
| 4208 __ vinss(result, 2, VTMP, 0); | 4183 __ vinss(result, 2, VTMP, 0); |
| 4209 break; | 4184 break; |
| 4210 case MethodRecognizer::kFloat32x4WithW: | 4185 case MethodRecognizer::kFloat32x4WithW: |
| 4211 __ vinss(result, 3, VTMP, 0); | 4186 __ vinss(result, 3, VTMP, 0); |
| 4212 break; | 4187 break; |
| 4213 default: UNREACHABLE(); | 4188 default: |
| 4189 UNREACHABLE(); |
| 4214 } | 4190 } |
| 4215 } | 4191 } |
| 4216 | 4192 |
| 4217 | 4193 |
| 4218 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, | 4194 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, |
| 4219 bool opt) const { | 4195 bool opt) const { |
| 4220 const intptr_t kNumInputs = 1; | 4196 const intptr_t kNumInputs = 1; |
| 4221 const intptr_t kNumTemps = 0; | 4197 const intptr_t kNumTemps = 0; |
| 4222 LocationSummary* summary = new LocationSummary( | 4198 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4223 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4199 LocationSummary::kNoCall); |
| 4224 summary->set_in(0, Location::RequiresFpuRegister()); | 4200 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4225 summary->set_out(0, Location::RequiresFpuRegister()); | 4201 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4226 return summary; | 4202 return summary; |
| 4227 } | 4203 } |
| 4228 | 4204 |
| 4229 | 4205 |
| 4230 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4206 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4231 const VRegister value = locs()->in(0).fpu_reg(); | 4207 const VRegister value = locs()->in(0).fpu_reg(); |
| 4232 const VRegister result = locs()->out(0).fpu_reg(); | 4208 const VRegister result = locs()->out(0).fpu_reg(); |
| 4233 | 4209 |
| 4234 if (value != result) { | 4210 if (value != result) { |
| 4235 __ vmov(result, value); | 4211 __ vmov(result, value); |
| 4236 } | 4212 } |
| 4237 } | 4213 } |
| 4238 | 4214 |
| 4239 | 4215 |
| 4240 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 4216 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 4241 bool opt) const { | 4217 bool opt) const { |
| 4242 const intptr_t kNumInputs = 1; | 4218 const intptr_t kNumInputs = 1; |
| 4243 const intptr_t kNumTemps = 0; | 4219 const intptr_t kNumTemps = 0; |
| 4244 LocationSummary* summary = new(zone) LocationSummary( | 4220 LocationSummary* summary = new (zone) |
| 4245 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4221 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4246 summary->set_in(0, Location::RequiresFpuRegister()); | 4222 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4247 summary->set_out(0, Location::RequiresFpuRegister()); | 4223 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4248 return summary; | 4224 return summary; |
| 4249 } | 4225 } |
| 4250 | 4226 |
| 4251 | 4227 |
| 4252 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4228 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4253 const VRegister value = locs()->in(0).fpu_reg(); | 4229 const VRegister value = locs()->in(0).fpu_reg(); |
| 4254 const VRegister result = locs()->out(0).fpu_reg(); | 4230 const VRegister result = locs()->out(0).fpu_reg(); |
| 4255 | 4231 |
| 4256 switch (op_kind()) { | 4232 switch (op_kind()) { |
| 4257 case MethodRecognizer::kFloat64x2GetX: | 4233 case MethodRecognizer::kFloat64x2GetX: |
| 4258 __ vinsd(result, 0, value, 0); | 4234 __ vinsd(result, 0, value, 0); |
| 4259 break; | 4235 break; |
| 4260 case MethodRecognizer::kFloat64x2GetY: | 4236 case MethodRecognizer::kFloat64x2GetY: |
| 4261 __ vinsd(result, 0, value, 1); | 4237 __ vinsd(result, 0, value, 1); |
| 4262 break; | 4238 break; |
| 4263 default: UNREACHABLE(); | 4239 default: |
| 4240 UNREACHABLE(); |
| 4264 } | 4241 } |
| 4265 } | 4242 } |
| 4266 | 4243 |
| 4267 | 4244 |
| 4268 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 4245 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |
| 4269 bool opt) const { | 4246 bool opt) const { |
| 4270 const intptr_t kNumInputs = 0; | 4247 const intptr_t kNumInputs = 0; |
| 4271 const intptr_t kNumTemps = 0; | 4248 const intptr_t kNumTemps = 0; |
| 4272 LocationSummary* summary = new(zone) LocationSummary( | 4249 LocationSummary* summary = new (zone) |
| 4273 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4250 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4274 summary->set_out(0, Location::RequiresFpuRegister()); | 4251 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4275 return summary; | 4252 return summary; |
| 4276 } | 4253 } |
| 4277 | 4254 |
| 4278 | 4255 |
| 4279 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4256 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4280 const VRegister v = locs()->out(0).fpu_reg(); | 4257 const VRegister v = locs()->out(0).fpu_reg(); |
| 4281 __ veor(v, v, v); | 4258 __ veor(v, v, v); |
| 4282 } | 4259 } |
| 4283 | 4260 |
| 4284 | 4261 |
| 4285 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 4262 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |
| 4286 bool opt) const { | 4263 bool opt) const { |
| 4287 const intptr_t kNumInputs = 1; | 4264 const intptr_t kNumInputs = 1; |
| 4288 const intptr_t kNumTemps = 0; | 4265 const intptr_t kNumTemps = 0; |
| 4289 LocationSummary* summary = new(zone) LocationSummary( | 4266 LocationSummary* summary = new (zone) |
| 4290 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4267 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4291 summary->set_in(0, Location::RequiresFpuRegister()); | 4268 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4292 summary->set_out(0, Location::RequiresFpuRegister()); | 4269 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4293 return summary; | 4270 return summary; |
| 4294 } | 4271 } |
| 4295 | 4272 |
| 4296 | 4273 |
| 4297 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4274 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4298 const VRegister value = locs()->in(0).fpu_reg(); | 4275 const VRegister value = locs()->in(0).fpu_reg(); |
| 4299 const VRegister result = locs()->out(0).fpu_reg(); | 4276 const VRegister result = locs()->out(0).fpu_reg(); |
| 4300 __ vdupd(result, value, 0); | 4277 __ vdupd(result, value, 0); |
| 4301 } | 4278 } |
| 4302 | 4279 |
| 4303 | 4280 |
| 4304 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 4281 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
| 4305 Zone* zone, bool opt) const { | 4282 Zone* zone, |
| 4283 bool opt) const { |
| 4306 const intptr_t kNumInputs = 2; | 4284 const intptr_t kNumInputs = 2; |
| 4307 const intptr_t kNumTemps = 0; | 4285 const intptr_t kNumTemps = 0; |
| 4308 LocationSummary* summary = new(zone) LocationSummary( | 4286 LocationSummary* summary = new (zone) |
| 4309 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4287 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4310 summary->set_in(0, Location::RequiresFpuRegister()); | 4288 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4311 summary->set_in(1, Location::RequiresFpuRegister()); | 4289 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4312 summary->set_out(0, Location::RequiresFpuRegister()); | 4290 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4313 return summary; | 4291 return summary; |
| 4314 } | 4292 } |
| 4315 | 4293 |
| 4316 | 4294 |
| 4317 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4295 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4318 const VRegister v0 = locs()->in(0).fpu_reg(); | 4296 const VRegister v0 = locs()->in(0).fpu_reg(); |
| 4319 const VRegister v1 = locs()->in(1).fpu_reg(); | 4297 const VRegister v1 = locs()->in(1).fpu_reg(); |
| 4320 const VRegister r = locs()->out(0).fpu_reg(); | 4298 const VRegister r = locs()->out(0).fpu_reg(); |
| 4321 __ vinsd(r, 0, v0, 0); | 4299 __ vinsd(r, 0, v0, 0); |
| 4322 __ vinsd(r, 1, v1, 0); | 4300 __ vinsd(r, 1, v1, 0); |
| 4323 } | 4301 } |
| 4324 | 4302 |
| 4325 | 4303 |
| 4326 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 4304 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
| 4327 Zone* zone, bool opt) const { | 4305 Zone* zone, |
| 4306 bool opt) const { |
| 4328 const intptr_t kNumInputs = 1; | 4307 const intptr_t kNumInputs = 1; |
| 4329 const intptr_t kNumTemps = 0; | 4308 const intptr_t kNumTemps = 0; |
| 4330 LocationSummary* summary = new LocationSummary( | 4309 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4331 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4310 LocationSummary::kNoCall); |
| 4332 summary->set_in(0, Location::RequiresFpuRegister()); | 4311 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4333 summary->set_out(0, Location::RequiresFpuRegister()); | 4312 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4334 return summary; | 4313 return summary; |
| 4335 } | 4314 } |
| 4336 | 4315 |
| 4337 | 4316 |
| 4338 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4317 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4339 const VRegister q = locs()->in(0).fpu_reg(); | 4318 const VRegister q = locs()->in(0).fpu_reg(); |
| 4340 const VRegister r = locs()->out(0).fpu_reg(); | 4319 const VRegister r = locs()->out(0).fpu_reg(); |
| 4341 | 4320 |
| 4342 // Zero register. | 4321 // Zero register. |
| 4343 __ veor(r, r, r); | 4322 __ veor(r, r, r); |
| 4344 // Set X lane. | 4323 // Set X lane. |
| 4345 __ vinsd(VTMP, 0, q, 0); | 4324 __ vinsd(VTMP, 0, q, 0); |
| 4346 __ fcvtsd(VTMP, VTMP); | 4325 __ fcvtsd(VTMP, VTMP); |
| 4347 __ vinss(r, 0, VTMP, 0); | 4326 __ vinss(r, 0, VTMP, 0); |
| 4348 // Set Y lane. | 4327 // Set Y lane. |
| 4349 __ vinsd(VTMP, 0, q, 1); | 4328 __ vinsd(VTMP, 0, q, 1); |
| 4350 __ fcvtsd(VTMP, VTMP); | 4329 __ fcvtsd(VTMP, VTMP); |
| 4351 __ vinss(r, 1, VTMP, 0); | 4330 __ vinss(r, 1, VTMP, 0); |
| 4352 } | 4331 } |
| 4353 | 4332 |
| 4354 | 4333 |
| 4355 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 4334 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
| 4356 Zone* zone, bool opt) const { | 4335 Zone* zone, |
| 4336 bool opt) const { |
| 4357 const intptr_t kNumInputs = 1; | 4337 const intptr_t kNumInputs = 1; |
| 4358 const intptr_t kNumTemps = 0; | 4338 const intptr_t kNumTemps = 0; |
| 4359 LocationSummary* summary = new LocationSummary( | 4339 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4360 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4340 LocationSummary::kNoCall); |
| 4361 summary->set_in(0, Location::RequiresFpuRegister()); | 4341 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4362 summary->set_out(0, Location::RequiresFpuRegister()); | 4342 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4363 return summary; | 4343 return summary; |
| 4364 } | 4344 } |
| 4365 | 4345 |
| 4366 | 4346 |
| 4367 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4347 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4368 const VRegister q = locs()->in(0).fpu_reg(); | 4348 const VRegister q = locs()->in(0).fpu_reg(); |
| 4369 const VRegister r = locs()->out(0).fpu_reg(); | 4349 const VRegister r = locs()->out(0).fpu_reg(); |
| 4370 | 4350 |
| 4371 // Set X. | 4351 // Set X. |
| 4372 __ vinss(VTMP, 0, q, 0); | 4352 __ vinss(VTMP, 0, q, 0); |
| 4373 __ fcvtds(VTMP, VTMP); | 4353 __ fcvtds(VTMP, VTMP); |
| 4374 __ vinsd(r, 0, VTMP, 0); | 4354 __ vinsd(r, 0, VTMP, 0); |
| 4375 // Set Y. | 4355 // Set Y. |
| 4376 __ vinss(VTMP, 0, q, 1); | 4356 __ vinss(VTMP, 0, q, 1); |
| 4377 __ fcvtds(VTMP, VTMP); | 4357 __ fcvtds(VTMP, VTMP); |
| 4378 __ vinsd(r, 1, VTMP, 0); | 4358 __ vinsd(r, 1, VTMP, 0); |
| 4379 } | 4359 } |
| 4380 | 4360 |
| 4381 | 4361 |
| 4382 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4362 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, |
| 4383 bool opt) const { | 4363 bool opt) const { |
| 4384 const intptr_t kNumInputs = 1; | 4364 const intptr_t kNumInputs = 1; |
| 4385 const intptr_t kNumTemps = 0; | 4365 const intptr_t kNumTemps = 0; |
| 4386 LocationSummary* summary = new(zone) LocationSummary( | 4366 LocationSummary* summary = new (zone) |
| 4387 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4367 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4388 | 4368 |
| 4389 if (representation() == kTagged) { | 4369 if (representation() == kTagged) { |
| 4390 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 4370 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |
| 4391 summary->set_in(0, Location::RequiresFpuRegister()); | 4371 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4392 summary->set_out(0, Location::RequiresRegister()); | 4372 summary->set_out(0, Location::RequiresRegister()); |
| 4393 } else { | 4373 } else { |
| 4394 summary->set_in(0, Location::RequiresFpuRegister()); | 4374 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4395 summary->set_out(0, Location::RequiresFpuRegister()); | 4375 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4396 } | 4376 } |
| 4397 return summary; | 4377 return summary; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 4421 switch (op_kind()) { | 4401 switch (op_kind()) { |
| 4422 case MethodRecognizer::kFloat64x2Negate: | 4402 case MethodRecognizer::kFloat64x2Negate: |
| 4423 __ vnegd(result, value); | 4403 __ vnegd(result, value); |
| 4424 break; | 4404 break; |
| 4425 case MethodRecognizer::kFloat64x2Abs: | 4405 case MethodRecognizer::kFloat64x2Abs: |
| 4426 __ vabsd(result, value); | 4406 __ vabsd(result, value); |
| 4427 break; | 4407 break; |
| 4428 case MethodRecognizer::kFloat64x2Sqrt: | 4408 case MethodRecognizer::kFloat64x2Sqrt: |
| 4429 __ vsqrtd(result, value); | 4409 __ vsqrtd(result, value); |
| 4430 break; | 4410 break; |
| 4431 default: UNREACHABLE(); | 4411 default: |
| 4412 UNREACHABLE(); |
| 4432 } | 4413 } |
| 4433 } | 4414 } |
| 4434 | 4415 |
| 4435 | 4416 |
| 4436 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, | 4417 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, |
| 4437 bool opt) const { | 4418 bool opt) const { |
| 4438 const intptr_t kNumInputs = 2; | 4419 const intptr_t kNumInputs = 2; |
| 4439 const intptr_t kNumTemps = 0; | 4420 const intptr_t kNumTemps = 0; |
| 4440 LocationSummary* summary = new LocationSummary( | 4421 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4441 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4422 LocationSummary::kNoCall); |
| 4442 summary->set_in(0, Location::RequiresFpuRegister()); | 4423 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4443 summary->set_in(1, Location::RequiresFpuRegister()); | 4424 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4444 summary->set_out(0, Location::SameAsFirstInput()); | 4425 summary->set_out(0, Location::SameAsFirstInput()); |
| 4445 return summary; | 4426 return summary; |
| 4446 } | 4427 } |
| 4447 | 4428 |
| 4448 | 4429 |
| 4449 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4430 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4450 const VRegister left = locs()->in(0).fpu_reg(); | 4431 const VRegister left = locs()->in(0).fpu_reg(); |
| 4451 const VRegister right = locs()->in(1).fpu_reg(); | 4432 const VRegister right = locs()->in(1).fpu_reg(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4462 break; | 4443 break; |
| 4463 case MethodRecognizer::kFloat64x2WithY: | 4444 case MethodRecognizer::kFloat64x2WithY: |
| 4464 __ vinsd(out, 1, right, 0); | 4445 __ vinsd(out, 1, right, 0); |
| 4465 break; | 4446 break; |
| 4466 case MethodRecognizer::kFloat64x2Min: | 4447 case MethodRecognizer::kFloat64x2Min: |
| 4467 __ vmind(out, left, right); | 4448 __ vmind(out, left, right); |
| 4468 break; | 4449 break; |
| 4469 case MethodRecognizer::kFloat64x2Max: | 4450 case MethodRecognizer::kFloat64x2Max: |
| 4470 __ vmaxd(out, left, right); | 4451 __ vmaxd(out, left, right); |
| 4471 break; | 4452 break; |
| 4472 default: UNREACHABLE(); | 4453 default: |
| 4454 UNREACHABLE(); |
| 4473 } | 4455 } |
| 4474 } | 4456 } |
| 4475 | 4457 |
| 4476 | 4458 |
| 4477 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary( | 4459 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, |
| 4478 Zone* zone, bool opt) const { | 4460 bool opt) const { |
| 4479 const intptr_t kNumInputs = 4; | 4461 const intptr_t kNumInputs = 4; |
| 4480 const intptr_t kNumTemps = 0; | 4462 const intptr_t kNumTemps = 0; |
| 4481 LocationSummary* summary = new(zone) LocationSummary( | 4463 LocationSummary* summary = new (zone) |
| 4482 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4464 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4483 summary->set_in(0, Location::RequiresRegister()); | 4465 summary->set_in(0, Location::RequiresRegister()); |
| 4484 summary->set_in(1, Location::RequiresRegister()); | 4466 summary->set_in(1, Location::RequiresRegister()); |
| 4485 summary->set_in(2, Location::RequiresRegister()); | 4467 summary->set_in(2, Location::RequiresRegister()); |
| 4486 summary->set_in(3, Location::RequiresRegister()); | 4468 summary->set_in(3, Location::RequiresRegister()); |
| 4487 summary->set_out(0, Location::RequiresFpuRegister()); | 4469 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4488 return summary; | 4470 return summary; |
| 4489 } | 4471 } |
| 4490 | 4472 |
| 4491 | 4473 |
| 4492 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4474 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4493 const Register v0 = locs()->in(0).reg(); | 4475 const Register v0 = locs()->in(0).reg(); |
| 4494 const Register v1 = locs()->in(1).reg(); | 4476 const Register v1 = locs()->in(1).reg(); |
| 4495 const Register v2 = locs()->in(2).reg(); | 4477 const Register v2 = locs()->in(2).reg(); |
| 4496 const Register v3 = locs()->in(3).reg(); | 4478 const Register v3 = locs()->in(3).reg(); |
| 4497 const VRegister result = locs()->out(0).fpu_reg(); | 4479 const VRegister result = locs()->out(0).fpu_reg(); |
| 4498 __ veor(result, result, result); | 4480 __ veor(result, result, result); |
| 4499 __ vinsw(result, 0, v0); | 4481 __ vinsw(result, 0, v0); |
| 4500 __ vinsw(result, 1, v1); | 4482 __ vinsw(result, 1, v1); |
| 4501 __ vinsw(result, 2, v2); | 4483 __ vinsw(result, 2, v2); |
| 4502 __ vinsw(result, 3, v3); | 4484 __ vinsw(result, 3, v3); |
| 4503 } | 4485 } |
| 4504 | 4486 |
| 4505 | 4487 |
| 4506 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 4488 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
| 4507 Zone* zone, bool opt) const { | 4489 Zone* zone, |
| 4490 bool opt) const { |
| 4508 const intptr_t kNumInputs = 4; | 4491 const intptr_t kNumInputs = 4; |
| 4509 const intptr_t kNumTemps = 1; | 4492 const intptr_t kNumTemps = 1; |
| 4510 LocationSummary* summary = new LocationSummary( | 4493 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4511 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4494 LocationSummary::kNoCall); |
| 4512 summary->set_in(0, Location::RequiresRegister()); | 4495 summary->set_in(0, Location::RequiresRegister()); |
| 4513 summary->set_in(1, Location::RequiresRegister()); | 4496 summary->set_in(1, Location::RequiresRegister()); |
| 4514 summary->set_in(2, Location::RequiresRegister()); | 4497 summary->set_in(2, Location::RequiresRegister()); |
| 4515 summary->set_in(3, Location::RequiresRegister()); | 4498 summary->set_in(3, Location::RequiresRegister()); |
| 4516 summary->set_temp(0, Location::RequiresRegister()); | 4499 summary->set_temp(0, Location::RequiresRegister()); |
| 4517 summary->set_out(0, Location::RequiresFpuRegister()); | 4500 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4518 return summary; | 4501 return summary; |
| 4519 } | 4502 } |
| 4520 | 4503 |
| 4521 | 4504 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 4550 __ CompareRegisters(v3, TMP2); | 4533 __ CompareRegisters(v3, TMP2); |
| 4551 __ csel(TMP, temp, ZR, EQ); | 4534 __ csel(TMP, temp, ZR, EQ); |
| 4552 __ vinsw(result, 3, TMP); | 4535 __ vinsw(result, 3, TMP); |
| 4553 } | 4536 } |
| 4554 | 4537 |
| 4555 | 4538 |
| 4556 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, | 4539 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, |
| 4557 bool opt) const { | 4540 bool opt) const { |
| 4558 const intptr_t kNumInputs = 1; | 4541 const intptr_t kNumInputs = 1; |
| 4559 const intptr_t kNumTemps = 0; | 4542 const intptr_t kNumTemps = 0; |
| 4560 LocationSummary* summary = new LocationSummary( | 4543 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4561 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4544 LocationSummary::kNoCall); |
| 4562 summary->set_in(0, Location::RequiresFpuRegister()); | 4545 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4563 summary->set_out(0, Location::RequiresRegister()); | 4546 summary->set_out(0, Location::RequiresRegister()); |
| 4564 return summary; | 4547 return summary; |
| 4565 } | 4548 } |
| 4566 | 4549 |
| 4567 | 4550 |
| 4568 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4551 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4569 const VRegister value = locs()->in(0).fpu_reg(); | 4552 const VRegister value = locs()->in(0).fpu_reg(); |
| 4570 const Register result = locs()->out(0).reg(); | 4553 const Register result = locs()->out(0).reg(); |
| 4571 | 4554 |
| 4572 switch (op_kind()) { | 4555 switch (op_kind()) { |
| 4573 case MethodRecognizer::kInt32x4GetFlagX: | 4556 case MethodRecognizer::kInt32x4GetFlagX: |
| 4574 __ vmovrs(result, value, 0); | 4557 __ vmovrs(result, value, 0); |
| 4575 break; | 4558 break; |
| 4576 case MethodRecognizer::kInt32x4GetFlagY: | 4559 case MethodRecognizer::kInt32x4GetFlagY: |
| 4577 __ vmovrs(result, value, 1); | 4560 __ vmovrs(result, value, 1); |
| 4578 break; | 4561 break; |
| 4579 case MethodRecognizer::kInt32x4GetFlagZ: | 4562 case MethodRecognizer::kInt32x4GetFlagZ: |
| 4580 __ vmovrs(result, value, 2); | 4563 __ vmovrs(result, value, 2); |
| 4581 break; | 4564 break; |
| 4582 case MethodRecognizer::kInt32x4GetFlagW: | 4565 case MethodRecognizer::kInt32x4GetFlagW: |
| 4583 __ vmovrs(result, value, 3); | 4566 __ vmovrs(result, value, 3); |
| 4584 break; | 4567 break; |
| 4585 default: UNREACHABLE(); | 4568 default: |
| 4569 UNREACHABLE(); |
| 4586 } | 4570 } |
| 4587 | 4571 |
| 4588 __ tst(result, Operand(result)); | 4572 __ tst(result, Operand(result)); |
| 4589 __ LoadObject(result, Bool::True()); | 4573 __ LoadObject(result, Bool::True()); |
| 4590 __ LoadObject(TMP, Bool::False()); | 4574 __ LoadObject(TMP, Bool::False()); |
| 4591 __ csel(result, TMP, result, EQ); | 4575 __ csel(result, TMP, result, EQ); |
| 4592 } | 4576 } |
| 4593 | 4577 |
| 4594 | 4578 |
| 4595 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, | 4579 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, |
| 4596 bool opt) const { | 4580 bool opt) const { |
| 4597 const intptr_t kNumInputs = 3; | 4581 const intptr_t kNumInputs = 3; |
| 4598 const intptr_t kNumTemps = 1; | 4582 const intptr_t kNumTemps = 1; |
| 4599 LocationSummary* summary = new LocationSummary( | 4583 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4600 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4584 LocationSummary::kNoCall); |
| 4601 summary->set_in(0, Location::RequiresFpuRegister()); | 4585 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4602 summary->set_in(1, Location::RequiresFpuRegister()); | 4586 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4603 summary->set_in(2, Location::RequiresFpuRegister()); | 4587 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4604 summary->set_temp(0, Location::RequiresFpuRegister()); | 4588 summary->set_temp(0, Location::RequiresFpuRegister()); |
| 4605 summary->set_out(0, Location::RequiresFpuRegister()); | 4589 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4606 return summary; | 4590 return summary; |
| 4607 } | 4591 } |
| 4608 | 4592 |
| 4609 | 4593 |
| 4610 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4594 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4624 __ vand(temp, temp, falseValue); | 4608 __ vand(temp, temp, falseValue); |
| 4625 // out = mask | temp. | 4609 // out = mask | temp. |
| 4626 __ vorr(out, mask, temp); | 4610 __ vorr(out, mask, temp); |
| 4627 } | 4611 } |
| 4628 | 4612 |
| 4629 | 4613 |
| 4630 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, | 4614 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, |
| 4631 bool opt) const { | 4615 bool opt) const { |
| 4632 const intptr_t kNumInputs = 2; | 4616 const intptr_t kNumInputs = 2; |
| 4633 const intptr_t kNumTemps = 0; | 4617 const intptr_t kNumTemps = 0; |
| 4634 LocationSummary* summary = new LocationSummary( | 4618 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4635 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4619 LocationSummary::kNoCall); |
| 4636 summary->set_in(0, Location::RequiresFpuRegister()); | 4620 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4637 summary->set_in(1, Location::RequiresRegister()); | 4621 summary->set_in(1, Location::RequiresRegister()); |
| 4638 summary->set_out(0, Location::RequiresFpuRegister()); | 4622 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4639 return summary; | 4623 return summary; |
| 4640 } | 4624 } |
| 4641 | 4625 |
| 4642 | 4626 |
| 4643 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4627 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4644 const VRegister mask = locs()->in(0).fpu_reg(); | 4628 const VRegister mask = locs()->in(0).fpu_reg(); |
| 4645 const Register flag = locs()->in(1).reg(); | 4629 const Register flag = locs()->in(1).reg(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4658 break; | 4642 break; |
| 4659 case MethodRecognizer::kInt32x4WithFlagY: | 4643 case MethodRecognizer::kInt32x4WithFlagY: |
| 4660 __ vinsw(result, 1, TMP); | 4644 __ vinsw(result, 1, TMP); |
| 4661 break; | 4645 break; |
| 4662 case MethodRecognizer::kInt32x4WithFlagZ: | 4646 case MethodRecognizer::kInt32x4WithFlagZ: |
| 4663 __ vinsw(result, 2, TMP); | 4647 __ vinsw(result, 2, TMP); |
| 4664 break; | 4648 break; |
| 4665 case MethodRecognizer::kInt32x4WithFlagW: | 4649 case MethodRecognizer::kInt32x4WithFlagW: |
| 4666 __ vinsw(result, 3, TMP); | 4650 __ vinsw(result, 3, TMP); |
| 4667 break; | 4651 break; |
| 4668 default: UNREACHABLE(); | 4652 default: |
| 4653 UNREACHABLE(); |
| 4669 } | 4654 } |
| 4670 } | 4655 } |
| 4671 | 4656 |
| 4672 | 4657 |
| 4673 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, | 4658 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, |
| 4674 bool opt) const { | 4659 bool opt) const { |
| 4675 const intptr_t kNumInputs = 1; | 4660 const intptr_t kNumInputs = 1; |
| 4676 const intptr_t kNumTemps = 0; | 4661 const intptr_t kNumTemps = 0; |
| 4677 LocationSummary* summary = new LocationSummary( | 4662 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4678 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4663 LocationSummary::kNoCall); |
| 4679 summary->set_in(0, Location::RequiresFpuRegister()); | 4664 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4680 summary->set_out(0, Location::RequiresFpuRegister()); | 4665 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4681 return summary; | 4666 return summary; |
| 4682 } | 4667 } |
| 4683 | 4668 |
| 4684 | 4669 |
| 4685 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4670 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4686 const VRegister value = locs()->in(0).fpu_reg(); | 4671 const VRegister value = locs()->in(0).fpu_reg(); |
| 4687 const VRegister result = locs()->out(0).fpu_reg(); | 4672 const VRegister result = locs()->out(0).fpu_reg(); |
| 4688 | 4673 |
| 4689 if (value != result) { | 4674 if (value != result) { |
| 4690 __ vmov(result, value); | 4675 __ vmov(result, value); |
| 4691 } | 4676 } |
| 4692 } | 4677 } |
| 4693 | 4678 |
| 4694 | 4679 |
| 4695 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, | 4680 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 4696 bool opt) const { | 4681 bool opt) const { |
| 4697 const intptr_t kNumInputs = 2; | 4682 const intptr_t kNumInputs = 2; |
| 4698 const intptr_t kNumTemps = 0; | 4683 const intptr_t kNumTemps = 0; |
| 4699 LocationSummary* summary = new LocationSummary( | 4684 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4700 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4685 LocationSummary::kNoCall); |
| 4701 summary->set_in(0, Location::RequiresFpuRegister()); | 4686 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4702 summary->set_in(1, Location::RequiresFpuRegister()); | 4687 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4703 summary->set_out(0, Location::RequiresFpuRegister()); | 4688 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4704 return summary; | 4689 return summary; |
| 4705 } | 4690 } |
| 4706 | 4691 |
| 4707 | 4692 |
| 4708 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4693 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4709 const VRegister left = locs()->in(0).fpu_reg(); | 4694 const VRegister left = locs()->in(0).fpu_reg(); |
| 4710 const VRegister right = locs()->in(1).fpu_reg(); | 4695 const VRegister right = locs()->in(1).fpu_reg(); |
| 4711 const VRegister result = locs()->out(0).fpu_reg(); | 4696 const VRegister result = locs()->out(0).fpu_reg(); |
| 4712 switch (op_kind()) { | 4697 switch (op_kind()) { |
| 4713 case Token::kBIT_AND: __ vand(result, left, right); break; | 4698 case Token::kBIT_AND: |
| 4714 case Token::kBIT_OR: __ vorr(result, left, right); break; | 4699 __ vand(result, left, right); |
| 4715 case Token::kBIT_XOR: __ veor(result, left, right); break; | 4700 break; |
| 4716 case Token::kADD: __ vaddw(result, left, right); break; | 4701 case Token::kBIT_OR: |
| 4717 case Token::kSUB: __ vsubw(result, left, right); break; | 4702 __ vorr(result, left, right); |
| 4718 default: UNREACHABLE(); | 4703 break; |
| 4704 case Token::kBIT_XOR: |
| 4705 __ veor(result, left, right); |
| 4706 break; |
| 4707 case Token::kADD: |
| 4708 __ vaddw(result, left, right); |
| 4709 break; |
| 4710 case Token::kSUB: |
| 4711 __ vsubw(result, left, right); |
| 4712 break; |
| 4713 default: |
| 4714 UNREACHABLE(); |
| 4719 } | 4715 } |
| 4720 } | 4716 } |
| 4721 | 4717 |
| 4722 | 4718 |
| 4723 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 4719 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |
| 4724 bool opt) const { | 4720 bool opt) const { |
| 4725 ASSERT((kind() == MathUnaryInstr::kSqrt) || | 4721 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
| 4726 (kind() == MathUnaryInstr::kDoubleSquare)); | 4722 (kind() == MathUnaryInstr::kDoubleSquare)); |
| 4727 const intptr_t kNumInputs = 1; | 4723 const intptr_t kNumInputs = 1; |
| 4728 const intptr_t kNumTemps = 0; | 4724 const intptr_t kNumTemps = 0; |
| 4729 LocationSummary* summary = new(zone) LocationSummary( | 4725 LocationSummary* summary = new (zone) |
| 4730 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4726 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4731 summary->set_in(0, Location::RequiresFpuRegister()); | 4727 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4732 summary->set_out(0, Location::RequiresFpuRegister()); | 4728 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4733 return summary; | 4729 return summary; |
| 4734 } | 4730 } |
| 4735 | 4731 |
| 4736 | 4732 |
| 4737 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4733 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4738 if (kind() == MathUnaryInstr::kSqrt) { | 4734 if (kind() == MathUnaryInstr::kSqrt) { |
| 4739 const VRegister val = locs()->in(0).fpu_reg(); | 4735 const VRegister val = locs()->in(0).fpu_reg(); |
| 4740 const VRegister result = locs()->out(0).fpu_reg(); | 4736 const VRegister result = locs()->out(0).fpu_reg(); |
| 4741 __ fsqrtd(result, val); | 4737 __ fsqrtd(result, val); |
| 4742 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 4738 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
| 4743 const VRegister val = locs()->in(0).fpu_reg(); | 4739 const VRegister val = locs()->in(0).fpu_reg(); |
| 4744 const VRegister result = locs()->out(0).fpu_reg(); | 4740 const VRegister result = locs()->out(0).fpu_reg(); |
| 4745 __ fmuld(result, val, val); | 4741 __ fmuld(result, val, val); |
| 4746 } else { | 4742 } else { |
| 4747 UNREACHABLE(); | 4743 UNREACHABLE(); |
| 4748 } | 4744 } |
| 4749 } | 4745 } |
| 4750 | 4746 |
| 4751 | 4747 |
| 4752 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 4748 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |
| 4753 Zone* zone, bool opt) const { | 4749 Zone* zone, |
| 4750 bool opt) const { |
| 4754 const intptr_t kNumTemps = 0; | 4751 const intptr_t kNumTemps = 0; |
| 4755 LocationSummary* summary = new(zone) LocationSummary( | 4752 LocationSummary* summary = new (zone) |
| 4756 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 4753 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 4757 summary->set_in(0, Location::RegisterLocation(R0)); | 4754 summary->set_in(0, Location::RegisterLocation(R0)); |
| 4758 summary->set_in(1, Location::RegisterLocation(R1)); | 4755 summary->set_in(1, Location::RegisterLocation(R1)); |
| 4759 summary->set_in(2, Location::RegisterLocation(R2)); | 4756 summary->set_in(2, Location::RegisterLocation(R2)); |
| 4760 summary->set_in(3, Location::RegisterLocation(R3)); | 4757 summary->set_in(3, Location::RegisterLocation(R3)); |
| 4761 summary->set_out(0, Location::RegisterLocation(R0)); | 4758 summary->set_out(0, Location::RegisterLocation(R0)); |
| 4762 return summary; | 4759 return summary; |
| 4763 } | 4760 } |
| 4764 | 4761 |
| 4765 | 4762 |
| 4766 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 4763 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |
| 4767 FlowGraphCompiler* compiler) { | 4764 FlowGraphCompiler* compiler) { |
| 4768 | |
| 4769 // Call the function. | 4765 // Call the function. |
| 4770 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 4766 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |
| 4771 } | 4767 } |
| 4772 | 4768 |
| 4773 | 4769 |
| 4774 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 4770 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |
| 4775 bool opt) const { | 4771 bool opt) const { |
| 4776 if (result_cid() == kDoubleCid) { | 4772 if (result_cid() == kDoubleCid) { |
| 4777 const intptr_t kNumInputs = 2; | 4773 const intptr_t kNumInputs = 2; |
| 4778 const intptr_t kNumTemps = 0; | 4774 const intptr_t kNumTemps = 0; |
| 4779 LocationSummary* summary = new(zone) LocationSummary( | 4775 LocationSummary* summary = new (zone) |
| 4780 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4776 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4781 summary->set_in(0, Location::RequiresFpuRegister()); | 4777 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4782 summary->set_in(1, Location::RequiresFpuRegister()); | 4778 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4783 // Reuse the left register so that code can be made shorter. | 4779 // Reuse the left register so that code can be made shorter. |
| 4784 summary->set_out(0, Location::SameAsFirstInput()); | 4780 summary->set_out(0, Location::SameAsFirstInput()); |
| 4785 return summary; | 4781 return summary; |
| 4786 } | 4782 } |
| 4787 ASSERT(result_cid() == kSmiCid); | 4783 ASSERT(result_cid() == kSmiCid); |
| 4788 const intptr_t kNumInputs = 2; | 4784 const intptr_t kNumInputs = 2; |
| 4789 const intptr_t kNumTemps = 0; | 4785 const intptr_t kNumTemps = 0; |
| 4790 LocationSummary* summary = new(zone) LocationSummary( | 4786 LocationSummary* summary = new (zone) |
| 4791 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4787 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4792 summary->set_in(0, Location::RequiresRegister()); | 4788 summary->set_in(0, Location::RequiresRegister()); |
| 4793 summary->set_in(1, Location::RequiresRegister()); | 4789 summary->set_in(1, Location::RequiresRegister()); |
| 4794 // Reuse the left register so that code can be made shorter. | 4790 // Reuse the left register so that code can be made shorter. |
| 4795 summary->set_out(0, Location::SameAsFirstInput()); | 4791 summary->set_out(0, Location::SameAsFirstInput()); |
| 4796 return summary; | 4792 return summary; |
| 4797 } | 4793 } |
| 4798 | 4794 |
| 4799 | 4795 |
| 4800 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4796 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4801 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 4797 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4854 } else { | 4850 } else { |
| 4855 __ csel(result, right, left, LT); | 4851 __ csel(result, right, left, LT); |
| 4856 } | 4852 } |
| 4857 } | 4853 } |
| 4858 | 4854 |
| 4859 | 4855 |
| 4860 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 4856 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 4861 bool opt) const { | 4857 bool opt) const { |
| 4862 const intptr_t kNumInputs = 1; | 4858 const intptr_t kNumInputs = 1; |
| 4863 const intptr_t kNumTemps = 0; | 4859 const intptr_t kNumTemps = 0; |
| 4864 LocationSummary* summary = new(zone) LocationSummary( | 4860 LocationSummary* summary = new (zone) |
| 4865 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4861 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4866 summary->set_in(0, Location::RequiresRegister()); | 4862 summary->set_in(0, Location::RequiresRegister()); |
| 4867 // We make use of 3-operand instructions by not requiring result register | 4863 // We make use of 3-operand instructions by not requiring result register |
| 4868 // to be identical to first input register as on Intel. | 4864 // to be identical to first input register as on Intel. |
| 4869 summary->set_out(0, Location::RequiresRegister()); | 4865 summary->set_out(0, Location::RequiresRegister()); |
| 4870 return summary; | 4866 return summary; |
| 4871 } | 4867 } |
| 4872 | 4868 |
| 4873 | 4869 |
| 4874 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4870 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4875 const Register value = locs()->in(0).reg(); | 4871 const Register value = locs()->in(0).reg(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4889 default: | 4885 default: |
| 4890 UNREACHABLE(); | 4886 UNREACHABLE(); |
| 4891 } | 4887 } |
| 4892 } | 4888 } |
| 4893 | 4889 |
| 4894 | 4890 |
| 4895 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 4891 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 4896 bool opt) const { | 4892 bool opt) const { |
| 4897 const intptr_t kNumInputs = 1; | 4893 const intptr_t kNumInputs = 1; |
| 4898 const intptr_t kNumTemps = 0; | 4894 const intptr_t kNumTemps = 0; |
| 4899 LocationSummary* summary = new(zone) LocationSummary( | 4895 LocationSummary* summary = new (zone) |
| 4900 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4896 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4901 summary->set_in(0, Location::RequiresFpuRegister()); | 4897 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4902 summary->set_out(0, Location::RequiresFpuRegister()); | 4898 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4903 return summary; | 4899 return summary; |
| 4904 } | 4900 } |
| 4905 | 4901 |
| 4906 | 4902 |
| 4907 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4903 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4908 const VRegister result = locs()->out(0).fpu_reg(); | 4904 const VRegister result = locs()->out(0).fpu_reg(); |
| 4909 const VRegister value = locs()->in(0).fpu_reg(); | 4905 const VRegister value = locs()->in(0).fpu_reg(); |
| 4910 __ fnegd(result, value); | 4906 __ fnegd(result, value); |
| 4911 } | 4907 } |
| 4912 | 4908 |
| 4913 | 4909 |
| 4914 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 4910 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 4915 bool opt) const { | 4911 bool opt) const { |
| 4916 const intptr_t kNumInputs = 1; | 4912 const intptr_t kNumInputs = 1; |
| 4917 const intptr_t kNumTemps = 0; | 4913 const intptr_t kNumTemps = 0; |
| 4918 LocationSummary* result = new(zone) LocationSummary( | 4914 LocationSummary* result = new (zone) |
| 4919 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4915 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4920 result->set_in(0, Location::RequiresRegister()); | 4916 result->set_in(0, Location::RequiresRegister()); |
| 4921 result->set_out(0, Location::RequiresFpuRegister()); | 4917 result->set_out(0, Location::RequiresFpuRegister()); |
| 4922 return result; | 4918 return result; |
| 4923 } | 4919 } |
| 4924 | 4920 |
| 4925 | 4921 |
| 4926 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4922 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4927 const Register value = locs()->in(0).reg(); | 4923 const Register value = locs()->in(0).reg(); |
| 4928 const VRegister result = locs()->out(0).fpu_reg(); | 4924 const VRegister result = locs()->out(0).fpu_reg(); |
| 4929 __ scvtfdw(result, value); | 4925 __ scvtfdw(result, value); |
| 4930 } | 4926 } |
| 4931 | 4927 |
| 4932 | 4928 |
| 4933 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 4929 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 4934 bool opt) const { | 4930 bool opt) const { |
| 4935 const intptr_t kNumInputs = 1; | 4931 const intptr_t kNumInputs = 1; |
| 4936 const intptr_t kNumTemps = 0; | 4932 const intptr_t kNumTemps = 0; |
| 4937 LocationSummary* result = new(zone) LocationSummary( | 4933 LocationSummary* result = new (zone) |
| 4938 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4934 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4939 result->set_in(0, Location::RequiresRegister()); | 4935 result->set_in(0, Location::RequiresRegister()); |
| 4940 result->set_out(0, Location::RequiresFpuRegister()); | 4936 result->set_out(0, Location::RequiresFpuRegister()); |
| 4941 return result; | 4937 return result; |
| 4942 } | 4938 } |
| 4943 | 4939 |
| 4944 | 4940 |
| 4945 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4941 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4946 const Register value = locs()->in(0).reg(); | 4942 const Register value = locs()->in(0).reg(); |
| 4947 const VRegister result = locs()->out(0).fpu_reg(); | 4943 const VRegister result = locs()->out(0).fpu_reg(); |
| 4948 __ SmiUntag(TMP, value); | 4944 __ SmiUntag(TMP, value); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4959 | 4955 |
| 4960 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4956 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4961 UNIMPLEMENTED(); | 4957 UNIMPLEMENTED(); |
| 4962 } | 4958 } |
| 4963 | 4959 |
| 4964 | 4960 |
| 4965 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 4961 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |
| 4966 bool opt) const { | 4962 bool opt) const { |
| 4967 const intptr_t kNumInputs = 1; | 4963 const intptr_t kNumInputs = 1; |
| 4968 const intptr_t kNumTemps = 0; | 4964 const intptr_t kNumTemps = 0; |
| 4969 LocationSummary* result = new(zone) LocationSummary( | 4965 LocationSummary* result = new (zone) |
| 4970 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 4966 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 4971 result->set_in(0, Location::RegisterLocation(R1)); | 4967 result->set_in(0, Location::RegisterLocation(R1)); |
| 4972 result->set_out(0, Location::RegisterLocation(R0)); | 4968 result->set_out(0, Location::RegisterLocation(R0)); |
| 4973 return result; | 4969 return result; |
| 4974 } | 4970 } |
| 4975 | 4971 |
| 4976 | 4972 |
| 4977 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4973 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4978 const Register result = locs()->out(0).reg(); | 4974 const Register result = locs()->out(0).reg(); |
| 4979 const Register value_obj = locs()->in(0).reg(); | 4975 const Register value_obj = locs()->in(0).reg(); |
| 4980 ASSERT(result == R0); | 4976 ASSERT(result == R0); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4996 __ SmiTag(result); | 4992 __ SmiTag(result); |
| 4997 __ b(&done); | 4993 __ b(&done); |
| 4998 __ Bind(&do_call); | 4994 __ Bind(&do_call); |
| 4999 __ Push(value_obj); | 4995 __ Push(value_obj); |
| 5000 ASSERT(instance_call()->HasICData()); | 4996 ASSERT(instance_call()->HasICData()); |
| 5001 const ICData& ic_data = *instance_call()->ic_data(); | 4997 const ICData& ic_data = *instance_call()->ic_data(); |
| 5002 ASSERT((ic_data.NumberOfChecks() == 1)); | 4998 ASSERT((ic_data.NumberOfChecks() == 1)); |
| 5003 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 4999 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
| 5004 | 5000 |
| 5005 const intptr_t kNumberOfArguments = 1; | 5001 const intptr_t kNumberOfArguments = 1; |
| 5006 compiler->GenerateStaticCall(deopt_id(), | 5002 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, |
| 5007 instance_call()->token_pos(), | |
| 5008 target, | |
| 5009 kNumberOfArguments, | 5003 kNumberOfArguments, |
| 5010 Object::null_array(), // No argument names., | 5004 Object::null_array(), // No argument names., |
| 5011 locs(), | 5005 locs(), ICData::Handle()); |
| 5012 ICData::Handle()); | |
| 5013 __ Bind(&done); | 5006 __ Bind(&done); |
| 5014 } | 5007 } |
| 5015 | 5008 |
| 5016 | 5009 |
| 5017 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 5010 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |
| 5018 bool opt) const { | 5011 bool opt) const { |
| 5019 const intptr_t kNumInputs = 1; | 5012 const intptr_t kNumInputs = 1; |
| 5020 const intptr_t kNumTemps = 0; | 5013 const intptr_t kNumTemps = 0; |
| 5021 LocationSummary* result = new(zone) LocationSummary( | 5014 LocationSummary* result = new (zone) |
| 5022 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5015 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5023 result->set_in(0, Location::RequiresFpuRegister()); | 5016 result->set_in(0, Location::RequiresFpuRegister()); |
| 5024 result->set_out(0, Location::RequiresRegister()); | 5017 result->set_out(0, Location::RequiresRegister()); |
| 5025 return result; | 5018 return result; |
| 5026 } | 5019 } |
| 5027 | 5020 |
| 5028 | 5021 |
| 5029 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5022 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5030 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 5023 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
| 5031 const Register result = locs()->out(0).reg(); | 5024 const Register result = locs()->out(0).reg(); |
| 5032 const VRegister value = locs()->in(0).fpu_reg(); | 5025 const VRegister value = locs()->in(0).fpu_reg(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 5053 | 5046 |
| 5054 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5047 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5055 UNIMPLEMENTED(); | 5048 UNIMPLEMENTED(); |
| 5056 } | 5049 } |
| 5057 | 5050 |
| 5058 | 5051 |
| 5059 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 5052 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |
| 5060 bool opt) const { | 5053 bool opt) const { |
| 5061 const intptr_t kNumInputs = 1; | 5054 const intptr_t kNumInputs = 1; |
| 5062 const intptr_t kNumTemps = 0; | 5055 const intptr_t kNumTemps = 0; |
| 5063 LocationSummary* result = new(zone) LocationSummary( | 5056 LocationSummary* result = new (zone) |
| 5064 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5057 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5065 result->set_in(0, Location::RequiresFpuRegister()); | 5058 result->set_in(0, Location::RequiresFpuRegister()); |
| 5066 result->set_out(0, Location::RequiresFpuRegister()); | 5059 result->set_out(0, Location::RequiresFpuRegister()); |
| 5067 return result; | 5060 return result; |
| 5068 } | 5061 } |
| 5069 | 5062 |
| 5070 | 5063 |
| 5071 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5064 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5072 const VRegister value = locs()->in(0).fpu_reg(); | 5065 const VRegister value = locs()->in(0).fpu_reg(); |
| 5073 const VRegister result = locs()->out(0).fpu_reg(); | 5066 const VRegister result = locs()->out(0).fpu_reg(); |
| 5074 __ fcvtsd(result, value); | 5067 __ fcvtsd(result, value); |
| 5075 } | 5068 } |
| 5076 | 5069 |
| 5077 | 5070 |
| 5078 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 5071 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5079 bool opt) const { | 5072 bool opt) const { |
| 5080 const intptr_t kNumInputs = 1; | 5073 const intptr_t kNumInputs = 1; |
| 5081 const intptr_t kNumTemps = 0; | 5074 const intptr_t kNumTemps = 0; |
| 5082 LocationSummary* result = new(zone) LocationSummary( | 5075 LocationSummary* result = new (zone) |
| 5083 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5076 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5084 result->set_in(0, Location::RequiresFpuRegister()); | 5077 result->set_in(0, Location::RequiresFpuRegister()); |
| 5085 result->set_out(0, Location::RequiresFpuRegister()); | 5078 result->set_out(0, Location::RequiresFpuRegister()); |
| 5086 return result; | 5079 return result; |
| 5087 } | 5080 } |
| 5088 | 5081 |
| 5089 | 5082 |
| 5090 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5083 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5091 const VRegister value = locs()->in(0).fpu_reg(); | 5084 const VRegister value = locs()->in(0).fpu_reg(); |
| 5092 const VRegister result = locs()->out(0).fpu_reg(); | 5085 const VRegister result = locs()->out(0).fpu_reg(); |
| 5093 __ fcvtds(result, value); | 5086 __ fcvtds(result, value); |
| 5094 } | 5087 } |
| 5095 | 5088 |
| 5096 | 5089 |
| 5097 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 5090 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |
| 5098 bool opt) const { | 5091 bool opt) const { |
| 5099 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 5092 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
| 5100 const intptr_t kNumTemps = | 5093 const intptr_t kNumTemps = |
| 5101 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0; | 5094 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0; |
| 5102 LocationSummary* result = new(zone) LocationSummary( | 5095 LocationSummary* result = new (zone) |
| 5103 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5096 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 5104 result->set_in(0, Location::FpuRegisterLocation(V0)); | 5097 result->set_in(0, Location::FpuRegisterLocation(V0)); |
| 5105 if (InputCount() == 2) { | 5098 if (InputCount() == 2) { |
| 5106 result->set_in(1, Location::FpuRegisterLocation(V1)); | 5099 result->set_in(1, Location::FpuRegisterLocation(V1)); |
| 5107 } | 5100 } |
| 5108 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5101 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 5109 result->set_temp(0, Location::FpuRegisterLocation(V30)); | 5102 result->set_temp(0, Location::FpuRegisterLocation(V30)); |
| 5110 } | 5103 } |
| 5111 result->set_out(0, Location::FpuRegisterLocation(V0)); | 5104 result->set_out(0, Location::FpuRegisterLocation(V0)); |
| 5112 return result; | 5105 return result; |
| 5113 } | 5106 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 5140 const VRegister result = locs->out(0).fpu_reg(); | 5133 const VRegister result = locs->out(0).fpu_reg(); |
| 5141 const VRegister saved_base = locs->temp(0).fpu_reg(); | 5134 const VRegister saved_base = locs->temp(0).fpu_reg(); |
| 5142 ASSERT((base == result) && (result != saved_base)); | 5135 ASSERT((base == result) && (result != saved_base)); |
| 5143 | 5136 |
| 5144 Label skip_call, try_sqrt, check_base, return_nan, do_pow; | 5137 Label skip_call, try_sqrt, check_base, return_nan, do_pow; |
| 5145 __ fmovdd(saved_base, base); | 5138 __ fmovdd(saved_base, base); |
| 5146 __ LoadDImmediate(result, 1.0); | 5139 __ LoadDImmediate(result, 1.0); |
| 5147 // exponent == 0.0 -> return 1.0; | 5140 // exponent == 0.0 -> return 1.0; |
| 5148 __ fcmpdz(exp); | 5141 __ fcmpdz(exp); |
| 5149 __ b(&check_base, VS); // NaN -> check base. | 5142 __ b(&check_base, VS); // NaN -> check base. |
| 5150 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. | 5143 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. |
| 5151 | 5144 |
| 5152 // exponent == 1.0 ? | 5145 // exponent == 1.0 ? |
| 5153 __ fcmpd(exp, result); | 5146 __ fcmpd(exp, result); |
| 5154 Label return_base; | 5147 Label return_base; |
| 5155 __ b(&return_base, EQ); | 5148 __ b(&return_base, EQ); |
| 5156 | 5149 |
| 5157 // exponent == 2.0 ? | 5150 // exponent == 2.0 ? |
| 5158 __ LoadDImmediate(VTMP, 2.0); | 5151 __ LoadDImmediate(VTMP, 2.0); |
| 5159 __ fcmpd(exp, VTMP); | 5152 __ fcmpd(exp, VTMP); |
| 5160 Label return_base_times_2; | 5153 Label return_base_times_2; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5233 } | 5226 } |
| 5234 __ CallRuntime(TargetFunction(), InputCount()); | 5227 __ CallRuntime(TargetFunction(), InputCount()); |
| 5235 } | 5228 } |
| 5236 | 5229 |
| 5237 | 5230 |
| 5238 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 5231 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |
| 5239 bool opt) const { | 5232 bool opt) const { |
| 5240 // Only use this instruction in optimized code. | 5233 // Only use this instruction in optimized code. |
| 5241 ASSERT(opt); | 5234 ASSERT(opt); |
| 5242 const intptr_t kNumInputs = 1; | 5235 const intptr_t kNumInputs = 1; |
| 5243 LocationSummary* summary = new(zone) LocationSummary( | 5236 LocationSummary* summary = |
| 5244 zone, kNumInputs, 0, LocationSummary::kNoCall); | 5237 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 5245 if (representation() == kUnboxedDouble) { | 5238 if (representation() == kUnboxedDouble) { |
| 5246 if (index() == 0) { | 5239 if (index() == 0) { |
| 5247 summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), | 5240 summary->set_in( |
| 5248 Location::Any())); | 5241 0, Location::Pair(Location::RequiresFpuRegister(), Location::Any())); |
| 5249 } else { | 5242 } else { |
| 5250 ASSERT(index() == 1); | 5243 ASSERT(index() == 1); |
| 5251 summary->set_in(0, Location::Pair(Location::Any(), | 5244 summary->set_in( |
| 5252 Location::RequiresFpuRegister())); | 5245 0, Location::Pair(Location::Any(), Location::RequiresFpuRegister())); |
| 5253 } | 5246 } |
| 5254 summary->set_out(0, Location::RequiresFpuRegister()); | 5247 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5255 } else { | 5248 } else { |
| 5256 ASSERT(representation() == kTagged); | 5249 ASSERT(representation() == kTagged); |
| 5257 if (index() == 0) { | 5250 if (index() == 0) { |
| 5258 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5251 summary->set_in( |
| 5259 Location::Any())); | 5252 0, Location::Pair(Location::RequiresRegister(), Location::Any())); |
| 5260 } else { | 5253 } else { |
| 5261 ASSERT(index() == 1); | 5254 ASSERT(index() == 1); |
| 5262 summary->set_in(0, Location::Pair(Location::Any(), | 5255 summary->set_in( |
| 5263 Location::RequiresRegister())); | 5256 0, Location::Pair(Location::Any(), Location::RequiresRegister())); |
| 5264 } | 5257 } |
| 5265 summary->set_out(0, Location::RequiresRegister()); | 5258 summary->set_out(0, Location::RequiresRegister()); |
| 5266 } | 5259 } |
| 5267 return summary; | 5260 return summary; |
| 5268 } | 5261 } |
| 5269 | 5262 |
| 5270 | 5263 |
| 5271 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5264 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5272 ASSERT(locs()->in(0).IsPairLocation()); | 5265 ASSERT(locs()->in(0).IsPairLocation()); |
| 5273 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5266 PairLocation* pair = locs()->in(0).AsPairLocation(); |
| 5274 Location in_loc = pair->At(index()); | 5267 Location in_loc = pair->At(index()); |
| 5275 if (representation() == kUnboxedDouble) { | 5268 if (representation() == kUnboxedDouble) { |
| 5276 const VRegister out = locs()->out(0).fpu_reg(); | 5269 const VRegister out = locs()->out(0).fpu_reg(); |
| 5277 const VRegister in = in_loc.fpu_reg(); | 5270 const VRegister in = in_loc.fpu_reg(); |
| 5278 __ fmovdd(out, in); | 5271 __ fmovdd(out, in); |
| 5279 } else { | 5272 } else { |
| 5280 ASSERT(representation() == kTagged); | 5273 ASSERT(representation() == kTagged); |
| 5281 const Register out = locs()->out(0).reg(); | 5274 const Register out = locs()->out(0).reg(); |
| 5282 const Register in = in_loc.reg(); | 5275 const Register in = in_loc.reg(); |
| 5283 __ mov(out, in); | 5276 __ mov(out, in); |
| 5284 } | 5277 } |
| 5285 } | 5278 } |
| 5286 | 5279 |
| 5287 | 5280 |
| 5288 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, | 5281 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, |
| 5289 bool opt) const { | 5282 bool opt) const { |
| 5290 if (kind() == MergedMathInstr::kTruncDivMod) { | 5283 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 5291 const intptr_t kNumInputs = 2; | 5284 const intptr_t kNumInputs = 2; |
| 5292 const intptr_t kNumTemps = 0; | 5285 const intptr_t kNumTemps = 0; |
| 5293 LocationSummary* summary = new(zone) LocationSummary( | 5286 LocationSummary* summary = new (zone) |
| 5294 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5287 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5295 summary->set_in(0, Location::RequiresRegister()); | 5288 summary->set_in(0, Location::RequiresRegister()); |
| 5296 summary->set_in(1, Location::RequiresRegister()); | 5289 summary->set_in(1, Location::RequiresRegister()); |
| 5297 // Output is a pair of registers. | 5290 // Output is a pair of registers. |
| 5298 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 5291 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 5299 Location::RequiresRegister())); | 5292 Location::RequiresRegister())); |
| 5300 return summary; | 5293 return summary; |
| 5301 } | 5294 } |
| 5302 UNIMPLEMENTED(); | 5295 UNIMPLEMENTED(); |
| 5303 return NULL; | 5296 return NULL; |
| 5304 } | 5297 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5357 return; | 5350 return; |
| 5358 } | 5351 } |
| 5359 if (kind() == MergedMathInstr::kSinCos) { | 5352 if (kind() == MergedMathInstr::kSinCos) { |
| 5360 UNIMPLEMENTED(); | 5353 UNIMPLEMENTED(); |
| 5361 } | 5354 } |
| 5362 UNIMPLEMENTED(); | 5355 UNIMPLEMENTED(); |
| 5363 } | 5356 } |
| 5364 | 5357 |
| 5365 | 5358 |
| 5366 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 5359 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
| 5367 Zone* zone, bool opt) const { | 5360 Zone* zone, |
| 5361 bool opt) const { |
| 5368 return MakeCallSummary(zone); | 5362 return MakeCallSummary(zone); |
| 5369 } | 5363 } |
| 5370 | 5364 |
| 5371 | 5365 |
| 5372 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, | 5366 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5373 bool opt) const { | |
| 5374 comparison()->InitializeLocationSummary(zone, opt); | 5367 comparison()->InitializeLocationSummary(zone, opt); |
| 5375 // Branches don't produce a result. | 5368 // Branches don't produce a result. |
| 5376 comparison()->locs()->set_out(0, Location::NoLocation()); | 5369 comparison()->locs()->set_out(0, Location::NoLocation()); |
| 5377 return comparison()->locs(); | 5370 return comparison()->locs(); |
| 5378 } | 5371 } |
| 5379 | 5372 |
| 5380 | 5373 |
| 5381 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5374 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5382 comparison()->EmitBranchCode(compiler, this); | 5375 comparison()->EmitBranchCode(compiler, this); |
| 5383 } | 5376 } |
| 5384 | 5377 |
| 5385 | 5378 |
| 5386 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 5379 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
| 5387 bool opt) const { | 5380 bool opt) const { |
| 5388 const intptr_t kNumInputs = 1; | 5381 const intptr_t kNumInputs = 1; |
| 5389 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); | 5382 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); |
| 5390 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 5383 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
| 5391 LocationSummary* summary = new(zone) LocationSummary( | 5384 LocationSummary* summary = new (zone) |
| 5392 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5385 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5393 summary->set_in(0, Location::RequiresRegister()); | 5386 summary->set_in(0, Location::RequiresRegister()); |
| 5394 if (!IsNullCheck()) { | 5387 if (!IsNullCheck()) { |
| 5395 summary->set_temp(0, Location::RequiresRegister()); | 5388 summary->set_temp(0, Location::RequiresRegister()); |
| 5396 if (need_mask_temp) { | 5389 if (need_mask_temp) { |
| 5397 summary->set_temp(1, Location::RequiresRegister()); | 5390 summary->set_temp(1, Location::RequiresRegister()); |
| 5398 } | 5391 } |
| 5399 } | 5392 } |
| 5400 return summary; | 5393 return summary; |
| 5401 } | 5394 } |
| 5402 | 5395 |
| 5403 | 5396 |
| 5404 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5397 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5405 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5398 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass, |
| 5406 ICData::kDeoptCheckClass, | |
| 5407 licm_hoisted_ ? ICData::kHoisted : 0); | 5399 licm_hoisted_ ? ICData::kHoisted : 0); |
| 5408 if (IsNullCheck()) { | 5400 if (IsNullCheck()) { |
| 5409 __ CompareObject(locs()->in(0).reg(), Object::null_object()); | 5401 __ CompareObject(locs()->in(0).reg(), Object::null_object()); |
| 5410 ASSERT(DeoptIfNull() || DeoptIfNotNull()); | 5402 ASSERT(DeoptIfNull() || DeoptIfNotNull()); |
| 5411 Condition cond = DeoptIfNull() ? EQ : NE; | 5403 Condition cond = DeoptIfNull() ? EQ : NE; |
| 5412 __ b(deopt, cond); | 5404 __ b(deopt, cond); |
| 5413 return; | 5405 return; |
| 5414 } | 5406 } |
| 5415 | 5407 |
| 5416 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 5408 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
| (...skipping 22 matching lines...) Expand all Loading... |
| 5439 ASSERT(cids_.length() > 2); | 5431 ASSERT(cids_.length() > 2); |
| 5440 Register mask_reg = locs()->temp(1).reg(); | 5432 Register mask_reg = locs()->temp(1).reg(); |
| 5441 __ LoadImmediate(mask_reg, 1); | 5433 __ LoadImmediate(mask_reg, 1); |
| 5442 __ lslv(mask_reg, mask_reg, temp); | 5434 __ lslv(mask_reg, mask_reg, temp); |
| 5443 __ TestImmediate(mask_reg, mask); | 5435 __ TestImmediate(mask_reg, mask); |
| 5444 __ b(deopt, EQ); | 5436 __ b(deopt, EQ); |
| 5445 } | 5437 } |
| 5446 | 5438 |
| 5447 } else { | 5439 } else { |
| 5448 GrowableArray<CidTarget> sorted_ic_data; | 5440 GrowableArray<CidTarget> sorted_ic_data; |
| 5449 FlowGraphCompiler::SortICDataByCount(unary_checks(), | 5441 FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data, |
| 5450 &sorted_ic_data, | |
| 5451 /* drop_smi = */ true); | 5442 /* drop_smi = */ true); |
| 5452 const intptr_t num_checks = sorted_ic_data.length(); | 5443 const intptr_t num_checks = sorted_ic_data.length(); |
| 5453 for (intptr_t i = 0; i < num_checks; i++) { | 5444 for (intptr_t i = 0; i < num_checks; i++) { |
| 5454 const intptr_t cid = sorted_ic_data[i].cid; | 5445 const intptr_t cid = sorted_ic_data[i].cid; |
| 5455 ASSERT(cid != kSmiCid); | 5446 ASSERT(cid != kSmiCid); |
| 5456 __ CompareImmediate(temp, cid); | 5447 __ CompareImmediate(temp, cid); |
| 5457 if (i == (num_checks - 1)) { | 5448 if (i == (num_checks - 1)) { |
| 5458 __ b(deopt, NE); | 5449 __ b(deopt, NE); |
| 5459 } else { | 5450 } else { |
| 5460 __ b(&is_ok, EQ); | 5451 __ b(&is_ok, EQ); |
| 5461 } | 5452 } |
| 5462 } | 5453 } |
| 5463 } | 5454 } |
| 5464 __ Bind(&is_ok); | 5455 __ Bind(&is_ok); |
| 5465 } | 5456 } |
| 5466 | 5457 |
| 5467 | 5458 |
| 5468 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 5459 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
| 5469 bool opt) const { | 5460 bool opt) const { |
| 5470 const intptr_t kNumInputs = 1; | 5461 const intptr_t kNumInputs = 1; |
| 5471 const intptr_t kNumTemps = 0; | 5462 const intptr_t kNumTemps = 0; |
| 5472 LocationSummary* summary = new(zone) LocationSummary( | 5463 LocationSummary* summary = new (zone) |
| 5473 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5464 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5474 summary->set_in(0, Location::RequiresRegister()); | 5465 summary->set_in(0, Location::RequiresRegister()); |
| 5475 return summary; | 5466 return summary; |
| 5476 } | 5467 } |
| 5477 | 5468 |
| 5478 | 5469 |
| 5479 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5470 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5480 Register value = locs()->in(0).reg(); | 5471 Register value = locs()->in(0).reg(); |
| 5481 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 5472 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
| 5482 __ CompareImmediate(value, Smi::RawValue(cid_)); | 5473 __ CompareImmediate(value, Smi::RawValue(cid_)); |
| 5483 __ b(deopt, NE); | 5474 __ b(deopt, NE); |
| 5484 } | 5475 } |
| 5485 | 5476 |
| 5486 | 5477 |
| 5487 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 5478 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
| 5488 bool opt) const { | 5479 bool opt) const { |
| 5489 const intptr_t kNumInputs = 1; | 5480 const intptr_t kNumInputs = 1; |
| 5490 const intptr_t kNumTemps = 0; | 5481 const intptr_t kNumTemps = 0; |
| 5491 LocationSummary* summary = new(zone) LocationSummary( | 5482 LocationSummary* summary = new (zone) |
| 5492 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5483 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5493 summary->set_in(0, Location::RequiresRegister()); | 5484 summary->set_in(0, Location::RequiresRegister()); |
| 5494 return summary; | 5485 return summary; |
| 5495 } | 5486 } |
| 5496 | 5487 |
| 5497 | 5488 |
| 5498 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5489 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5499 const Register value = locs()->in(0).reg(); | 5490 const Register value = locs()->in(0).reg(); |
| 5500 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5491 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, |
| 5501 ICData::kDeoptCheckSmi, | |
| 5502 licm_hoisted_ ? ICData::kHoisted : 0); | 5492 licm_hoisted_ ? ICData::kHoisted : 0); |
| 5503 __ BranchIfNotSmi(value, deopt); | 5493 __ BranchIfNotSmi(value, deopt); |
| 5504 } | 5494 } |
| 5505 | 5495 |
| 5506 | 5496 |
| 5507 | |
| 5508 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, | 5497 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, |
| 5509 bool opt) const { | 5498 bool opt) const { |
| 5510 const intptr_t kNumInputs = 2; | 5499 const intptr_t kNumInputs = 2; |
| 5511 const intptr_t kNumTemps = 0; | 5500 const intptr_t kNumTemps = 0; |
| 5512 LocationSummary* locs = new(zone) LocationSummary( | 5501 LocationSummary* locs = new (zone) LocationSummary( |
| 5513 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 5502 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 5514 locs->set_in(kLengthPos, Location::RequiresRegister()); | 5503 locs->set_in(kLengthPos, Location::RequiresRegister()); |
| 5515 locs->set_in(kIndexPos, Location::RequiresRegister()); | 5504 locs->set_in(kIndexPos, Location::RequiresRegister()); |
| 5516 return locs; | 5505 return locs; |
| 5517 } | 5506 } |
| 5518 | 5507 |
| 5519 | 5508 |
| 5520 class RangeErrorSlowPath : public SlowPathCode { | 5509 class RangeErrorSlowPath : public SlowPathCode { |
| 5521 public: | 5510 public: |
| 5522 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) | 5511 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) |
| 5523 : instruction_(instruction), try_index_(try_index) { } | 5512 : instruction_(instruction), try_index_(try_index) {} |
| 5524 | 5513 |
| 5525 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 5514 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5526 if (Assembler::EmittingComments()) { | 5515 if (Assembler::EmittingComments()) { |
| 5527 __ Comment("slow path check bound operation"); | 5516 __ Comment("slow path check bound operation"); |
| 5528 } | 5517 } |
| 5529 __ Bind(entry_label()); | 5518 __ Bind(entry_label()); |
| 5530 LocationSummary* locs = instruction_->locs(); | 5519 LocationSummary* locs = instruction_->locs(); |
| 5531 __ Push(locs->in(0).reg()); | 5520 __ Push(locs->in(0).reg()); |
| 5532 __ Push(locs->in(1).reg()); | 5521 __ Push(locs->in(1).reg()); |
| 5533 __ CallRuntime(kRangeErrorRuntimeEntry, 2); | 5522 __ CallRuntime(kRangeErrorRuntimeEntry, 2); |
| 5534 compiler->pc_descriptors_list()->AddDescriptor( | 5523 compiler->pc_descriptors_list()->AddDescriptor( |
| 5535 RawPcDescriptors::kOther, | 5524 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), |
| 5536 compiler->assembler()->CodeSize(), | 5525 instruction_->deopt_id(), instruction_->token_pos(), try_index_); |
| 5537 instruction_->deopt_id(), | |
| 5538 instruction_->token_pos(), | |
| 5539 try_index_); | |
| 5540 compiler->RecordSafepoint(locs, 2); | 5526 compiler->RecordSafepoint(locs, 2); |
| 5541 __ brk(0); | 5527 __ brk(0); |
| 5542 } | 5528 } |
| 5543 | 5529 |
| 5544 private: | 5530 private: |
| 5545 GenericCheckBoundInstr* instruction_; | 5531 GenericCheckBoundInstr* instruction_; |
| 5546 intptr_t try_index_; | 5532 intptr_t try_index_; |
| 5547 }; | 5533 }; |
| 5548 | 5534 |
| 5549 | 5535 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5562 } | 5548 } |
| 5563 __ cmp(index, Operand(length)); | 5549 __ cmp(index, Operand(length)); |
| 5564 __ b(slow_path->entry_label(), CS); | 5550 __ b(slow_path->entry_label(), CS); |
| 5565 } | 5551 } |
| 5566 | 5552 |
| 5567 | 5553 |
| 5568 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 5554 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
| 5569 bool opt) const { | 5555 bool opt) const { |
| 5570 const intptr_t kNumInputs = 2; | 5556 const intptr_t kNumInputs = 2; |
| 5571 const intptr_t kNumTemps = 0; | 5557 const intptr_t kNumTemps = 0; |
| 5572 LocationSummary* locs = new(zone) LocationSummary( | 5558 LocationSummary* locs = new (zone) |
| 5573 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5559 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5574 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 5560 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
| 5575 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 5561 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
| 5576 return locs; | 5562 return locs; |
| 5577 } | 5563 } |
| 5578 | 5564 |
| 5579 | 5565 |
| 5580 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5566 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5581 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 5567 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |
| 5582 flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 5568 flags |= licm_hoisted_ ? ICData::kHoisted : 0; |
| 5583 Label* deopt = compiler->AddDeoptStub( | 5569 Label* deopt = |
| 5584 deopt_id(), | 5570 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); |
| 5585 ICData::kDeoptCheckArrayBound, | |
| 5586 flags); | |
| 5587 | 5571 |
| 5588 Location length_loc = locs()->in(kLengthPos); | 5572 Location length_loc = locs()->in(kLengthPos); |
| 5589 Location index_loc = locs()->in(kIndexPos); | 5573 Location index_loc = locs()->in(kIndexPos); |
| 5590 | 5574 |
| 5591 const intptr_t index_cid = index()->Type()->ToCid(); | 5575 const intptr_t index_cid = index()->Type()->ToCid(); |
| 5592 if (length_loc.IsConstant() && index_loc.IsConstant()) { | 5576 if (length_loc.IsConstant() && index_loc.IsConstant()) { |
| 5593 // TODO(srdjan): remove this code once failures are fixed. | 5577 // TODO(srdjan): remove this code once failures are fixed. |
| 5594 if ((Smi::Cast(length_loc.constant()).Value() > | 5578 if ((Smi::Cast(length_loc.constant()).Value() > |
| 5595 Smi::Cast(index_loc.constant()).Value()) && | 5579 Smi::Cast(index_loc.constant()).Value()) && |
| 5596 (Smi::Cast(index_loc.constant()).Value() >= 0)) { | 5580 (Smi::Cast(index_loc.constant()).Value() >= 0)) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5696 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) | 5680 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) |
| 5697 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) | 5681 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) |
| 5698 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) | 5682 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) |
| 5699 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 5683 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
| 5700 | 5684 |
| 5701 | 5685 |
| 5702 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 5686 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |
| 5703 bool opt) const { | 5687 bool opt) const { |
| 5704 const intptr_t kNumInputs = 1; | 5688 const intptr_t kNumInputs = 1; |
| 5705 const intptr_t kNumTemps = 0; | 5689 const intptr_t kNumTemps = 0; |
| 5706 LocationSummary* summary = new(zone) LocationSummary( | 5690 LocationSummary* summary = new (zone) |
| 5707 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5691 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5708 if (from() == kUnboxedMint) { | 5692 if (from() == kUnboxedMint) { |
| 5709 UNREACHABLE(); | 5693 UNREACHABLE(); |
| 5710 } else if (to() == kUnboxedMint) { | 5694 } else if (to() == kUnboxedMint) { |
| 5711 UNREACHABLE(); | 5695 UNREACHABLE(); |
| 5712 } else { | 5696 } else { |
| 5713 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 5697 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 5714 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 5698 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5715 summary->set_in(0, Location::RequiresRegister()); | 5699 summary->set_in(0, Location::RequiresRegister()); |
| 5716 summary->set_out(0, Location::RequiresRegister()); | 5700 summary->set_out(0, Location::RequiresRegister()); |
| 5717 } | 5701 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5749 UNREACHABLE(); | 5733 UNREACHABLE(); |
| 5750 } else if (to() == kUnboxedMint) { | 5734 } else if (to() == kUnboxedMint) { |
| 5751 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 5735 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5752 UNREACHABLE(); | 5736 UNREACHABLE(); |
| 5753 } else { | 5737 } else { |
| 5754 UNREACHABLE(); | 5738 UNREACHABLE(); |
| 5755 } | 5739 } |
| 5756 } | 5740 } |
| 5757 | 5741 |
| 5758 | 5742 |
| 5759 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, | 5743 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5760 bool opt) const { | 5744 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 5761 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
| 5762 } | 5745 } |
| 5763 | 5746 |
| 5764 | 5747 |
| 5765 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5748 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5766 compiler->GenerateRuntimeCall(token_pos(), | 5749 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, |
| 5767 deopt_id(), | |
| 5768 kThrowRuntimeEntry, | |
| 5769 1, | |
| 5770 locs()); | 5750 locs()); |
| 5771 __ brk(0); | 5751 __ brk(0); |
| 5772 } | 5752 } |
| 5773 | 5753 |
| 5774 | 5754 |
| 5775 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, | 5755 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5776 bool opt) const { | 5756 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 5777 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
| 5778 } | 5757 } |
| 5779 | 5758 |
| 5780 | 5759 |
| 5781 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5760 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5782 compiler->SetNeedsStacktrace(catch_try_index()); | 5761 compiler->SetNeedsStacktrace(catch_try_index()); |
| 5783 compiler->GenerateRuntimeCall(token_pos(), | 5762 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, |
| 5784 deopt_id(), | 5763 2, locs()); |
| 5785 kReThrowRuntimeEntry, | |
| 5786 2, | |
| 5787 locs()); | |
| 5788 __ brk(0); | 5764 __ brk(0); |
| 5789 } | 5765 } |
| 5790 | 5766 |
| 5791 | 5767 |
| 5792 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, | 5768 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5793 bool opt) const { | 5769 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 5794 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
| 5795 } | 5770 } |
| 5796 | 5771 |
| 5797 | 5772 |
| 5798 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5773 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5799 __ Stop(message()); | 5774 __ Stop(message()); |
| 5800 } | 5775 } |
| 5801 | 5776 |
| 5802 | 5777 |
| 5803 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5778 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5804 if (!compiler->CanFallThroughTo(normal_entry())) { | 5779 if (!compiler->CanFallThroughTo(normal_entry())) { |
| 5805 __ b(compiler->GetJumpLabel(normal_entry())); | 5780 __ b(compiler->GetJumpLabel(normal_entry())); |
| 5806 } | 5781 } |
| 5807 } | 5782 } |
| 5808 | 5783 |
| 5809 | 5784 |
| 5810 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, | 5785 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5811 bool opt) const { | 5786 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 5812 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
| 5813 } | 5787 } |
| 5814 | 5788 |
| 5815 | 5789 |
| 5816 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5790 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5817 if (!compiler->is_optimizing()) { | 5791 if (!compiler->is_optimizing()) { |
| 5818 if (FLAG_reorder_basic_blocks) { | 5792 if (FLAG_reorder_basic_blocks) { |
| 5819 compiler->EmitEdgeCounter(block()->preorder_number()); | 5793 compiler->EmitEdgeCounter(block()->preorder_number()); |
| 5820 } | 5794 } |
| 5821 // Add a deoptimization descriptor for deoptimizing instructions that | 5795 // Add a deoptimization descriptor for deoptimizing instructions that |
| 5822 // may be inserted before this instruction. | 5796 // may be inserted before this instruction. |
| 5823 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 5797 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), |
| 5824 GetDeoptId(), | |
| 5825 TokenPosition::kNoSource); | 5798 TokenPosition::kNoSource); |
| 5826 } | 5799 } |
| 5827 if (HasParallelMove()) { | 5800 if (HasParallelMove()) { |
| 5828 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 5801 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 5829 } | 5802 } |
| 5830 | 5803 |
| 5831 // We can fall through if the successor is the next block in the list. | 5804 // We can fall through if the successor is the next block in the list. |
| 5832 // Otherwise, we need a jump. | 5805 // Otherwise, we need a jump. |
| 5833 if (!compiler->CanFallThroughTo(successor())) { | 5806 if (!compiler->CanFallThroughTo(successor())) { |
| 5834 __ b(compiler->GetJumpLabel(successor())); | 5807 __ b(compiler->GetJumpLabel(successor())); |
| 5835 } | 5808 } |
| 5836 } | 5809 } |
| 5837 | 5810 |
| 5838 | 5811 |
| 5839 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 5812 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |
| 5840 bool opt) const { | 5813 bool opt) const { |
| 5841 const intptr_t kNumInputs = 1; | 5814 const intptr_t kNumInputs = 1; |
| 5842 const intptr_t kNumTemps = 1; | 5815 const intptr_t kNumTemps = 1; |
| 5843 | 5816 |
| 5844 LocationSummary* summary = new(zone) LocationSummary( | 5817 LocationSummary* summary = new (zone) |
| 5845 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5818 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5846 | 5819 |
| 5847 summary->set_in(0, Location::RequiresRegister()); | 5820 summary->set_in(0, Location::RequiresRegister()); |
| 5848 summary->set_temp(0, Location::RequiresRegister()); | 5821 summary->set_temp(0, Location::RequiresRegister()); |
| 5849 | 5822 |
| 5850 return summary; | 5823 return summary; |
| 5851 } | 5824 } |
| 5852 | 5825 |
| 5853 | 5826 |
| 5854 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5827 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5855 Register target_address_reg = locs()->temp_slot(0)->reg(); | 5828 Register target_address_reg = locs()->temp_slot(0)->reg(); |
| 5856 | 5829 |
| 5857 // Load code entry point. | 5830 // Load code entry point. |
| 5858 const intptr_t entry_offset = __ CodeSize(); | 5831 const intptr_t entry_offset = __ CodeSize(); |
| 5859 if (Utils::IsInt(21, -entry_offset)) { | 5832 if (Utils::IsInt(21, -entry_offset)) { |
| 5860 __ adr(target_address_reg, Immediate(-entry_offset)); | 5833 __ adr(target_address_reg, Immediate(-entry_offset)); |
| 5861 } else { | 5834 } else { |
| 5862 __ adr(target_address_reg, Immediate(0)); | 5835 __ adr(target_address_reg, Immediate(0)); |
| 5863 __ AddImmediate(target_address_reg, target_address_reg, -entry_offset); | 5836 __ AddImmediate(target_address_reg, target_address_reg, -entry_offset); |
| 5864 } | 5837 } |
| 5865 | 5838 |
| 5866 // Add the offset. | 5839 // Add the offset. |
| 5867 Register offset_reg = locs()->in(0).reg(); | 5840 Register offset_reg = locs()->in(0).reg(); |
| 5868 Operand offset_opr = | 5841 Operand offset_opr = (offset()->definition()->representation() == kTagged) |
| 5869 (offset()->definition()->representation() == kTagged) ? | 5842 ? Operand(offset_reg, ASR, kSmiTagSize) |
| 5870 Operand(offset_reg, ASR, kSmiTagSize) : | 5843 : Operand(offset_reg); |
| 5871 Operand(offset_reg); | |
| 5872 __ add(target_address_reg, target_address_reg, offset_opr); | 5844 __ add(target_address_reg, target_address_reg, offset_opr); |
| 5873 | 5845 |
| 5874 // Jump to the absolute address. | 5846 // Jump to the absolute address. |
| 5875 __ br(target_address_reg); | 5847 __ br(target_address_reg); |
| 5876 } | 5848 } |
| 5877 | 5849 |
| 5878 | 5850 |
| 5879 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, | 5851 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, |
| 5880 bool opt) const { | 5852 bool opt) const { |
| 5881 const intptr_t kNumInputs = 2; | 5853 const intptr_t kNumInputs = 2; |
| 5882 const intptr_t kNumTemps = 0; | 5854 const intptr_t kNumTemps = 0; |
| 5883 if (needs_number_check()) { | 5855 if (needs_number_check()) { |
| 5884 LocationSummary* locs = new(zone) LocationSummary( | 5856 LocationSummary* locs = new (zone) |
| 5885 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5857 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 5886 locs->set_in(0, Location::RegisterLocation(R0)); | 5858 locs->set_in(0, Location::RegisterLocation(R0)); |
| 5887 locs->set_in(1, Location::RegisterLocation(R1)); | 5859 locs->set_in(1, Location::RegisterLocation(R1)); |
| 5888 locs->set_out(0, Location::RegisterLocation(R0)); | 5860 locs->set_out(0, Location::RegisterLocation(R0)); |
| 5889 return locs; | 5861 return locs; |
| 5890 } | 5862 } |
| 5891 LocationSummary* locs = new(zone) LocationSummary( | 5863 LocationSummary* locs = new (zone) |
| 5892 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5864 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5893 locs->set_in(0, Location::RegisterOrConstant(left())); | 5865 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 5894 // Only one of the inputs can be a constant. Choose register if the first one | 5866 // Only one of the inputs can be a constant. Choose register if the first one |
| 5895 // is a constant. | 5867 // is a constant. |
| 5896 locs->set_in(1, locs->in(0).IsConstant() | 5868 locs->set_in(1, locs->in(0).IsConstant() |
| 5897 ? Location::RequiresRegister() | 5869 ? Location::RequiresRegister() |
| 5898 : Location::RegisterOrConstant(right())); | 5870 : Location::RegisterOrConstant(right())); |
| 5899 locs->set_out(0, Location::RequiresRegister()); | 5871 locs->set_out(0, Location::RequiresRegister()); |
| 5900 return locs; | 5872 return locs; |
| 5901 } | 5873 } |
| 5902 | 5874 |
| 5903 | 5875 |
| 5904 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 5876 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 5905 BranchLabels labels) { | 5877 BranchLabels labels) { |
| 5906 Location left = locs()->in(0); | 5878 Location left = locs()->in(0); |
| 5907 Location right = locs()->in(1); | 5879 Location right = locs()->in(1); |
| 5908 ASSERT(!left.IsConstant() || !right.IsConstant()); | 5880 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 5909 Condition true_condition; | 5881 Condition true_condition; |
| 5910 if (left.IsConstant()) { | 5882 if (left.IsConstant()) { |
| 5911 true_condition = compiler->EmitEqualityRegConstCompare(right.reg(), | 5883 true_condition = compiler->EmitEqualityRegConstCompare( |
| 5912 left.constant(), | 5884 right.reg(), left.constant(), needs_number_check(), token_pos()); |
| 5913 needs_number_check(), | |
| 5914 token_pos()); | |
| 5915 } else if (right.IsConstant()) { | 5885 } else if (right.IsConstant()) { |
| 5916 true_condition = compiler->EmitEqualityRegConstCompare(left.reg(), | 5886 true_condition = compiler->EmitEqualityRegConstCompare( |
| 5917 right.constant(), | 5887 left.reg(), right.constant(), needs_number_check(), token_pos()); |
| 5918 needs_number_check(), | |
| 5919 token_pos()); | |
| 5920 } else { | 5888 } else { |
| 5921 true_condition = compiler->EmitEqualityRegRegCompare(left.reg(), | 5889 true_condition = compiler->EmitEqualityRegRegCompare( |
| 5922 right.reg(), | 5890 left.reg(), right.reg(), needs_number_check(), token_pos()); |
| 5923 needs_number_check(), | |
| 5924 token_pos()); | |
| 5925 } | 5891 } |
| 5926 if (kind() != Token::kEQ_STRICT) { | 5892 if (kind() != Token::kEQ_STRICT) { |
| 5927 ASSERT(kind() == Token::kNE_STRICT); | 5893 ASSERT(kind() == Token::kNE_STRICT); |
| 5928 true_condition = NegateCondition(true_condition); | 5894 true_condition = NegateCondition(true_condition); |
| 5929 } | 5895 } |
| 5930 return true_condition; | 5896 return true_condition; |
| 5931 } | 5897 } |
| 5932 | 5898 |
| 5933 | 5899 |
| 5934 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5900 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5935 __ Comment("StrictCompareInstr"); | 5901 __ Comment("StrictCompareInstr"); |
| 5936 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 5902 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 5937 | 5903 |
| 5938 Label is_true, is_false; | 5904 Label is_true, is_false; |
| 5939 BranchLabels labels = { &is_true, &is_false, &is_false }; | 5905 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 5940 Condition true_condition = EmitComparisonCode(compiler, labels); | 5906 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 5941 EmitBranchOnCondition(compiler, true_condition, labels); | 5907 EmitBranchOnCondition(compiler, true_condition, labels); |
| 5942 | 5908 |
| 5943 const Register result = locs()->out(0).reg(); | 5909 const Register result = locs()->out(0).reg(); |
| 5944 Label done; | 5910 Label done; |
| 5945 __ Bind(&is_false); | 5911 __ Bind(&is_false); |
| 5946 __ LoadObject(result, Bool::False()); | 5912 __ LoadObject(result, Bool::False()); |
| 5947 __ b(&done); | 5913 __ b(&done); |
| 5948 __ Bind(&is_true); | 5914 __ Bind(&is_true); |
| 5949 __ LoadObject(result, Bool::True()); | 5915 __ LoadObject(result, Bool::True()); |
| 5950 __ Bind(&done); | 5916 __ Bind(&done); |
| 5951 } | 5917 } |
| 5952 | 5918 |
| 5953 | 5919 |
| 5954 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 5920 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 5955 BranchInstr* branch) { | 5921 BranchInstr* branch) { |
| 5956 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 5922 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 5957 | 5923 |
| 5958 BranchLabels labels = compiler->CreateBranchLabels(branch); | 5924 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 5959 Condition true_condition = EmitComparisonCode(compiler, labels); | 5925 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 5960 EmitBranchOnCondition(compiler, true_condition, labels); | 5926 EmitBranchOnCondition(compiler, true_condition, labels); |
| 5961 } | 5927 } |
| 5962 | 5928 |
| 5963 | 5929 |
| 5964 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 5930 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
| 5965 bool opt) const { | 5931 bool opt) const { |
| 5966 return LocationSummary::Make(zone, | 5932 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
| 5967 1, | |
| 5968 Location::RequiresRegister(), | |
| 5969 LocationSummary::kNoCall); | 5933 LocationSummary::kNoCall); |
| 5970 } | 5934 } |
| 5971 | 5935 |
| 5972 | 5936 |
| 5973 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5937 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5974 const Register value = locs()->in(0).reg(); | 5938 const Register value = locs()->in(0).reg(); |
| 5975 const Register result = locs()->out(0).reg(); | 5939 const Register result = locs()->out(0).reg(); |
| 5976 | 5940 |
| 5977 __ LoadObject(result, Bool::True()); | 5941 __ LoadObject(result, Bool::True()); |
| 5978 __ LoadObject(TMP, Bool::False()); | 5942 __ LoadObject(TMP, Bool::False()); |
| 5979 __ CompareRegisters(result, value); | 5943 __ CompareRegisters(result, value); |
| 5980 __ csel(result, TMP, result, EQ); | 5944 __ csel(result, TMP, result, EQ); |
| 5981 } | 5945 } |
| 5982 | 5946 |
| 5983 | 5947 |
| 5984 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 5948 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
| 5985 bool opt) const { | 5949 bool opt) const { |
| 5986 return MakeCallSummary(zone); | 5950 return MakeCallSummary(zone); |
| 5987 } | 5951 } |
| 5988 | 5952 |
| 5989 | 5953 |
| 5990 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5954 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5991 const Code& stub = Code::ZoneHandle( | 5955 const Code& stub = Code::ZoneHandle( |
| 5992 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 5956 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |
| 5993 const StubEntry stub_entry(stub); | 5957 const StubEntry stub_entry(stub); |
| 5994 compiler->GenerateCall(token_pos(), | 5958 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, |
| 5995 stub_entry, | |
| 5996 RawPcDescriptors::kOther, | |
| 5997 locs()); | 5959 locs()); |
| 5998 compiler->AddStubCallTarget(stub); | 5960 compiler->AddStubCallTarget(stub); |
| 5999 __ Drop(ArgumentCount()); // Discard arguments. | 5961 __ Drop(ArgumentCount()); // Discard arguments. |
| 6000 } | 5962 } |
| 6001 | 5963 |
| 6002 | 5964 |
| 6003 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5965 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6004 ASSERT(!compiler->is_optimizing()); | 5966 ASSERT(!compiler->is_optimizing()); |
| 6005 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); | 5967 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); |
| 6006 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); | 5968 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); |
| 6007 compiler->RecordSafepoint(locs()); | 5969 compiler->RecordSafepoint(locs()); |
| 6008 } | 5970 } |
| 6009 | 5971 |
| 6010 | 5972 |
| 6011 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary( | 5973 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary(Zone* zone, |
| 6012 Zone* zone, bool opt) const { | 5974 bool opt) const { |
| 6013 const intptr_t kNumInputs = 1; | 5975 const intptr_t kNumInputs = 1; |
| 6014 const intptr_t kNumTemps = 0; | 5976 const intptr_t kNumTemps = 0; |
| 6015 LocationSummary* locs = new(zone) LocationSummary( | 5977 LocationSummary* locs = new (zone) |
| 6016 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5978 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 6017 locs->set_in(0, Location::RegisterLocation(R0)); | 5979 locs->set_in(0, Location::RegisterLocation(R0)); |
| 6018 locs->set_out(0, Location::RegisterLocation(R0)); | 5980 locs->set_out(0, Location::RegisterLocation(R0)); |
| 6019 return locs; | 5981 return locs; |
| 6020 } | 5982 } |
| 6021 | 5983 |
| 6022 | 5984 |
| 6023 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5985 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6024 const Register typed_data = locs()->in(0).reg(); | 5986 const Register typed_data = locs()->in(0).reg(); |
| 6025 const Register result = locs()->out(0).reg(); | 5987 const Register result = locs()->out(0).reg(); |
| 6026 __ PushObject(Object::null_object()); | 5988 __ PushObject(Object::null_object()); |
| 6027 __ Push(typed_data); | 5989 __ Push(typed_data); |
| 6028 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, | 5990 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
| 6029 deopt_id(), | 5991 kGrowRegExpStackRuntimeEntry, 1, locs()); |
| 6030 kGrowRegExpStackRuntimeEntry, | |
| 6031 1, | |
| 6032 locs()); | |
| 6033 __ Drop(1); | 5992 __ Drop(1); |
| 6034 __ Pop(result); | 5993 __ Pop(result); |
| 6035 } | 5994 } |
| 6036 | 5995 |
| 6037 | 5996 |
| 6038 } // namespace dart | 5997 } // namespace dart |
| 6039 | 5998 |
| 6040 #endif // defined TARGET_ARCH_ARM64 | 5999 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |