| 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 17 matching lines...) Expand all Loading... |
| 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 = | 32 LocationSummary* result = |
| 33 new (zone) LocationSummary(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 | |
| 39 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, | 38 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, |
| 40 bool opt) const { | 39 bool opt) const { |
| 41 const intptr_t kNumInputs = 1; | 40 const intptr_t kNumInputs = 1; |
| 42 const intptr_t kNumTemps = 0; | 41 const intptr_t kNumTemps = 0; |
| 43 LocationSummary* locs = new (zone) | 42 LocationSummary* locs = new (zone) |
| 44 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 43 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 45 locs->set_in(0, Location::AnyOrConstant(value())); | 44 locs->set_in(0, Location::AnyOrConstant(value())); |
| 46 return locs; | 45 return locs; |
| 47 } | 46 } |
| 48 | 47 |
| 49 | |
| 50 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 48 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 51 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 49 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
| 52 // where PushArgument is handled by BindInstr::EmitNativeCode. | 50 // where PushArgument is handled by BindInstr::EmitNativeCode. |
| 53 if (compiler->is_optimizing()) { | 51 if (compiler->is_optimizing()) { |
| 54 Location value = locs()->in(0); | 52 Location value = locs()->in(0); |
| 55 if (value.IsRegister()) { | 53 if (value.IsRegister()) { |
| 56 __ Push(value.reg()); | 54 __ Push(value.reg()); |
| 57 } else if (value.IsConstant()) { | 55 } else if (value.IsConstant()) { |
| 58 __ PushObject(value.constant()); | 56 __ PushObject(value.constant()); |
| 59 } else { | 57 } else { |
| 60 ASSERT(value.IsStackSlot()); | 58 ASSERT(value.IsStackSlot()); |
| 61 const intptr_t value_offset = value.ToStackSlotOffset(); | 59 const intptr_t value_offset = value.ToStackSlotOffset(); |
| 62 __ LoadFromOffset(TMP, value.base_reg(), value_offset); | 60 __ LoadFromOffset(TMP, value.base_reg(), value_offset); |
| 63 __ Push(TMP); | 61 __ Push(TMP); |
| 64 } | 62 } |
| 65 } | 63 } |
| 66 } | 64 } |
| 67 | 65 |
| 68 | |
| 69 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 66 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 70 const intptr_t kNumInputs = 1; | 67 const intptr_t kNumInputs = 1; |
| 71 const intptr_t kNumTemps = 0; | 68 const intptr_t kNumTemps = 0; |
| 72 LocationSummary* locs = new (zone) | 69 LocationSummary* locs = new (zone) |
| 73 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 70 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 74 locs->set_in(0, Location::RegisterLocation(R0)); | 71 locs->set_in(0, Location::RegisterLocation(R0)); |
| 75 return locs; | 72 return locs; |
| 76 } | 73 } |
| 77 | 74 |
| 78 | |
| 79 // Attempt optimized compilation at return instruction instead of at the entry. | 75 // Attempt optimized compilation at return instruction instead of at the entry. |
| 80 // The entry needs to be patchable, no inlined objects are allowed in the area | 76 // The entry needs to be patchable, no inlined objects are allowed in the area |
| 81 // that will be overwritten by the patch instructions: a branch macro sequence. | 77 // that will be overwritten by the patch instructions: a branch macro sequence. |
| 82 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 78 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 83 const Register result = locs()->in(0).reg(); | 79 const Register result = locs()->in(0).reg(); |
| 84 ASSERT(result == R0); | 80 ASSERT(result == R0); |
| 85 | 81 |
| 86 if (compiler->intrinsic_mode()) { | 82 if (compiler->intrinsic_mode()) { |
| 87 // Intrinsics don't have a frame. | 83 // Intrinsics don't have a frame. |
| 88 __ ret(); | 84 __ ret(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 102 __ Bind(&stack_ok); | 98 __ Bind(&stack_ok); |
| 103 #endif | 99 #endif |
| 104 ASSERT(__ constant_pool_allowed()); | 100 ASSERT(__ constant_pool_allowed()); |
| 105 __ LeaveDartFrame(); // Disallows constant pool use. | 101 __ LeaveDartFrame(); // Disallows constant pool use. |
| 106 __ ret(); | 102 __ ret(); |
| 107 // This ReturnInstr may be emitted out of order by the optimizer. The next | 103 // This ReturnInstr may be emitted out of order by the optimizer. The next |
| 108 // block may be a target expecting a properly set constant pool pointer. | 104 // block may be a target expecting a properly set constant pool pointer. |
| 109 __ set_constant_pool_allowed(true); | 105 __ set_constant_pool_allowed(true); |
| 110 } | 106 } |
| 111 | 107 |
| 112 | |
| 113 static Condition NegateCondition(Condition condition) { | 108 static Condition NegateCondition(Condition condition) { |
| 114 switch (condition) { | 109 switch (condition) { |
| 115 case EQ: | 110 case EQ: |
| 116 return NE; | 111 return NE; |
| 117 case NE: | 112 case NE: |
| 118 return EQ; | 113 return EQ; |
| 119 case LT: | 114 case LT: |
| 120 return GE; | 115 return GE; |
| 121 case LE: | 116 case LE: |
| 122 return GT; | 117 return GT; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 135 case VS: | 130 case VS: |
| 136 return VC; | 131 return VC; |
| 137 case VC: | 132 case VC: |
| 138 return VS; | 133 return VS; |
| 139 default: | 134 default: |
| 140 UNREACHABLE(); | 135 UNREACHABLE(); |
| 141 return EQ; | 136 return EQ; |
| 142 } | 137 } |
| 143 } | 138 } |
| 144 | 139 |
| 145 | |
| 146 // Detect pattern when one value is zero and another is a power of 2. | 140 // Detect pattern when one value is zero and another is a power of 2. |
| 147 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 141 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 148 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 142 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| 149 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 143 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
| 150 } | 144 } |
| 151 | 145 |
| 152 | |
| 153 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, | 146 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, |
| 154 bool opt) const { | 147 bool opt) const { |
| 155 comparison()->InitializeLocationSummary(zone, opt); | 148 comparison()->InitializeLocationSummary(zone, opt); |
| 156 return comparison()->locs(); | 149 return comparison()->locs(); |
| 157 } | 150 } |
| 158 | 151 |
| 159 | |
| 160 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 152 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 161 const Register result = locs()->out(0).reg(); | 153 const Register result = locs()->out(0).reg(); |
| 162 | 154 |
| 163 Location left = locs()->in(0); | 155 Location left = locs()->in(0); |
| 164 Location right = locs()->in(1); | 156 Location right = locs()->in(1); |
| 165 ASSERT(!left.IsConstant() || !right.IsConstant()); | 157 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 166 | 158 |
| 167 // Emit comparison code. This must not overwrite the result register. | 159 // Emit comparison code. This must not overwrite the result register. |
| 168 // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using | 160 // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using |
| 169 // the labels or returning an invalid condition. | 161 // the labels or returning an invalid condition. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 } else { | 193 } else { |
| 202 __ sub(result, result, Operand(1)); | 194 __ sub(result, result, Operand(1)); |
| 203 const int64_t val = Smi::RawValue(true_value) - Smi::RawValue(false_value); | 195 const int64_t val = Smi::RawValue(true_value) - Smi::RawValue(false_value); |
| 204 __ AndImmediate(result, result, val); | 196 __ AndImmediate(result, result, val); |
| 205 if (false_value != 0) { | 197 if (false_value != 0) { |
| 206 __ AddImmediate(result, Smi::RawValue(false_value)); | 198 __ AddImmediate(result, Smi::RawValue(false_value)); |
| 207 } | 199 } |
| 208 } | 200 } |
| 209 } | 201 } |
| 210 | 202 |
| 211 | |
| 212 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 203 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |
| 213 bool opt) const { | 204 bool opt) const { |
| 214 const intptr_t kNumInputs = 1; | 205 const intptr_t kNumInputs = 1; |
| 215 const intptr_t kNumTemps = 0; | 206 const intptr_t kNumTemps = 0; |
| 216 LocationSummary* summary = new (zone) | 207 LocationSummary* summary = new (zone) |
| 217 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 208 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 218 summary->set_in(0, Location::RegisterLocation(R0)); // Function. | 209 summary->set_in(0, Location::RegisterLocation(R0)); // Function. |
| 219 summary->set_out(0, Location::RegisterLocation(R0)); | 210 summary->set_out(0, Location::RegisterLocation(R0)); |
| 220 return summary; | 211 return summary; |
| 221 } | 212 } |
| 222 | 213 |
| 223 | |
| 224 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 214 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 225 // Load arguments descriptor in R4. | 215 // Load arguments descriptor in R4. |
| 226 const intptr_t argument_count = ArgumentCount(); // Includes type args. | 216 const intptr_t argument_count = ArgumentCount(); // Includes type args. |
| 227 const Array& arguments_descriptor = | 217 const Array& arguments_descriptor = |
| 228 Array::ZoneHandle(Z, GetArgumentsDescriptor()); | 218 Array::ZoneHandle(Z, GetArgumentsDescriptor()); |
| 229 __ LoadObject(R4, arguments_descriptor); | 219 __ LoadObject(R4, arguments_descriptor); |
| 230 | 220 |
| 231 // R4: Arguments descriptor. | 221 // R4: Arguments descriptor. |
| 232 // R0: Function. | 222 // R0: Function. |
| 233 ASSERT(locs()->in(0).reg() == R0); | 223 ASSERT(locs()->in(0).reg() == R0); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 248 compiler->AddDeoptIndexAtCall(deopt_id_after); | 238 compiler->AddDeoptIndexAtCall(deopt_id_after); |
| 249 } | 239 } |
| 250 // Add deoptimization continuation point after the call and before the | 240 // Add deoptimization continuation point after the call and before the |
| 251 // arguments are removed. | 241 // arguments are removed. |
| 252 // In optimized code this descriptor is needed for exception handling. | 242 // In optimized code this descriptor is needed for exception handling. |
| 253 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, | 243 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, |
| 254 token_pos()); | 244 token_pos()); |
| 255 __ Drop(argument_count); | 245 __ Drop(argument_count); |
| 256 } | 246 } |
| 257 | 247 |
| 258 | |
| 259 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 248 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
| 260 bool opt) const { | 249 bool opt) const { |
| 261 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), | 250 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), |
| 262 LocationSummary::kNoCall); | 251 LocationSummary::kNoCall); |
| 263 } | 252 } |
| 264 | 253 |
| 265 | |
| 266 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 254 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 267 const Register result = locs()->out(0).reg(); | 255 const Register result = locs()->out(0).reg(); |
| 268 __ LoadFromOffset(result, FP, local().index() * kWordSize); | 256 __ LoadFromOffset(result, FP, local().index() * kWordSize); |
| 269 } | 257 } |
| 270 | 258 |
| 271 | |
| 272 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 259 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |
| 273 bool opt) const { | 260 bool opt) const { |
| 274 return LocationSummary::Make(zone, 1, Location::SameAsFirstInput(), | 261 return LocationSummary::Make(zone, 1, Location::SameAsFirstInput(), |
| 275 LocationSummary::kNoCall); | 262 LocationSummary::kNoCall); |
| 276 } | 263 } |
| 277 | 264 |
| 278 | |
| 279 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 265 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 280 const Register value = locs()->in(0).reg(); | 266 const Register value = locs()->in(0).reg(); |
| 281 const Register result = locs()->out(0).reg(); | 267 const Register result = locs()->out(0).reg(); |
| 282 ASSERT(result == value); // Assert that register assignment is correct. | 268 ASSERT(result == value); // Assert that register assignment is correct. |
| 283 __ StoreToOffset(value, FP, local().index() * kWordSize); | 269 __ StoreToOffset(value, FP, local().index() * kWordSize); |
| 284 } | 270 } |
| 285 | 271 |
| 286 | |
| 287 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 272 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |
| 288 bool opt) const { | 273 bool opt) const { |
| 289 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), | 274 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), |
| 290 LocationSummary::kNoCall); | 275 LocationSummary::kNoCall); |
| 291 } | 276 } |
| 292 | 277 |
| 293 | |
| 294 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 278 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 295 // The register allocator drops constant definitions that have no uses. | 279 // The register allocator drops constant definitions that have no uses. |
| 296 if (!locs()->out(0).IsInvalid()) { | 280 if (!locs()->out(0).IsInvalid()) { |
| 297 const Register result = locs()->out(0).reg(); | 281 const Register result = locs()->out(0).reg(); |
| 298 __ LoadObject(result, value()); | 282 __ LoadObject(result, value()); |
| 299 } | 283 } |
| 300 } | 284 } |
| 301 | 285 |
| 302 | |
| 303 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 286 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
| 304 bool opt) const { | 287 bool opt) const { |
| 305 const intptr_t kNumInputs = 0; | 288 const intptr_t kNumInputs = 0; |
| 306 const Location out = (representation_ == kUnboxedInt32) | 289 const Location out = (representation_ == kUnboxedInt32) |
| 307 ? Location::RequiresRegister() | 290 ? Location::RequiresRegister() |
| 308 : Location::RequiresFpuRegister(); | 291 : Location::RequiresFpuRegister(); |
| 309 return LocationSummary::Make(zone, kNumInputs, out, LocationSummary::kNoCall); | 292 return LocationSummary::Make(zone, kNumInputs, out, LocationSummary::kNoCall); |
| 310 } | 293 } |
| 311 | 294 |
| 312 | |
| 313 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 295 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 314 if (!locs()->out(0).IsInvalid()) { | 296 if (!locs()->out(0).IsInvalid()) { |
| 315 switch (representation_) { | 297 switch (representation_) { |
| 316 case kUnboxedDouble: | 298 case kUnboxedDouble: |
| 317 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { | 299 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { |
| 318 const VRegister dst = locs()->out(0).fpu_reg(); | 300 const VRegister dst = locs()->out(0).fpu_reg(); |
| 319 __ veor(dst, dst, dst); | 301 __ veor(dst, dst, dst); |
| 320 } else { | 302 } else { |
| 321 const VRegister dst = locs()->out(0).fpu_reg(); | 303 const VRegister dst = locs()->out(0).fpu_reg(); |
| 322 __ LoadDImmediate(dst, Double::Cast(value()).value()); | 304 __ LoadDImmediate(dst, Double::Cast(value()).value()); |
| 323 } | 305 } |
| 324 break; | 306 break; |
| 325 case kUnboxedInt32: | 307 case kUnboxedInt32: |
| 326 __ LoadImmediate(locs()->out(0).reg(), | 308 __ LoadImmediate(locs()->out(0).reg(), |
| 327 static_cast<int32_t>(Smi::Cast(value()).Value())); | 309 static_cast<int32_t>(Smi::Cast(value()).Value())); |
| 328 break; | 310 break; |
| 329 default: | 311 default: |
| 330 UNREACHABLE(); | 312 UNREACHABLE(); |
| 331 break; | 313 break; |
| 332 } | 314 } |
| 333 } | 315 } |
| 334 } | 316 } |
| 335 | 317 |
| 336 | |
| 337 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 318 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
| 338 bool opt) const { | 319 bool opt) const { |
| 339 const intptr_t kNumInputs = 3; | 320 const intptr_t kNumInputs = 3; |
| 340 const intptr_t kNumTemps = 0; | 321 const intptr_t kNumTemps = 0; |
| 341 LocationSummary* summary = new (zone) | 322 LocationSummary* summary = new (zone) |
| 342 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 323 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 343 summary->set_in(0, Location::RegisterLocation(R0)); // Value. | 324 summary->set_in(0, Location::RegisterLocation(R0)); // Value. |
| 344 summary->set_in(1, Location::RegisterLocation(R1)); // Instant. type args. | 325 summary->set_in(1, Location::RegisterLocation(R1)); // Instant. type args. |
| 345 summary->set_in(2, Location::RegisterLocation(R2)); // Function type args. | 326 summary->set_in(2, Location::RegisterLocation(R2)); // Function type args. |
| 346 summary->set_out(0, Location::RegisterLocation(R0)); | 327 summary->set_out(0, Location::RegisterLocation(R0)); |
| 347 return summary; | 328 return summary; |
| 348 } | 329 } |
| 349 | 330 |
| 350 | |
| 351 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 331 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
| 352 bool opt) const { | 332 bool opt) const { |
| 353 const intptr_t kNumInputs = 1; | 333 const intptr_t kNumInputs = 1; |
| 354 const intptr_t kNumTemps = 0; | 334 const intptr_t kNumTemps = 0; |
| 355 LocationSummary* locs = new (zone) | 335 LocationSummary* locs = new (zone) |
| 356 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 336 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 357 locs->set_in(0, Location::RegisterLocation(R0)); | 337 locs->set_in(0, Location::RegisterLocation(R0)); |
| 358 locs->set_out(0, Location::RegisterLocation(R0)); | 338 locs->set_out(0, Location::RegisterLocation(R0)); |
| 359 return locs; | 339 return locs; |
| 360 } | 340 } |
| 361 | 341 |
| 362 | |
| 363 static void EmitAssertBoolean(Register reg, | 342 static void EmitAssertBoolean(Register reg, |
| 364 TokenPosition token_pos, | 343 TokenPosition token_pos, |
| 365 intptr_t deopt_id, | 344 intptr_t deopt_id, |
| 366 LocationSummary* locs, | 345 LocationSummary* locs, |
| 367 FlowGraphCompiler* compiler) { | 346 FlowGraphCompiler* compiler) { |
| 368 // Check that the type of the value is allowed in conditional context. | 347 // Check that the type of the value is allowed in conditional context. |
| 369 // Call the runtime if the object is not bool::true or bool::false. | 348 // Call the runtime if the object is not bool::true or bool::false. |
| 370 ASSERT(locs->always_calls()); | 349 ASSERT(locs->always_calls()); |
| 371 Label done; | 350 Label done; |
| 372 | 351 |
| 373 if (Isolate::Current()->type_checks()) { | 352 if (Isolate::Current()->type_checks()) { |
| 374 __ CompareObject(reg, Bool::True()); | 353 __ CompareObject(reg, Bool::True()); |
| 375 __ b(&done, EQ); | 354 __ b(&done, EQ); |
| 376 __ CompareObject(reg, Bool::False()); | 355 __ CompareObject(reg, Bool::False()); |
| 377 __ b(&done, EQ); | 356 __ b(&done, EQ); |
| 378 } else { | 357 } else { |
| 379 ASSERT(Isolate::Current()->asserts()); | 358 ASSERT(Isolate::Current()->asserts()); |
| 380 __ CompareObject(reg, Object::null_instance()); | 359 __ CompareObject(reg, Object::null_instance()); |
| 381 __ b(&done, NE); | 360 __ b(&done, NE); |
| 382 } | 361 } |
| 383 | 362 |
| 384 __ Push(reg); // Push the source object. | 363 __ Push(reg); // Push the source object. |
| 385 compiler->GenerateRuntimeCall(token_pos, deopt_id, | 364 compiler->GenerateRuntimeCall(token_pos, deopt_id, |
| 386 kNonBoolTypeErrorRuntimeEntry, 1, locs); | 365 kNonBoolTypeErrorRuntimeEntry, 1, locs); |
| 387 // We should never return here. | 366 // We should never return here. |
| 388 __ brk(0); | 367 __ brk(0); |
| 389 __ Bind(&done); | 368 __ Bind(&done); |
| 390 } | 369 } |
| 391 | 370 |
| 392 | |
| 393 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 371 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 394 const Register obj = locs()->in(0).reg(); | 372 const Register obj = locs()->in(0).reg(); |
| 395 const Register result = locs()->out(0).reg(); | 373 const Register result = locs()->out(0).reg(); |
| 396 | 374 |
| 397 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 375 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 398 ASSERT(obj == result); | 376 ASSERT(obj == result); |
| 399 } | 377 } |
| 400 | 378 |
| 401 | |
| 402 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 379 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
| 403 switch (kind) { | 380 switch (kind) { |
| 404 case Token::kEQ: | 381 case Token::kEQ: |
| 405 return EQ; | 382 return EQ; |
| 406 case Token::kNE: | 383 case Token::kNE: |
| 407 return NE; | 384 return NE; |
| 408 case Token::kLT: | 385 case Token::kLT: |
| 409 return LT; | 386 return LT; |
| 410 case Token::kGT: | 387 case Token::kGT: |
| 411 return GT; | 388 return GT; |
| 412 case Token::kLTE: | 389 case Token::kLTE: |
| 413 return LE; | 390 return LE; |
| 414 case Token::kGTE: | 391 case Token::kGTE: |
| 415 return GE; | 392 return GE; |
| 416 default: | 393 default: |
| 417 UNREACHABLE(); | 394 UNREACHABLE(); |
| 418 return VS; | 395 return VS; |
| 419 } | 396 } |
| 420 } | 397 } |
| 421 | 398 |
| 422 | |
| 423 static Condition FlipCondition(Condition condition) { | 399 static Condition FlipCondition(Condition condition) { |
| 424 switch (condition) { | 400 switch (condition) { |
| 425 case EQ: | 401 case EQ: |
| 426 return EQ; | 402 return EQ; |
| 427 case NE: | 403 case NE: |
| 428 return NE; | 404 return NE; |
| 429 case LT: | 405 case LT: |
| 430 return GT; | 406 return GT; |
| 431 case LE: | 407 case LE: |
| 432 return GE; | 408 return GE; |
| 433 case GT: | 409 case GT: |
| 434 return LT; | 410 return LT; |
| 435 case GE: | 411 case GE: |
| 436 return LE; | 412 return LE; |
| 437 case CC: | 413 case CC: |
| 438 return HI; | 414 return HI; |
| 439 case LS: | 415 case LS: |
| 440 return CS; | 416 return CS; |
| 441 case HI: | 417 case HI: |
| 442 return CC; | 418 return CC; |
| 443 case CS: | 419 case CS: |
| 444 return LS; | 420 return LS; |
| 445 default: | 421 default: |
| 446 UNREACHABLE(); | 422 UNREACHABLE(); |
| 447 return EQ; | 423 return EQ; |
| 448 } | 424 } |
| 449 } | 425 } |
| 450 | 426 |
| 451 | |
| 452 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 427 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 453 Condition true_condition, | 428 Condition true_condition, |
| 454 BranchLabels labels) { | 429 BranchLabels labels) { |
| 455 if (labels.fall_through == labels.false_label) { | 430 if (labels.fall_through == labels.false_label) { |
| 456 // If the next block is the false successor we will fall through to it. | 431 // If the next block is the false successor we will fall through to it. |
| 457 __ b(labels.true_label, true_condition); | 432 __ b(labels.true_label, true_condition); |
| 458 } else { | 433 } else { |
| 459 // If the next block is not the false successor we will branch to it. | 434 // If the next block is not the false successor we will branch to it. |
| 460 Condition false_condition = NegateCondition(true_condition); | 435 Condition false_condition = NegateCondition(true_condition); |
| 461 __ b(labels.false_label, false_condition); | 436 __ b(labels.false_label, false_condition); |
| 462 | 437 |
| 463 // Fall through or jump to the true successor. | 438 // Fall through or jump to the true successor. |
| 464 if (labels.fall_through != labels.true_label) { | 439 if (labels.fall_through != labels.true_label) { |
| 465 __ b(labels.true_label); | 440 __ b(labels.true_label); |
| 466 } | 441 } |
| 467 } | 442 } |
| 468 } | 443 } |
| 469 | 444 |
| 470 | |
| 471 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 445 static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 472 LocationSummary* locs, | 446 LocationSummary* locs, |
| 473 Token::Kind kind) { | 447 Token::Kind kind) { |
| 474 Location left = locs->in(0); | 448 Location left = locs->in(0); |
| 475 Location right = locs->in(1); | 449 Location right = locs->in(1); |
| 476 ASSERT(!left.IsConstant() || !right.IsConstant()); | 450 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 477 | 451 |
| 478 Condition true_condition = TokenKindToSmiCondition(kind); | 452 Condition true_condition = TokenKindToSmiCondition(kind); |
| 479 | 453 |
| 480 if (left.IsConstant()) { | 454 if (left.IsConstant()) { |
| 481 __ CompareObject(right.reg(), left.constant()); | 455 __ CompareObject(right.reg(), left.constant()); |
| 482 true_condition = FlipCondition(true_condition); | 456 true_condition = FlipCondition(true_condition); |
| 483 } else if (right.IsConstant()) { | 457 } else if (right.IsConstant()) { |
| 484 __ CompareObject(left.reg(), right.constant()); | 458 __ CompareObject(left.reg(), right.constant()); |
| 485 } else { | 459 } else { |
| 486 __ CompareRegisters(left.reg(), right.reg()); | 460 __ CompareRegisters(left.reg(), right.reg()); |
| 487 } | 461 } |
| 488 return true_condition; | 462 return true_condition; |
| 489 } | 463 } |
| 490 | 464 |
| 491 | |
| 492 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 465 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |
| 493 bool opt) const { | 466 bool opt) const { |
| 494 const intptr_t kNumInputs = 2; | 467 const intptr_t kNumInputs = 2; |
| 495 if (operation_cid() == kDoubleCid) { | 468 if (operation_cid() == kDoubleCid) { |
| 496 const intptr_t kNumTemps = 0; | 469 const intptr_t kNumTemps = 0; |
| 497 LocationSummary* locs = new (zone) | 470 LocationSummary* locs = new (zone) |
| 498 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 471 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 499 locs->set_in(0, Location::RequiresFpuRegister()); | 472 locs->set_in(0, Location::RequiresFpuRegister()); |
| 500 locs->set_in(1, Location::RequiresFpuRegister()); | 473 locs->set_in(1, Location::RequiresFpuRegister()); |
| 501 locs->set_out(0, Location::RequiresRegister()); | 474 locs->set_out(0, Location::RequiresRegister()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 512 locs->set_in(1, locs->in(0).IsConstant() | 485 locs->set_in(1, locs->in(0).IsConstant() |
| 513 ? Location::RequiresRegister() | 486 ? Location::RequiresRegister() |
| 514 : Location::RegisterOrConstant(right())); | 487 : Location::RegisterOrConstant(right())); |
| 515 locs->set_out(0, Location::RequiresRegister()); | 488 locs->set_out(0, Location::RequiresRegister()); |
| 516 return locs; | 489 return locs; |
| 517 } | 490 } |
| 518 UNREACHABLE(); | 491 UNREACHABLE(); |
| 519 return NULL; | 492 return NULL; |
| 520 } | 493 } |
| 521 | 494 |
| 522 | |
| 523 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 495 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 524 switch (kind) { | 496 switch (kind) { |
| 525 case Token::kEQ: | 497 case Token::kEQ: |
| 526 return EQ; | 498 return EQ; |
| 527 case Token::kNE: | 499 case Token::kNE: |
| 528 return NE; | 500 return NE; |
| 529 case Token::kLT: | 501 case Token::kLT: |
| 530 return LT; | 502 return LT; |
| 531 case Token::kGT: | 503 case Token::kGT: |
| 532 return GT; | 504 return GT; |
| 533 case Token::kLTE: | 505 case Token::kLTE: |
| 534 return LE; | 506 return LE; |
| 535 case Token::kGTE: | 507 case Token::kGTE: |
| 536 return GE; | 508 return GE; |
| 537 default: | 509 default: |
| 538 UNREACHABLE(); | 510 UNREACHABLE(); |
| 539 return VS; | 511 return VS; |
| 540 } | 512 } |
| 541 } | 513 } |
| 542 | 514 |
| 543 | |
| 544 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 515 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 545 LocationSummary* locs, | 516 LocationSummary* locs, |
| 546 BranchLabels labels, | 517 BranchLabels labels, |
| 547 Token::Kind kind) { | 518 Token::Kind kind) { |
| 548 const VRegister left = locs->in(0).fpu_reg(); | 519 const VRegister left = locs->in(0).fpu_reg(); |
| 549 const VRegister right = locs->in(1).fpu_reg(); | 520 const VRegister right = locs->in(1).fpu_reg(); |
| 550 __ fcmpd(left, right); | 521 __ fcmpd(left, right); |
| 551 Condition true_condition = TokenKindToDoubleCondition(kind); | 522 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 552 if (true_condition != NE) { | 523 if (true_condition != NE) { |
| 553 // Special case for NaN comparison. Result is always false unless | 524 // Special case for NaN comparison. Result is always false unless |
| 554 // relational operator is !=. | 525 // relational operator is !=. |
| 555 __ b(labels.false_label, VS); | 526 __ b(labels.false_label, VS); |
| 556 } | 527 } |
| 557 return true_condition; | 528 return true_condition; |
| 558 } | 529 } |
| 559 | 530 |
| 560 | |
| 561 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 531 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 562 BranchLabels labels) { | 532 BranchLabels labels) { |
| 563 if (operation_cid() == kSmiCid) { | 533 if (operation_cid() == kSmiCid) { |
| 564 return EmitSmiComparisonOp(compiler, locs(), kind()); | 534 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 565 } else { | 535 } else { |
| 566 ASSERT(operation_cid() == kDoubleCid); | 536 ASSERT(operation_cid() == kDoubleCid); |
| 567 return EmitDoubleComparisonOp(compiler, locs(), labels, kind()); | 537 return EmitDoubleComparisonOp(compiler, locs(), labels, kind()); |
| 568 } | 538 } |
| 569 } | 539 } |
| 570 | 540 |
| 571 | |
| 572 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 541 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 573 const intptr_t kNumInputs = 2; | 542 const intptr_t kNumInputs = 2; |
| 574 const intptr_t kNumTemps = 0; | 543 const intptr_t kNumTemps = 0; |
| 575 LocationSummary* locs = new (zone) | 544 LocationSummary* locs = new (zone) |
| 576 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 545 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 577 locs->set_in(0, Location::RequiresRegister()); | 546 locs->set_in(0, Location::RequiresRegister()); |
| 578 // Only one input can be a constant operand. The case of two constant | 547 // Only one input can be a constant operand. The case of two constant |
| 579 // operands should be handled by constant propagation. | 548 // operands should be handled by constant propagation. |
| 580 locs->set_in(1, Location::RegisterOrConstant(right())); | 549 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 581 return locs; | 550 return locs; |
| 582 } | 551 } |
| 583 | 552 |
| 584 | |
| 585 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 553 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 586 BranchLabels labels) { | 554 BranchLabels labels) { |
| 587 const Register left = locs()->in(0).reg(); | 555 const Register left = locs()->in(0).reg(); |
| 588 Location right = locs()->in(1); | 556 Location right = locs()->in(1); |
| 589 if (right.IsConstant()) { | 557 if (right.IsConstant()) { |
| 590 ASSERT(right.constant().IsSmi()); | 558 ASSERT(right.constant().IsSmi()); |
| 591 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); | 559 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); |
| 592 __ TestImmediate(left, imm); | 560 __ TestImmediate(left, imm); |
| 593 } else { | 561 } else { |
| 594 __ tst(left, Operand(right.reg())); | 562 __ tst(left, Operand(right.reg())); |
| 595 } | 563 } |
| 596 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; | 564 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |
| 597 return true_condition; | 565 return true_condition; |
| 598 } | 566 } |
| 599 | 567 |
| 600 | |
| 601 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 568 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
| 602 bool opt) const { | 569 bool opt) const { |
| 603 const intptr_t kNumInputs = 1; | 570 const intptr_t kNumInputs = 1; |
| 604 const intptr_t kNumTemps = 1; | 571 const intptr_t kNumTemps = 1; |
| 605 LocationSummary* locs = new (zone) | 572 LocationSummary* locs = new (zone) |
| 606 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 573 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 607 locs->set_in(0, Location::RequiresRegister()); | 574 locs->set_in(0, Location::RequiresRegister()); |
| 608 locs->set_temp(0, Location::RequiresRegister()); | 575 locs->set_temp(0, Location::RequiresRegister()); |
| 609 locs->set_out(0, Location::RequiresRegister()); | 576 locs->set_out(0, Location::RequiresRegister()); |
| 610 return locs; | 577 return locs; |
| 611 } | 578 } |
| 612 | 579 |
| 613 | |
| 614 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 580 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 615 BranchLabels labels) { | 581 BranchLabels labels) { |
| 616 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 582 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
| 617 const Register val_reg = locs()->in(0).reg(); | 583 const Register val_reg = locs()->in(0).reg(); |
| 618 const Register cid_reg = locs()->temp(0).reg(); | 584 const Register cid_reg = locs()->temp(0).reg(); |
| 619 | 585 |
| 620 Label* deopt = | 586 Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub( |
| 621 CanDeoptimize() | 587 deopt_id(), ICData::kDeoptTestCids, |
| 622 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, | 588 licm_hoisted_ ? ICData::kHoisted : 0) |
| 623 licm_hoisted_ ? ICData::kHoisted : 0) | 589 : NULL; |
| 624 : NULL; | |
| 625 | 590 |
| 626 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 591 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
| 627 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 592 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
| 628 ASSERT(data[0] == kSmiCid); | 593 ASSERT(data[0] == kSmiCid); |
| 629 bool result = data[1] == true_result; | 594 bool result = data[1] == true_result; |
| 630 __ tsti(val_reg, Immediate(kSmiTagMask)); | 595 __ tsti(val_reg, Immediate(kSmiTagMask)); |
| 631 __ b(result ? labels.true_label : labels.false_label, EQ); | 596 __ b(result ? labels.true_label : labels.false_label, EQ); |
| 632 __ LoadClassId(cid_reg, val_reg); | 597 __ LoadClassId(cid_reg, val_reg); |
| 633 | 598 |
| 634 for (intptr_t i = 2; i < data.length(); i += 2) { | 599 for (intptr_t i = 2; i < data.length(); i += 2) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 648 __ b(target); | 613 __ b(target); |
| 649 } | 614 } |
| 650 } else { | 615 } else { |
| 651 __ b(deopt); | 616 __ b(deopt); |
| 652 } | 617 } |
| 653 // Dummy result as this method already did the jump, there's no need | 618 // Dummy result as this method already did the jump, there's no need |
| 654 // for the caller to branch on a condition. | 619 // for the caller to branch on a condition. |
| 655 return kInvalidCondition; | 620 return kInvalidCondition; |
| 656 } | 621 } |
| 657 | 622 |
| 658 | |
| 659 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 623 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
| 660 bool opt) const { | 624 bool opt) const { |
| 661 const intptr_t kNumInputs = 2; | 625 const intptr_t kNumInputs = 2; |
| 662 const intptr_t kNumTemps = 0; | 626 const intptr_t kNumTemps = 0; |
| 663 if (operation_cid() == kDoubleCid) { | 627 if (operation_cid() == kDoubleCid) { |
| 664 LocationSummary* summary = new (zone) | 628 LocationSummary* summary = new (zone) |
| 665 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 629 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 666 summary->set_in(0, Location::RequiresFpuRegister()); | 630 summary->set_in(0, Location::RequiresFpuRegister()); |
| 667 summary->set_in(1, Location::RequiresFpuRegister()); | 631 summary->set_in(1, Location::RequiresFpuRegister()); |
| 668 summary->set_out(0, Location::RequiresRegister()); | 632 summary->set_out(0, Location::RequiresRegister()); |
| 669 return summary; | 633 return summary; |
| 670 } | 634 } |
| 671 ASSERT(operation_cid() == kSmiCid); | 635 ASSERT(operation_cid() == kSmiCid); |
| 672 LocationSummary* summary = new (zone) | 636 LocationSummary* summary = new (zone) |
| 673 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 637 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 674 summary->set_in(0, Location::RegisterOrConstant(left())); | 638 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 675 // Only one input can be a constant operand. The case of two constant | 639 // Only one input can be a constant operand. The case of two constant |
| 676 // operands should be handled by constant propagation. | 640 // operands should be handled by constant propagation. |
| 677 summary->set_in(1, summary->in(0).IsConstant() | 641 summary->set_in(1, summary->in(0).IsConstant() |
| 678 ? Location::RequiresRegister() | 642 ? Location::RequiresRegister() |
| 679 : Location::RegisterOrConstant(right())); | 643 : Location::RegisterOrConstant(right())); |
| 680 summary->set_out(0, Location::RequiresRegister()); | 644 summary->set_out(0, Location::RequiresRegister()); |
| 681 return summary; | 645 return summary; |
| 682 } | 646 } |
| 683 | 647 |
| 684 | |
| 685 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 648 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 686 BranchLabels labels) { | 649 BranchLabels labels) { |
| 687 if (operation_cid() == kSmiCid) { | 650 if (operation_cid() == kSmiCid) { |
| 688 return EmitSmiComparisonOp(compiler, locs(), kind()); | 651 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 689 } else { | 652 } else { |
| 690 ASSERT(operation_cid() == kDoubleCid); | 653 ASSERT(operation_cid() == kDoubleCid); |
| 691 return EmitDoubleComparisonOp(compiler, locs(), labels, kind()); | 654 return EmitDoubleComparisonOp(compiler, locs(), labels, kind()); |
| 692 } | 655 } |
| 693 } | 656 } |
| 694 | 657 |
| 695 | |
| 696 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, | 658 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, |
| 697 bool opt) const { | 659 bool opt) const { |
| 698 return MakeCallSummary(zone); | 660 return MakeCallSummary(zone); |
| 699 } | 661 } |
| 700 | 662 |
| 701 | |
| 702 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 663 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 703 SetupNative(); | 664 SetupNative(); |
| 704 const Register result = locs()->out(0).reg(); | 665 const Register result = locs()->out(0).reg(); |
| 705 | 666 |
| 706 // Push the result place holder initialized to NULL. | 667 // Push the result place holder initialized to NULL. |
| 707 __ PushObject(Object::null_object()); | 668 __ PushObject(Object::null_object()); |
| 708 // Pass a pointer to the first argument in R2. | 669 // Pass a pointer to the first argument in R2. |
| 709 if (!function().HasOptionalParameters()) { | 670 if (!function().HasOptionalParameters()) { |
| 710 __ AddImmediate( | 671 __ AddImmediate( |
| 711 R2, FP, (kParamEndSlotFromFp + function().NumParameters()) * kWordSize); | 672 R2, FP, (kParamEndSlotFromFp + function().NumParameters()) * kWordSize); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 if (link_lazily()) { | 708 if (link_lazily()) { |
| 748 compiler->GeneratePatchableCall(token_pos(), *stub_entry, | 709 compiler->GeneratePatchableCall(token_pos(), *stub_entry, |
| 749 RawPcDescriptors::kOther, locs()); | 710 RawPcDescriptors::kOther, locs()); |
| 750 } else { | 711 } else { |
| 751 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, | 712 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, |
| 752 locs()); | 713 locs()); |
| 753 } | 714 } |
| 754 __ Pop(result); | 715 __ Pop(result); |
| 755 } | 716 } |
| 756 | 717 |
| 757 | |
| 758 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 718 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |
| 759 Zone* zone, | 719 Zone* zone, |
| 760 bool opt) const { | 720 bool opt) const { |
| 761 const intptr_t kNumInputs = 1; | 721 const intptr_t kNumInputs = 1; |
| 762 // TODO(fschneider): Allow immediate operands for the char code. | 722 // TODO(fschneider): Allow immediate operands for the char code. |
| 763 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 723 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 764 LocationSummary::kNoCall); | 724 LocationSummary::kNoCall); |
| 765 } | 725 } |
| 766 | 726 |
| 767 | |
| 768 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 727 void OneByteStringFromCharCodeInstr::EmitNativeCode( |
| 769 FlowGraphCompiler* compiler) { | 728 FlowGraphCompiler* compiler) { |
| 770 ASSERT(compiler->is_optimizing()); | 729 ASSERT(compiler->is_optimizing()); |
| 771 const Register char_code = locs()->in(0).reg(); | 730 const Register char_code = locs()->in(0).reg(); |
| 772 const Register result = locs()->out(0).reg(); | 731 const Register result = locs()->out(0).reg(); |
| 773 | 732 |
| 774 __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset())); | 733 __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset())); |
| 775 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); | 734 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); |
| 776 __ SmiUntag(TMP, char_code); // Untag to use scaled address mode. | 735 __ SmiUntag(TMP, char_code); // Untag to use scaled address mode. |
| 777 __ ldr(result, Address(result, TMP, UXTX, Address::Scaled)); | 736 __ ldr(result, Address(result, TMP, UXTX, Address::Scaled)); |
| 778 } | 737 } |
| 779 | 738 |
| 780 | |
| 781 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 739 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
| 782 bool opt) const { | 740 bool opt) const { |
| 783 const intptr_t kNumInputs = 1; | 741 const intptr_t kNumInputs = 1; |
| 784 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 742 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 785 LocationSummary::kNoCall); | 743 LocationSummary::kNoCall); |
| 786 } | 744 } |
| 787 | 745 |
| 788 | |
| 789 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 746 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 790 ASSERT(cid_ == kOneByteStringCid); | 747 ASSERT(cid_ == kOneByteStringCid); |
| 791 const Register str = locs()->in(0).reg(); | 748 const Register str = locs()->in(0).reg(); |
| 792 const Register result = locs()->out(0).reg(); | 749 const Register result = locs()->out(0).reg(); |
| 793 __ LoadFieldFromOffset(result, str, String::length_offset()); | 750 __ LoadFieldFromOffset(result, str, String::length_offset()); |
| 794 __ ldr(TMP, FieldAddress(str, OneByteString::data_offset()), kUnsignedByte); | 751 __ ldr(TMP, FieldAddress(str, OneByteString::data_offset()), kUnsignedByte); |
| 795 __ CompareImmediate(result, Smi::RawValue(1)); | 752 __ CompareImmediate(result, Smi::RawValue(1)); |
| 796 __ LoadImmediate(result, -1); | 753 __ LoadImmediate(result, -1); |
| 797 __ csel(result, TMP, result, EQ); | 754 __ csel(result, TMP, result, EQ); |
| 798 __ SmiTag(result); | 755 __ SmiTag(result); |
| 799 } | 756 } |
| 800 | 757 |
| 801 | |
| 802 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 758 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |
| 803 bool opt) const { | 759 bool opt) const { |
| 804 const intptr_t kNumInputs = 1; | 760 const intptr_t kNumInputs = 1; |
| 805 const intptr_t kNumTemps = 0; | 761 const intptr_t kNumTemps = 0; |
| 806 LocationSummary* summary = new (zone) | 762 LocationSummary* summary = new (zone) |
| 807 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 763 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 808 summary->set_in(0, Location::RegisterLocation(R0)); | 764 summary->set_in(0, Location::RegisterLocation(R0)); |
| 809 summary->set_out(0, Location::RegisterLocation(R0)); | 765 summary->set_out(0, Location::RegisterLocation(R0)); |
| 810 return summary; | 766 return summary; |
| 811 } | 767 } |
| 812 | 768 |
| 813 | |
| 814 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 769 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 815 const Register array = locs()->in(0).reg(); | 770 const Register array = locs()->in(0).reg(); |
| 816 __ Push(array); | 771 __ Push(array); |
| 817 const int kTypeArgsLen = 0; | 772 const int kTypeArgsLen = 0; |
| 818 const int kNumberOfArguments = 1; | 773 const int kNumberOfArguments = 1; |
| 819 const Array& kNoArgumentNames = Object::null_array(); | 774 const Array& kNoArgumentNames = Object::null_array(); |
| 820 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); | 775 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); |
| 821 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), | 776 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), |
| 822 args_info, locs(), ICData::Handle()); | 777 args_info, locs(), ICData::Handle()); |
| 823 ASSERT(locs()->out(0).reg() == R0); | 778 ASSERT(locs()->out(0).reg() == R0); |
| 824 } | 779 } |
| 825 | 780 |
| 826 | |
| 827 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 781 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |
| 828 bool opt) const { | 782 bool opt) const { |
| 829 const intptr_t kNumInputs = 1; | 783 const intptr_t kNumInputs = 1; |
| 830 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 784 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 831 LocationSummary::kNoCall); | 785 LocationSummary::kNoCall); |
| 832 } | 786 } |
| 833 | 787 |
| 834 | |
| 835 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 788 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 836 const Register obj = locs()->in(0).reg(); | 789 const Register obj = locs()->in(0).reg(); |
| 837 const Register result = locs()->out(0).reg(); | 790 const Register result = locs()->out(0).reg(); |
| 838 if (object()->definition()->representation() == kUntagged) { | 791 if (object()->definition()->representation() == kUntagged) { |
| 839 __ LoadFromOffset(result, obj, offset()); | 792 __ LoadFromOffset(result, obj, offset()); |
| 840 } else { | 793 } else { |
| 841 ASSERT(object()->definition()->representation() == kTagged); | 794 ASSERT(object()->definition()->representation() == kTagged); |
| 842 __ LoadFieldFromOffset(result, obj, offset()); | 795 __ LoadFieldFromOffset(result, obj, offset()); |
| 843 } | 796 } |
| 844 } | 797 } |
| 845 | 798 |
| 846 | |
| 847 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 799 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |
| 848 bool opt) const { | 800 bool opt) const { |
| 849 const intptr_t kNumInputs = 1; | 801 const intptr_t kNumInputs = 1; |
| 850 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 802 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 851 LocationSummary::kNoCall); | 803 LocationSummary::kNoCall); |
| 852 } | 804 } |
| 853 | 805 |
| 854 | |
| 855 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 806 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 856 const Register object = locs()->in(0).reg(); | 807 const Register object = locs()->in(0).reg(); |
| 857 const Register result = locs()->out(0).reg(); | 808 const Register result = locs()->out(0).reg(); |
| 858 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 809 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |
| 859 if (CompileType::Smi().IsAssignableTo(value_type) || | 810 if (CompileType::Smi().IsAssignableTo(value_type) || |
| 860 value_type.IsTypeParameter()) { | 811 value_type.IsTypeParameter()) { |
| 861 __ LoadTaggedClassIdMayBeSmi(result, object); | 812 __ LoadTaggedClassIdMayBeSmi(result, object); |
| 862 } else { | 813 } else { |
| 863 __ LoadClassId(result, object); | 814 __ LoadClassId(result, object); |
| 864 __ SmiTag(result); | 815 __ SmiTag(result); |
| 865 } | 816 } |
| 866 } | 817 } |
| 867 | 818 |
| 868 | |
| 869 CompileType LoadIndexedInstr::ComputeType() const { | 819 CompileType LoadIndexedInstr::ComputeType() const { |
| 870 switch (class_id_) { | 820 switch (class_id_) { |
| 871 case kArrayCid: | 821 case kArrayCid: |
| 872 case kImmutableArrayCid: | 822 case kImmutableArrayCid: |
| 873 return CompileType::Dynamic(); | 823 return CompileType::Dynamic(); |
| 874 | 824 |
| 875 case kTypedDataFloat32ArrayCid: | 825 case kTypedDataFloat32ArrayCid: |
| 876 case kTypedDataFloat64ArrayCid: | 826 case kTypedDataFloat64ArrayCid: |
| 877 return CompileType::FromCid(kDoubleCid); | 827 return CompileType::FromCid(kDoubleCid); |
| 878 case kTypedDataFloat32x4ArrayCid: | 828 case kTypedDataFloat32x4ArrayCid: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 896 case kTypedDataInt32ArrayCid: | 846 case kTypedDataInt32ArrayCid: |
| 897 case kTypedDataUint32ArrayCid: | 847 case kTypedDataUint32ArrayCid: |
| 898 return CompileType::FromCid(kSmiCid); | 848 return CompileType::FromCid(kSmiCid); |
| 899 | 849 |
| 900 default: | 850 default: |
| 901 UNIMPLEMENTED(); | 851 UNIMPLEMENTED(); |
| 902 return CompileType::Dynamic(); | 852 return CompileType::Dynamic(); |
| 903 } | 853 } |
| 904 } | 854 } |
| 905 | 855 |
| 906 | |
| 907 Representation LoadIndexedInstr::representation() const { | 856 Representation LoadIndexedInstr::representation() const { |
| 908 switch (class_id_) { | 857 switch (class_id_) { |
| 909 case kArrayCid: | 858 case kArrayCid: |
| 910 case kImmutableArrayCid: | 859 case kImmutableArrayCid: |
| 911 case kTypedDataInt8ArrayCid: | 860 case kTypedDataInt8ArrayCid: |
| 912 case kTypedDataUint8ArrayCid: | 861 case kTypedDataUint8ArrayCid: |
| 913 case kTypedDataUint8ClampedArrayCid: | 862 case kTypedDataUint8ClampedArrayCid: |
| 914 case kExternalTypedDataUint8ArrayCid: | 863 case kExternalTypedDataUint8ArrayCid: |
| 915 case kExternalTypedDataUint8ClampedArrayCid: | 864 case kExternalTypedDataUint8ClampedArrayCid: |
| 916 case kTypedDataInt16ArrayCid: | 865 case kTypedDataInt16ArrayCid: |
| (...skipping 15 matching lines...) Expand all Loading... |
| 932 case kTypedDataFloat32x4ArrayCid: | 881 case kTypedDataFloat32x4ArrayCid: |
| 933 return kUnboxedFloat32x4; | 882 return kUnboxedFloat32x4; |
| 934 case kTypedDataFloat64x2ArrayCid: | 883 case kTypedDataFloat64x2ArrayCid: |
| 935 return kUnboxedFloat64x2; | 884 return kUnboxedFloat64x2; |
| 936 default: | 885 default: |
| 937 UNIMPLEMENTED(); | 886 UNIMPLEMENTED(); |
| 938 return kTagged; | 887 return kTagged; |
| 939 } | 888 } |
| 940 } | 889 } |
| 941 | 890 |
| 942 | |
| 943 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) { | 891 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) { |
| 944 ConstantInstr* constant = value->definition()->AsConstant(); | 892 ConstantInstr* constant = value->definition()->AsConstant(); |
| 945 if ((constant == NULL) || !constant->value().IsSmi()) { | 893 if ((constant == NULL) || !constant->value().IsSmi()) { |
| 946 return false; | 894 return false; |
| 947 } | 895 } |
| 948 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); | 896 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); |
| 949 const intptr_t scale = Instance::ElementSizeFor(cid); | 897 const intptr_t scale = Instance::ElementSizeFor(cid); |
| 950 const int64_t offset = | 898 const int64_t offset = |
| 951 index * scale + | 899 index * scale + |
| 952 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); | 900 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); |
| 953 if (!Utils::IsInt(32, offset)) { | 901 if (!Utils::IsInt(32, offset)) { |
| 954 return false; | 902 return false; |
| 955 } | 903 } |
| 956 return Address::CanHoldOffset(static_cast<int32_t>(offset), Address::Offset, | 904 return Address::CanHoldOffset(static_cast<int32_t>(offset), Address::Offset, |
| 957 Address::OperandSizeFor(cid)); | 905 Address::OperandSizeFor(cid)); |
| 958 } | 906 } |
| 959 | 907 |
| 960 | |
| 961 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 908 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
| 962 bool opt) const { | 909 bool opt) const { |
| 963 const intptr_t kNumInputs = 2; | 910 const intptr_t kNumInputs = 2; |
| 964 const intptr_t kNumTemps = aligned() ? 0 : 1; | 911 const intptr_t kNumTemps = aligned() ? 0 : 1; |
| 965 LocationSummary* locs = new (zone) | 912 LocationSummary* locs = new (zone) |
| 966 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 913 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 967 locs->set_in(0, Location::RequiresRegister()); | 914 locs->set_in(0, Location::RequiresRegister()); |
| 968 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { | 915 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { |
| 969 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 916 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
| 970 } else { | 917 } else { |
| 971 locs->set_in(1, Location::RequiresRegister()); | 918 locs->set_in(1, Location::RequiresRegister()); |
| 972 } | 919 } |
| 973 if ((representation() == kUnboxedDouble) || | 920 if ((representation() == kUnboxedDouble) || |
| 974 (representation() == kUnboxedFloat32x4) || | 921 (representation() == kUnboxedFloat32x4) || |
| 975 (representation() == kUnboxedInt32x4) || | 922 (representation() == kUnboxedInt32x4) || |
| 976 (representation() == kUnboxedFloat64x2)) { | 923 (representation() == kUnboxedFloat64x2)) { |
| 977 locs->set_out(0, Location::RequiresFpuRegister()); | 924 locs->set_out(0, Location::RequiresFpuRegister()); |
| 978 } else { | 925 } else { |
| 979 locs->set_out(0, Location::RequiresRegister()); | 926 locs->set_out(0, Location::RequiresRegister()); |
| 980 } | 927 } |
| 981 if (!aligned()) { | 928 if (!aligned()) { |
| 982 locs->set_temp(0, Location::RequiresRegister()); | 929 locs->set_temp(0, Location::RequiresRegister()); |
| 983 } | 930 } |
| 984 return locs; | 931 return locs; |
| 985 } | 932 } |
| 986 | 933 |
| 987 | |
| 988 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 934 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 989 // The array register points to the backing store for external arrays. | 935 // The array register points to the backing store for external arrays. |
| 990 const Register array = locs()->in(0).reg(); | 936 const Register array = locs()->in(0).reg(); |
| 991 const Location index = locs()->in(1); | 937 const Location index = locs()->in(1); |
| 992 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); | 938 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |
| 993 | 939 |
| 994 Address element_address(TMP); // Bad address. | 940 Address element_address(TMP); // Bad address. |
| 995 if (aligned()) { | 941 if (aligned()) { |
| 996 element_address = | 942 element_address = |
| 997 index.IsRegister() | 943 index.IsRegister() |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1115 __ SmiTag(result); | 1061 __ SmiTag(result); |
| 1116 break; | 1062 break; |
| 1117 default: | 1063 default: |
| 1118 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1064 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1119 ASSERT(aligned()); | 1065 ASSERT(aligned()); |
| 1120 __ ldr(result, element_address); | 1066 __ ldr(result, element_address); |
| 1121 break; | 1067 break; |
| 1122 } | 1068 } |
| 1123 } | 1069 } |
| 1124 | 1070 |
| 1125 | |
| 1126 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 1071 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |
| 1127 bool opt) const { | 1072 bool opt) const { |
| 1128 const intptr_t kNumInputs = 2; | 1073 const intptr_t kNumInputs = 2; |
| 1129 const intptr_t kNumTemps = 0; | 1074 const intptr_t kNumTemps = 0; |
| 1130 LocationSummary* summary = new (zone) | 1075 LocationSummary* summary = new (zone) |
| 1131 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1076 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1132 summary->set_in(0, Location::RequiresRegister()); | 1077 summary->set_in(0, Location::RequiresRegister()); |
| 1133 summary->set_in(1, Location::RequiresRegister()); | 1078 summary->set_in(1, Location::RequiresRegister()); |
| 1134 summary->set_out(0, Location::RequiresRegister()); | 1079 summary->set_out(0, Location::RequiresRegister()); |
| 1135 return summary; | 1080 return summary; |
| 1136 } | 1081 } |
| 1137 | 1082 |
| 1138 | |
| 1139 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1083 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1140 // The string register points to the backing store for external strings. | 1084 // The string register points to the backing store for external strings. |
| 1141 const Register str = locs()->in(0).reg(); | 1085 const Register str = locs()->in(0).reg(); |
| 1142 const Location index = locs()->in(1); | 1086 const Location index = locs()->in(1); |
| 1143 | 1087 |
| 1144 Address element_address = __ ElementAddressForRegIndex( | 1088 Address element_address = __ ElementAddressForRegIndex( |
| 1145 true, IsExternal(), class_id(), index_scale(), str, index.reg()); | 1089 true, IsExternal(), class_id(), index_scale(), str, index.reg()); |
| 1146 // Warning: element_address may use register TMP as base. | 1090 // Warning: element_address may use register TMP as base. |
| 1147 | 1091 |
| 1148 Register result = locs()->out(0).reg(); | 1092 Register result = locs()->out(0).reg(); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1177 UNREACHABLE(); | 1121 UNREACHABLE(); |
| 1178 } | 1122 } |
| 1179 __ SmiTag(result); | 1123 __ SmiTag(result); |
| 1180 break; | 1124 break; |
| 1181 default: | 1125 default: |
| 1182 UNREACHABLE(); | 1126 UNREACHABLE(); |
| 1183 break; | 1127 break; |
| 1184 } | 1128 } |
| 1185 } | 1129 } |
| 1186 | 1130 |
| 1187 | |
| 1188 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1131 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 1189 intptr_t idx) const { | 1132 intptr_t idx) const { |
| 1190 // Array can be a Dart object or a pointer to external data. | 1133 // Array can be a Dart object or a pointer to external data. |
| 1191 if (idx == 0) return kNoRepresentation; // Flexible input representation. | 1134 if (idx == 0) return kNoRepresentation; // Flexible input representation. |
| 1192 if (idx == 1) return kTagged; // Index is a smi. | 1135 if (idx == 1) return kTagged; // Index is a smi. |
| 1193 ASSERT(idx == 2); | 1136 ASSERT(idx == 2); |
| 1194 switch (class_id_) { | 1137 switch (class_id_) { |
| 1195 case kArrayCid: | 1138 case kArrayCid: |
| 1196 case kOneByteStringCid: | 1139 case kOneByteStringCid: |
| 1197 case kTypedDataInt8ArrayCid: | 1140 case kTypedDataInt8ArrayCid: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1214 case kTypedDataInt32x4ArrayCid: | 1157 case kTypedDataInt32x4ArrayCid: |
| 1215 return kUnboxedInt32x4; | 1158 return kUnboxedInt32x4; |
| 1216 case kTypedDataFloat64x2ArrayCid: | 1159 case kTypedDataFloat64x2ArrayCid: |
| 1217 return kUnboxedFloat64x2; | 1160 return kUnboxedFloat64x2; |
| 1218 default: | 1161 default: |
| 1219 UNREACHABLE(); | 1162 UNREACHABLE(); |
| 1220 return kTagged; | 1163 return kTagged; |
| 1221 } | 1164 } |
| 1222 } | 1165 } |
| 1223 | 1166 |
| 1224 | |
| 1225 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1167 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1226 bool opt) const { | 1168 bool opt) const { |
| 1227 const intptr_t kNumInputs = 3; | 1169 const intptr_t kNumInputs = 3; |
| 1228 const intptr_t kNumTemps = aligned() ? 0 : 2; | 1170 const intptr_t kNumTemps = aligned() ? 0 : 2; |
| 1229 LocationSummary* locs = new (zone) | 1171 LocationSummary* locs = new (zone) |
| 1230 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1172 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1231 locs->set_in(0, Location::RequiresRegister()); | 1173 locs->set_in(0, Location::RequiresRegister()); |
| 1232 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { | 1174 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { |
| 1233 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1175 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
| 1234 } else { | 1176 } else { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1265 UNREACHABLE(); | 1207 UNREACHABLE(); |
| 1266 return NULL; | 1208 return NULL; |
| 1267 } | 1209 } |
| 1268 if (!aligned()) { | 1210 if (!aligned()) { |
| 1269 locs->set_temp(0, Location::RequiresRegister()); | 1211 locs->set_temp(0, Location::RequiresRegister()); |
| 1270 locs->set_temp(1, Location::RequiresRegister()); | 1212 locs->set_temp(1, Location::RequiresRegister()); |
| 1271 } | 1213 } |
| 1272 return locs; | 1214 return locs; |
| 1273 } | 1215 } |
| 1274 | 1216 |
| 1275 | |
| 1276 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1217 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1277 // The array register points to the backing store for external arrays. | 1218 // The array register points to the backing store for external arrays. |
| 1278 const Register array = locs()->in(0).reg(); | 1219 const Register array = locs()->in(0).reg(); |
| 1279 const Location index = locs()->in(1); | 1220 const Location index = locs()->in(1); |
| 1280 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); | 1221 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |
| 1281 const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg(); | 1222 const Register scratch = aligned() ? kNoRegister : locs()->temp(1).reg(); |
| 1282 | 1223 |
| 1283 Address element_address(TMP); // Bad address. | 1224 Address element_address(TMP); // Bad address. |
| 1284 if (aligned()) { | 1225 if (aligned()) { |
| 1285 element_address = | 1226 element_address = |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1405 ASSERT(aligned()); | 1346 ASSERT(aligned()); |
| 1406 const VRegister value_reg = locs()->in(2).fpu_reg(); | 1347 const VRegister value_reg = locs()->in(2).fpu_reg(); |
| 1407 __ fstrq(value_reg, element_address); | 1348 __ fstrq(value_reg, element_address); |
| 1408 break; | 1349 break; |
| 1409 } | 1350 } |
| 1410 default: | 1351 default: |
| 1411 UNREACHABLE(); | 1352 UNREACHABLE(); |
| 1412 } | 1353 } |
| 1413 } | 1354 } |
| 1414 | 1355 |
| 1415 | |
| 1416 static void LoadValueCid(FlowGraphCompiler* compiler, | 1356 static void LoadValueCid(FlowGraphCompiler* compiler, |
| 1417 Register value_cid_reg, | 1357 Register value_cid_reg, |
| 1418 Register value_reg, | 1358 Register value_reg, |
| 1419 Label* value_is_smi = NULL) { | 1359 Label* value_is_smi = NULL) { |
| 1420 Label done; | 1360 Label done; |
| 1421 if (value_is_smi == NULL) { | 1361 if (value_is_smi == NULL) { |
| 1422 __ LoadImmediate(value_cid_reg, kSmiCid); | 1362 __ LoadImmediate(value_cid_reg, kSmiCid); |
| 1423 } | 1363 } |
| 1424 __ tsti(value_reg, Immediate(kSmiTagMask)); | 1364 __ tsti(value_reg, Immediate(kSmiTagMask)); |
| 1425 if (value_is_smi == NULL) { | 1365 if (value_is_smi == NULL) { |
| 1426 __ b(&done, EQ); | 1366 __ b(&done, EQ); |
| 1427 } else { | 1367 } else { |
| 1428 __ b(value_is_smi, EQ); | 1368 __ b(value_is_smi, EQ); |
| 1429 } | 1369 } |
| 1430 __ LoadClassId(value_cid_reg, value_reg); | 1370 __ LoadClassId(value_cid_reg, value_reg); |
| 1431 __ Bind(&done); | 1371 __ Bind(&done); |
| 1432 } | 1372 } |
| 1433 | 1373 |
| 1434 | |
| 1435 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 1374 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |
| 1436 bool opt) const { | 1375 bool opt) const { |
| 1437 const intptr_t kNumInputs = 1; | 1376 const intptr_t kNumInputs = 1; |
| 1438 | 1377 |
| 1439 const intptr_t value_cid = value()->Type()->ToCid(); | 1378 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1440 const intptr_t field_cid = field().guarded_cid(); | 1379 const intptr_t field_cid = field().guarded_cid(); |
| 1441 | 1380 |
| 1442 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); | 1381 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); |
| 1443 | 1382 |
| 1444 const bool needs_value_cid_temp_reg = | 1383 const bool needs_value_cid_temp_reg = |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1458 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 1397 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
| 1459 summary->set_in(0, Location::RequiresRegister()); | 1398 summary->set_in(0, Location::RequiresRegister()); |
| 1460 | 1399 |
| 1461 for (intptr_t i = 0; i < num_temps; i++) { | 1400 for (intptr_t i = 0; i < num_temps; i++) { |
| 1462 summary->set_temp(i, Location::RequiresRegister()); | 1401 summary->set_temp(i, Location::RequiresRegister()); |
| 1463 } | 1402 } |
| 1464 | 1403 |
| 1465 return summary; | 1404 return summary; |
| 1466 } | 1405 } |
| 1467 | 1406 |
| 1468 | |
| 1469 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1407 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1470 ASSERT(sizeof(classid_t) == kInt16Size); | 1408 ASSERT(sizeof(classid_t) == kInt16Size); |
| 1471 const intptr_t value_cid = value()->Type()->ToCid(); | 1409 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1472 const intptr_t field_cid = field().guarded_cid(); | 1410 const intptr_t field_cid = field().guarded_cid(); |
| 1473 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1411 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
| 1474 | 1412 |
| 1475 if (field_cid == kDynamicCid) { | 1413 if (field_cid == kDynamicCid) { |
| 1476 if (Compiler::IsBackgroundCompilation()) { | 1414 if (Compiler::IsBackgroundCompilation()) { |
| 1477 // Field state changed while compiling. | 1415 // Field state changed while compiling. |
| 1478 Compiler::AbortBackgroundCompilation( | 1416 Compiler::AbortBackgroundCompilation( |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1600 __ b(fail, NE); | 1538 __ b(fail, NE); |
| 1601 } else { | 1539 } else { |
| 1602 // Both value's and field's class id is known. | 1540 // Both value's and field's class id is known. |
| 1603 ASSERT((value_cid != field_cid) && (value_cid != nullability)); | 1541 ASSERT((value_cid != field_cid) && (value_cid != nullability)); |
| 1604 __ b(fail); | 1542 __ b(fail); |
| 1605 } | 1543 } |
| 1606 } | 1544 } |
| 1607 __ Bind(&ok); | 1545 __ Bind(&ok); |
| 1608 } | 1546 } |
| 1609 | 1547 |
| 1610 | |
| 1611 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 1548 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |
| 1612 bool opt) const { | 1549 bool opt) const { |
| 1613 const intptr_t kNumInputs = 1; | 1550 const intptr_t kNumInputs = 1; |
| 1614 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1551 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
| 1615 const intptr_t kNumTemps = 3; | 1552 const intptr_t kNumTemps = 3; |
| 1616 LocationSummary* summary = new (zone) | 1553 LocationSummary* summary = new (zone) |
| 1617 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1554 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1618 summary->set_in(0, Location::RequiresRegister()); | 1555 summary->set_in(0, Location::RequiresRegister()); |
| 1619 // We need temporaries for field object, length offset and expected length. | 1556 // We need temporaries for field object, length offset and expected length. |
| 1620 summary->set_temp(0, Location::RequiresRegister()); | 1557 summary->set_temp(0, Location::RequiresRegister()); |
| 1621 summary->set_temp(1, Location::RequiresRegister()); | 1558 summary->set_temp(1, Location::RequiresRegister()); |
| 1622 summary->set_temp(2, Location::RequiresRegister()); | 1559 summary->set_temp(2, Location::RequiresRegister()); |
| 1623 return summary; | 1560 return summary; |
| 1624 } else { | 1561 } else { |
| 1625 LocationSummary* summary = new (zone) | 1562 LocationSummary* summary = new (zone) |
| 1626 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); | 1563 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 1627 summary->set_in(0, Location::RequiresRegister()); | 1564 summary->set_in(0, Location::RequiresRegister()); |
| 1628 return summary; | 1565 return summary; |
| 1629 } | 1566 } |
| 1630 UNREACHABLE(); | 1567 UNREACHABLE(); |
| 1631 } | 1568 } |
| 1632 | 1569 |
| 1633 | |
| 1634 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1570 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1635 if (field().guarded_list_length() == Field::kNoFixedLength) { | 1571 if (field().guarded_list_length() == Field::kNoFixedLength) { |
| 1636 if (Compiler::IsBackgroundCompilation()) { | 1572 if (Compiler::IsBackgroundCompilation()) { |
| 1637 // Field state changed while compiling. | 1573 // Field state changed while compiling. |
| 1638 Compiler::AbortBackgroundCompilation( | 1574 Compiler::AbortBackgroundCompilation( |
| 1639 deopt_id(), | 1575 deopt_id(), |
| 1640 "GuardFieldLengthInstr: field state changed while compiling"); | 1576 "GuardFieldLengthInstr: field state changed while compiling"); |
| 1641 } | 1577 } |
| 1642 ASSERT(!compiler->is_optimizing()); | 1578 ASSERT(!compiler->is_optimizing()); |
| 1643 return; // Nothing to emit. | 1579 return; // Nothing to emit. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1695 ASSERT(field().guarded_list_length_in_object_offset() != | 1631 ASSERT(field().guarded_list_length_in_object_offset() != |
| 1696 Field::kUnknownLengthOffset); | 1632 Field::kUnknownLengthOffset); |
| 1697 | 1633 |
| 1698 __ ldr(TMP, FieldAddress(value_reg, | 1634 __ ldr(TMP, FieldAddress(value_reg, |
| 1699 field().guarded_list_length_in_object_offset())); | 1635 field().guarded_list_length_in_object_offset())); |
| 1700 __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length())); | 1636 __ CompareImmediate(TMP, Smi::RawValue(field().guarded_list_length())); |
| 1701 __ b(deopt, NE); | 1637 __ b(deopt, NE); |
| 1702 } | 1638 } |
| 1703 } | 1639 } |
| 1704 | 1640 |
| 1705 | |
| 1706 class BoxAllocationSlowPath : public SlowPathCode { | 1641 class BoxAllocationSlowPath : public SlowPathCode { |
| 1707 public: | 1642 public: |
| 1708 BoxAllocationSlowPath(Instruction* instruction, | 1643 BoxAllocationSlowPath(Instruction* instruction, |
| 1709 const Class& cls, | 1644 const Class& cls, |
| 1710 Register result) | 1645 Register result) |
| 1711 : instruction_(instruction), cls_(cls), result_(result) {} | 1646 : instruction_(instruction), cls_(cls), result_(result) {} |
| 1712 | 1647 |
| 1713 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1648 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1714 if (Assembler::EmittingComments()) { | 1649 if (Assembler::EmittingComments()) { |
| 1715 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), | 1650 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1749 __ Bind(slow_path->exit_label()); | 1684 __ Bind(slow_path->exit_label()); |
| 1750 } | 1685 } |
| 1751 } | 1686 } |
| 1752 | 1687 |
| 1753 private: | 1688 private: |
| 1754 Instruction* instruction_; | 1689 Instruction* instruction_; |
| 1755 const Class& cls_; | 1690 const Class& cls_; |
| 1756 const Register result_; | 1691 const Register result_; |
| 1757 }; | 1692 }; |
| 1758 | 1693 |
| 1759 | |
| 1760 static void EnsureMutableBox(FlowGraphCompiler* compiler, | 1694 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
| 1761 StoreInstanceFieldInstr* instruction, | 1695 StoreInstanceFieldInstr* instruction, |
| 1762 Register box_reg, | 1696 Register box_reg, |
| 1763 const Class& cls, | 1697 const Class& cls, |
| 1764 Register instance_reg, | 1698 Register instance_reg, |
| 1765 intptr_t offset, | 1699 intptr_t offset, |
| 1766 Register temp) { | 1700 Register temp) { |
| 1767 Label done; | 1701 Label done; |
| 1768 __ LoadFieldFromOffset(box_reg, instance_reg, offset); | 1702 __ LoadFieldFromOffset(box_reg, instance_reg, offset); |
| 1769 __ CompareObject(box_reg, Object::null_object()); | 1703 __ CompareObject(box_reg, Object::null_object()); |
| 1770 __ b(&done, NE); | 1704 __ b(&done, NE); |
| 1771 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); | 1705 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); |
| 1772 __ mov(temp, box_reg); | 1706 __ mov(temp, box_reg); |
| 1773 __ StoreIntoObjectOffset(instance_reg, offset, temp); | 1707 __ StoreIntoObjectOffset(instance_reg, offset, temp); |
| 1774 __ Bind(&done); | 1708 __ Bind(&done); |
| 1775 } | 1709 } |
| 1776 | 1710 |
| 1777 | |
| 1778 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 1711 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |
| 1779 bool opt) const { | 1712 bool opt) const { |
| 1780 const intptr_t kNumInputs = 2; | 1713 const intptr_t kNumInputs = 2; |
| 1781 const intptr_t kNumTemps = | 1714 const intptr_t kNumTemps = |
| 1782 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 2 : 0); | 1715 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 2 : 0); |
| 1783 LocationSummary* summary = new (zone) | 1716 LocationSummary* summary = new (zone) |
| 1784 LocationSummary(zone, kNumInputs, kNumTemps, | 1717 LocationSummary(zone, kNumInputs, kNumTemps, |
| 1785 ((IsUnboxedStore() && opt && is_initialization()) || | 1718 ((IsUnboxedStore() && opt && is_initialization()) || |
| 1786 IsPotentialUnboxedStore()) | 1719 IsPotentialUnboxedStore()) |
| 1787 ? LocationSummary::kCallOnSlowPath | 1720 ? LocationSummary::kCallOnSlowPath |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1798 summary->set_temp(0, Location::RequiresRegister()); | 1731 summary->set_temp(0, Location::RequiresRegister()); |
| 1799 summary->set_temp(1, Location::RequiresRegister()); | 1732 summary->set_temp(1, Location::RequiresRegister()); |
| 1800 } else { | 1733 } else { |
| 1801 summary->set_in(1, ShouldEmitStoreBarrier() | 1734 summary->set_in(1, ShouldEmitStoreBarrier() |
| 1802 ? Location::WritableRegister() | 1735 ? Location::WritableRegister() |
| 1803 : Location::RegisterOrConstant(value())); | 1736 : Location::RegisterOrConstant(value())); |
| 1804 } | 1737 } |
| 1805 return summary; | 1738 return summary; |
| 1806 } | 1739 } |
| 1807 | 1740 |
| 1808 | |
| 1809 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1741 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1810 ASSERT(sizeof(classid_t) == kInt16Size); | 1742 ASSERT(sizeof(classid_t) == kInt16Size); |
| 1811 Label skip_store; | 1743 Label skip_store; |
| 1812 | 1744 |
| 1813 const Register instance_reg = locs()->in(0).reg(); | 1745 const Register instance_reg = locs()->in(0).reg(); |
| 1814 | 1746 |
| 1815 if (IsUnboxedStore() && compiler->is_optimizing()) { | 1747 if (IsUnboxedStore() && compiler->is_optimizing()) { |
| 1816 const VRegister value = locs()->in(1).fpu_reg(); | 1748 const VRegister value = locs()->in(1).fpu_reg(); |
| 1817 const Register temp = locs()->temp(0).reg(); | 1749 const Register temp = locs()->temp(0).reg(); |
| 1818 const Register temp2 = locs()->temp(1).reg(); | 1750 const Register temp2 = locs()->temp(1).reg(); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1951 locs()->in(1).constant()); | 1883 locs()->in(1).constant()); |
| 1952 } else { | 1884 } else { |
| 1953 const Register value_reg = locs()->in(1).reg(); | 1885 const Register value_reg = locs()->in(1).reg(); |
| 1954 __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes_, | 1886 __ StoreIntoObjectOffsetNoBarrier(instance_reg, offset_in_bytes_, |
| 1955 value_reg); | 1887 value_reg); |
| 1956 } | 1888 } |
| 1957 } | 1889 } |
| 1958 __ Bind(&skip_store); | 1890 __ Bind(&skip_store); |
| 1959 } | 1891 } |
| 1960 | 1892 |
| 1961 | |
| 1962 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 1893 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 1963 bool opt) const { | 1894 bool opt) const { |
| 1964 const intptr_t kNumInputs = 1; | 1895 const intptr_t kNumInputs = 1; |
| 1965 const intptr_t kNumTemps = 0; | 1896 const intptr_t kNumTemps = 0; |
| 1966 LocationSummary* summary = new (zone) | 1897 LocationSummary* summary = new (zone) |
| 1967 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1898 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1968 summary->set_in(0, Location::RequiresRegister()); | 1899 summary->set_in(0, Location::RequiresRegister()); |
| 1969 summary->set_out(0, Location::RequiresRegister()); | 1900 summary->set_out(0, Location::RequiresRegister()); |
| 1970 return summary; | 1901 return summary; |
| 1971 } | 1902 } |
| 1972 | 1903 |
| 1973 | |
| 1974 // When the parser is building an implicit static getter for optimization, | 1904 // When the parser is building an implicit static getter for optimization, |
| 1975 // it can generate a function body where deoptimization ids do not line up | 1905 // it can generate a function body where deoptimization ids do not line up |
| 1976 // with the unoptimized code. | 1906 // with the unoptimized code. |
| 1977 // | 1907 // |
| 1978 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 1908 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
| 1979 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1909 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1980 const Register field = locs()->in(0).reg(); | 1910 const Register field = locs()->in(0).reg(); |
| 1981 const Register result = locs()->out(0).reg(); | 1911 const Register result = locs()->out(0).reg(); |
| 1982 __ LoadFieldFromOffset(result, field, Field::static_value_offset()); | 1912 __ LoadFieldFromOffset(result, field, Field::static_value_offset()); |
| 1983 } | 1913 } |
| 1984 | 1914 |
| 1985 | |
| 1986 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 1915 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 1987 bool opt) const { | 1916 bool opt) const { |
| 1988 LocationSummary* locs = | 1917 LocationSummary* locs = |
| 1989 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); | 1918 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); |
| 1990 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 1919 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 1991 : Location::RequiresRegister()); | 1920 : Location::RequiresRegister()); |
| 1992 locs->set_temp(0, Location::RequiresRegister()); | 1921 locs->set_temp(0, Location::RequiresRegister()); |
| 1993 return locs; | 1922 return locs; |
| 1994 } | 1923 } |
| 1995 | 1924 |
| 1996 | |
| 1997 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1925 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1998 const Register value = locs()->in(0).reg(); | 1926 const Register value = locs()->in(0).reg(); |
| 1999 const Register temp = locs()->temp(0).reg(); | 1927 const Register temp = locs()->temp(0).reg(); |
| 2000 | 1928 |
| 2001 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 1929 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
| 2002 if (this->value()->NeedsStoreBuffer()) { | 1930 if (this->value()->NeedsStoreBuffer()) { |
| 2003 __ StoreIntoObjectOffset(temp, Field::static_value_offset(), value, | 1931 __ StoreIntoObjectOffset(temp, Field::static_value_offset(), value, |
| 2004 CanValueBeSmi()); | 1932 CanValueBeSmi()); |
| 2005 } else { | 1933 } else { |
| 2006 __ StoreIntoObjectOffsetNoBarrier(temp, Field::static_value_offset(), | 1934 __ StoreIntoObjectOffsetNoBarrier(temp, Field::static_value_offset(), |
| 2007 value); | 1935 value); |
| 2008 } | 1936 } |
| 2009 } | 1937 } |
| 2010 | 1938 |
| 2011 | |
| 2012 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 1939 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
| 2013 bool opt) const { | 1940 bool opt) const { |
| 2014 const intptr_t kNumInputs = 3; | 1941 const intptr_t kNumInputs = 3; |
| 2015 const intptr_t kNumTemps = 0; | 1942 const intptr_t kNumTemps = 0; |
| 2016 LocationSummary* summary = new (zone) | 1943 LocationSummary* summary = new (zone) |
| 2017 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 1944 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2018 summary->set_in(0, Location::RegisterLocation(R0)); // Instance. | 1945 summary->set_in(0, Location::RegisterLocation(R0)); // Instance. |
| 2019 summary->set_in(1, Location::RegisterLocation(R1)); // Instant. type args. | 1946 summary->set_in(1, Location::RegisterLocation(R1)); // Instant. type args. |
| 2020 summary->set_in(2, Location::RegisterLocation(R2)); // Function type args. | 1947 summary->set_in(2, Location::RegisterLocation(R2)); // Function type args. |
| 2021 summary->set_out(0, Location::RegisterLocation(R0)); | 1948 summary->set_out(0, Location::RegisterLocation(R0)); |
| 2022 return summary; | 1949 return summary; |
| 2023 } | 1950 } |
| 2024 | 1951 |
| 2025 | |
| 2026 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1952 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2027 ASSERT(locs()->in(0).reg() == R0); // Value. | 1953 ASSERT(locs()->in(0).reg() == R0); // Value. |
| 2028 ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments. | 1954 ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments. |
| 2029 ASSERT(locs()->in(2).reg() == R2); // Function type arguments. | 1955 ASSERT(locs()->in(2).reg() == R2); // Function type arguments. |
| 2030 | 1956 |
| 2031 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs()); | 1957 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs()); |
| 2032 ASSERT(locs()->out(0).reg() == R0); | 1958 ASSERT(locs()->out(0).reg() == R0); |
| 2033 } | 1959 } |
| 2034 | 1960 |
| 2035 | |
| 2036 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 1961 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
| 2037 bool opt) const { | 1962 bool opt) const { |
| 2038 const intptr_t kNumInputs = 2; | 1963 const intptr_t kNumInputs = 2; |
| 2039 const intptr_t kNumTemps = 0; | 1964 const intptr_t kNumTemps = 0; |
| 2040 LocationSummary* locs = new (zone) | 1965 LocationSummary* locs = new (zone) |
| 2041 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 1966 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2042 locs->set_in(kElementTypePos, Location::RegisterLocation(R1)); | 1967 locs->set_in(kElementTypePos, Location::RegisterLocation(R1)); |
| 2043 locs->set_in(kLengthPos, Location::RegisterLocation(R2)); | 1968 locs->set_in(kLengthPos, Location::RegisterLocation(R2)); |
| 2044 locs->set_out(0, Location::RegisterLocation(R0)); | 1969 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2045 return locs; | 1970 return locs; |
| 2046 } | 1971 } |
| 2047 | 1972 |
| 2048 | |
| 2049 // Inlines array allocation for known constant values. | 1973 // Inlines array allocation for known constant values. |
| 2050 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 1974 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
| 2051 intptr_t num_elements, | 1975 intptr_t num_elements, |
| 2052 Label* slow_path, | 1976 Label* slow_path, |
| 2053 Label* done) { | 1977 Label* done) { |
| 2054 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. | 1978 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. |
| 2055 const Register kLengthReg = R2; | 1979 const Register kLengthReg = R2; |
| 2056 const Register kElemTypeReg = R1; | 1980 const Register kElemTypeReg = R1; |
| 2057 const intptr_t instance_size = Array::InstanceSize(num_elements); | 1981 const intptr_t instance_size = Array::InstanceSize(num_elements); |
| 2058 | 1982 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2095 __ b(&end_loop, CS); | 2019 __ b(&end_loop, CS); |
| 2096 __ str(R6, Address(R8)); | 2020 __ str(R6, Address(R8)); |
| 2097 __ AddImmediate(R8, kWordSize); | 2021 __ AddImmediate(R8, kWordSize); |
| 2098 __ b(&init_loop); | 2022 __ b(&init_loop); |
| 2099 __ Bind(&end_loop); | 2023 __ Bind(&end_loop); |
| 2100 } | 2024 } |
| 2101 } | 2025 } |
| 2102 __ b(done); | 2026 __ b(done); |
| 2103 } | 2027 } |
| 2104 | 2028 |
| 2105 | |
| 2106 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2029 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2107 const Register kLengthReg = R2; | 2030 const Register kLengthReg = R2; |
| 2108 const Register kElemTypeReg = R1; | 2031 const Register kElemTypeReg = R1; |
| 2109 const Register kResultReg = R0; | 2032 const Register kResultReg = R0; |
| 2110 | 2033 |
| 2111 ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg); | 2034 ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg); |
| 2112 ASSERT(locs()->in(kLengthPos).reg() == kLengthReg); | 2035 ASSERT(locs()->in(kLengthPos).reg() == kLengthReg); |
| 2113 | 2036 |
| 2114 if (compiler->is_optimizing() && !FLAG_precompiled_mode && | 2037 if (compiler->is_optimizing() && !FLAG_precompiled_mode && |
| 2115 num_elements()->BindsToConstant() && | 2038 num_elements()->BindsToConstant() && |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2132 } | 2055 } |
| 2133 const Code& stub = Code::ZoneHandle(compiler->zone(), | 2056 const Code& stub = Code::ZoneHandle(compiler->zone(), |
| 2134 StubCode::AllocateArray_entry()->code()); | 2057 StubCode::AllocateArray_entry()->code()); |
| 2135 compiler->AddStubCallTarget(stub); | 2058 compiler->AddStubCallTarget(stub); |
| 2136 compiler->GenerateCallWithDeopt(token_pos(), deopt_id(), | 2059 compiler->GenerateCallWithDeopt(token_pos(), deopt_id(), |
| 2137 *StubCode::AllocateArray_entry(), | 2060 *StubCode::AllocateArray_entry(), |
| 2138 RawPcDescriptors::kOther, locs()); | 2061 RawPcDescriptors::kOther, locs()); |
| 2139 ASSERT(locs()->out(0).reg() == kResultReg); | 2062 ASSERT(locs()->out(0).reg() == kResultReg); |
| 2140 } | 2063 } |
| 2141 | 2064 |
| 2142 | |
| 2143 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 2065 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |
| 2144 bool opt) const { | 2066 bool opt) const { |
| 2145 const intptr_t kNumInputs = 1; | 2067 const intptr_t kNumInputs = 1; |
| 2146 const intptr_t kNumTemps = | 2068 const intptr_t kNumTemps = |
| 2147 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 1 : 0); | 2069 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 1 : 0); |
| 2148 LocationSummary* locs = new (zone) LocationSummary( | 2070 LocationSummary* locs = new (zone) LocationSummary( |
| 2149 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) | 2071 zone, kNumInputs, kNumTemps, |
| 2150 ? LocationSummary::kNoCall | 2072 (opt && !IsPotentialUnboxedLoad()) ? LocationSummary::kNoCall |
| 2151 : LocationSummary::kCallOnSlowPath); | 2073 : LocationSummary::kCallOnSlowPath); |
| 2152 | 2074 |
| 2153 locs->set_in(0, Location::RequiresRegister()); | 2075 locs->set_in(0, Location::RequiresRegister()); |
| 2154 | 2076 |
| 2155 if (IsUnboxedLoad() && opt) { | 2077 if (IsUnboxedLoad() && opt) { |
| 2156 locs->set_temp(0, Location::RequiresRegister()); | 2078 locs->set_temp(0, Location::RequiresRegister()); |
| 2157 } else if (IsPotentialUnboxedLoad()) { | 2079 } else if (IsPotentialUnboxedLoad()) { |
| 2158 locs->set_temp(0, Location::RequiresRegister()); | 2080 locs->set_temp(0, Location::RequiresRegister()); |
| 2159 } | 2081 } |
| 2160 locs->set_out(0, Location::RequiresRegister()); | 2082 locs->set_out(0, Location::RequiresRegister()); |
| 2161 return locs; | 2083 return locs; |
| 2162 } | 2084 } |
| 2163 | 2085 |
| 2164 | |
| 2165 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2086 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2166 ASSERT(sizeof(classid_t) == kInt16Size); | 2087 ASSERT(sizeof(classid_t) == kInt16Size); |
| 2167 const Register instance_reg = locs()->in(0).reg(); | 2088 const Register instance_reg = locs()->in(0).reg(); |
| 2168 if (IsUnboxedLoad() && compiler->is_optimizing()) { | 2089 if (IsUnboxedLoad() && compiler->is_optimizing()) { |
| 2169 const VRegister result = locs()->out(0).fpu_reg(); | 2090 const VRegister result = locs()->out(0).fpu_reg(); |
| 2170 const Register temp = locs()->temp(0).reg(); | 2091 const Register temp = locs()->temp(0).reg(); |
| 2171 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); | 2092 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); |
| 2172 const intptr_t cid = field()->UnboxedFieldCid(); | 2093 const intptr_t cid = field()->UnboxedFieldCid(); |
| 2173 switch (cid) { | 2094 switch (cid) { |
| 2174 case kDoubleCid: | 2095 case kDoubleCid: |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2256 __ StoreQFieldToOffset(VTMP, result_reg, Float64x2::value_offset()); | 2177 __ StoreQFieldToOffset(VTMP, result_reg, Float64x2::value_offset()); |
| 2257 __ b(&done); | 2178 __ b(&done); |
| 2258 } | 2179 } |
| 2259 | 2180 |
| 2260 __ Bind(&load_pointer); | 2181 __ Bind(&load_pointer); |
| 2261 } | 2182 } |
| 2262 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); | 2183 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); |
| 2263 __ Bind(&done); | 2184 __ Bind(&done); |
| 2264 } | 2185 } |
| 2265 | 2186 |
| 2266 | |
| 2267 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2187 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
| 2268 bool opt) const { | 2188 bool opt) const { |
| 2269 const intptr_t kNumInputs = 2; | 2189 const intptr_t kNumInputs = 2; |
| 2270 const intptr_t kNumTemps = 0; | 2190 const intptr_t kNumTemps = 0; |
| 2271 LocationSummary* locs = new (zone) | 2191 LocationSummary* locs = new (zone) |
| 2272 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2192 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2273 locs->set_in(0, Location::RegisterLocation(R0)); // Instant. type args. | 2193 locs->set_in(0, Location::RegisterLocation(R0)); // Instant. type args. |
| 2274 locs->set_in(1, Location::RegisterLocation(R1)); // Function type args. | 2194 locs->set_in(1, Location::RegisterLocation(R1)); // Function type args. |
| 2275 locs->set_out(0, Location::RegisterLocation(R0)); | 2195 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2276 return locs; | 2196 return locs; |
| 2277 } | 2197 } |
| 2278 | 2198 |
| 2279 | |
| 2280 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2199 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2281 const Register instantiator_type_args_reg = locs()->in(0).reg(); | 2200 const Register instantiator_type_args_reg = locs()->in(0).reg(); |
| 2282 const Register function_type_args_reg = locs()->in(1).reg(); | 2201 const Register function_type_args_reg = locs()->in(1).reg(); |
| 2283 const Register result_reg = locs()->out(0).reg(); | 2202 const Register result_reg = locs()->out(0).reg(); |
| 2284 | 2203 |
| 2285 // 'instantiator_type_args_reg' is a TypeArguments object (or null). | 2204 // 'instantiator_type_args_reg' is a TypeArguments object (or null). |
| 2286 // 'function_type_args_reg' is a TypeArguments object (or null). | 2205 // 'function_type_args_reg' is a TypeArguments object (or null). |
| 2287 // A runtime call to instantiate the type is required. | 2206 // A runtime call to instantiate the type is required. |
| 2288 __ PushObject(Object::null_object()); // Make room for the result. | 2207 __ PushObject(Object::null_object()); // Make room for the result. |
| 2289 __ PushObject(type()); | 2208 __ PushObject(type()); |
| 2290 __ PushPair(function_type_args_reg, instantiator_type_args_reg); | 2209 __ PushPair(function_type_args_reg, instantiator_type_args_reg); |
| 2291 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2210 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2292 kInstantiateTypeRuntimeEntry, 3, locs()); | 2211 kInstantiateTypeRuntimeEntry, 3, locs()); |
| 2293 __ Drop(3); // Drop 2 type argument vectors and uninstantiated type. | 2212 __ Drop(3); // Drop 2 type argument vectors and uninstantiated type. |
| 2294 __ Pop(result_reg); // Pop instantiated type. | 2213 __ Pop(result_reg); // Pop instantiated type. |
| 2295 ASSERT(instantiator_type_args_reg == result_reg); | 2214 ASSERT(instantiator_type_args_reg == result_reg); |
| 2296 } | 2215 } |
| 2297 | 2216 |
| 2298 | |
| 2299 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2217 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
| 2300 Zone* zone, | 2218 Zone* zone, |
| 2301 bool opt) const { | 2219 bool opt) const { |
| 2302 const intptr_t kNumInputs = 2; | 2220 const intptr_t kNumInputs = 2; |
| 2303 const intptr_t kNumTemps = 0; | 2221 const intptr_t kNumTemps = 0; |
| 2304 LocationSummary* locs = new (zone) | 2222 LocationSummary* locs = new (zone) |
| 2305 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2223 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2306 locs->set_in(0, Location::RegisterLocation(R0)); // Instant. type args. | 2224 locs->set_in(0, Location::RegisterLocation(R0)); // Instant. type args. |
| 2307 locs->set_in(1, Location::RegisterLocation(R1)); // Function type args. | 2225 locs->set_in(1, Location::RegisterLocation(R1)); // Function type args. |
| 2308 locs->set_out(0, Location::RegisterLocation(R0)); | 2226 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2309 return locs; | 2227 return locs; |
| 2310 } | 2228 } |
| 2311 | 2229 |
| 2312 | |
| 2313 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2230 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
| 2314 FlowGraphCompiler* compiler) { | 2231 FlowGraphCompiler* compiler) { |
| 2315 const Register instantiator_type_args_reg = locs()->in(0).reg(); | 2232 const Register instantiator_type_args_reg = locs()->in(0).reg(); |
| 2316 const Register function_type_args_reg = locs()->in(1).reg(); | 2233 const Register function_type_args_reg = locs()->in(1).reg(); |
| 2317 const Register result_reg = locs()->out(0).reg(); | 2234 const Register result_reg = locs()->out(0).reg(); |
| 2318 ASSERT(instantiator_type_args_reg == R0); | 2235 ASSERT(instantiator_type_args_reg == R0); |
| 2319 ASSERT(instantiator_type_args_reg == result_reg); | 2236 ASSERT(instantiator_type_args_reg == result_reg); |
| 2320 | 2237 |
| 2321 // 'instantiator_type_args_reg' is a TypeArguments object (or null). | 2238 // 'instantiator_type_args_reg' is a TypeArguments object (or null). |
| 2322 // 'function_type_args_reg' is a TypeArguments object (or null). | 2239 // 'function_type_args_reg' is a TypeArguments object (or null). |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2369 __ PushObject(type_arguments()); | 2286 __ PushObject(type_arguments()); |
| 2370 __ PushPair(function_type_args_reg, instantiator_type_args_reg); | 2287 __ PushPair(function_type_args_reg, instantiator_type_args_reg); |
| 2371 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2288 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2372 kInstantiateTypeArgumentsRuntimeEntry, 3, | 2289 kInstantiateTypeArgumentsRuntimeEntry, 3, |
| 2373 locs()); | 2290 locs()); |
| 2374 __ Drop(3); // Drop 2 type argument vectors and uninstantiated args. | 2291 __ Drop(3); // Drop 2 type argument vectors and uninstantiated args. |
| 2375 __ Pop(result_reg); // Pop instantiated type arguments. | 2292 __ Pop(result_reg); // Pop instantiated type arguments. |
| 2376 __ Bind(&type_arguments_instantiated); | 2293 __ Bind(&type_arguments_instantiated); |
| 2377 } | 2294 } |
| 2378 | 2295 |
| 2379 | |
| 2380 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2296 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
| 2381 Zone* zone, | 2297 Zone* zone, |
| 2382 bool opt) const { | 2298 bool opt) const { |
| 2383 ASSERT(opt); | 2299 ASSERT(opt); |
| 2384 const intptr_t kNumInputs = 0; | 2300 const intptr_t kNumInputs = 0; |
| 2385 const intptr_t kNumTemps = 3; | 2301 const intptr_t kNumTemps = 3; |
| 2386 LocationSummary* locs = new (zone) LocationSummary( | 2302 LocationSummary* locs = new (zone) LocationSummary( |
| 2387 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2303 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2388 locs->set_temp(0, Location::RegisterLocation(R1)); | 2304 locs->set_temp(0, Location::RegisterLocation(R1)); |
| 2389 locs->set_temp(1, Location::RegisterLocation(R2)); | 2305 locs->set_temp(1, Location::RegisterLocation(R2)); |
| 2390 locs->set_temp(2, Location::RegisterLocation(R3)); | 2306 locs->set_temp(2, Location::RegisterLocation(R3)); |
| 2391 locs->set_out(0, Location::RegisterLocation(R0)); | 2307 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2392 return locs; | 2308 return locs; |
| 2393 } | 2309 } |
| 2394 | 2310 |
| 2395 | |
| 2396 class AllocateContextSlowPath : public SlowPathCode { | 2311 class AllocateContextSlowPath : public SlowPathCode { |
| 2397 public: | 2312 public: |
| 2398 explicit AllocateContextSlowPath( | 2313 explicit AllocateContextSlowPath( |
| 2399 AllocateUninitializedContextInstr* instruction) | 2314 AllocateUninitializedContextInstr* instruction) |
| 2400 : instruction_(instruction) {} | 2315 : instruction_(instruction) {} |
| 2401 | 2316 |
| 2402 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2317 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2403 __ Comment("AllocateContextSlowPath"); | 2318 __ Comment("AllocateContextSlowPath"); |
| 2404 __ Bind(entry_label()); | 2319 __ Bind(entry_label()); |
| 2405 | 2320 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2417 RawPcDescriptors::kOther, locs); | 2332 RawPcDescriptors::kOther, locs); |
| 2418 ASSERT(instruction_->locs()->out(0).reg() == R0); | 2333 ASSERT(instruction_->locs()->out(0).reg() == R0); |
| 2419 compiler->RestoreLiveRegisters(instruction_->locs()); | 2334 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2420 __ b(exit_label()); | 2335 __ b(exit_label()); |
| 2421 } | 2336 } |
| 2422 | 2337 |
| 2423 private: | 2338 private: |
| 2424 AllocateUninitializedContextInstr* instruction_; | 2339 AllocateUninitializedContextInstr* instruction_; |
| 2425 }; | 2340 }; |
| 2426 | 2341 |
| 2427 | |
| 2428 void AllocateUninitializedContextInstr::EmitNativeCode( | 2342 void AllocateUninitializedContextInstr::EmitNativeCode( |
| 2429 FlowGraphCompiler* compiler) { | 2343 FlowGraphCompiler* compiler) { |
| 2430 Register temp0 = locs()->temp(0).reg(); | 2344 Register temp0 = locs()->temp(0).reg(); |
| 2431 Register temp1 = locs()->temp(1).reg(); | 2345 Register temp1 = locs()->temp(1).reg(); |
| 2432 Register temp2 = locs()->temp(2).reg(); | 2346 Register temp2 = locs()->temp(2).reg(); |
| 2433 Register result = locs()->out(0).reg(); | 2347 Register result = locs()->out(0).reg(); |
| 2434 // Try allocate the object. | 2348 // Try allocate the object. |
| 2435 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2349 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
| 2436 compiler->AddSlowPathCode(slow_path); | 2350 compiler->AddSlowPathCode(slow_path); |
| 2437 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2351 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
| 2438 | 2352 |
| 2439 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 2353 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
| 2440 result, // instance | 2354 result, // instance |
| 2441 temp0, temp1, temp2); | 2355 temp0, temp1, temp2); |
| 2442 | 2356 |
| 2443 // Setup up number of context variables field. | 2357 // Setup up number of context variables field. |
| 2444 __ LoadImmediate(temp0, num_context_variables()); | 2358 __ LoadImmediate(temp0, num_context_variables()); |
| 2445 __ str(temp0, FieldAddress(result, Context::num_variables_offset())); | 2359 __ str(temp0, FieldAddress(result, Context::num_variables_offset())); |
| 2446 | 2360 |
| 2447 __ Bind(slow_path->exit_label()); | 2361 __ Bind(slow_path->exit_label()); |
| 2448 } | 2362 } |
| 2449 | 2363 |
| 2450 | |
| 2451 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 2364 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |
| 2452 bool opt) const { | 2365 bool opt) const { |
| 2453 const intptr_t kNumInputs = 0; | 2366 const intptr_t kNumInputs = 0; |
| 2454 const intptr_t kNumTemps = 1; | 2367 const intptr_t kNumTemps = 1; |
| 2455 LocationSummary* locs = new (zone) | 2368 LocationSummary* locs = new (zone) |
| 2456 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2369 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2457 locs->set_temp(0, Location::RegisterLocation(R1)); | 2370 locs->set_temp(0, Location::RegisterLocation(R1)); |
| 2458 locs->set_out(0, Location::RegisterLocation(R0)); | 2371 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2459 return locs; | 2372 return locs; |
| 2460 } | 2373 } |
| 2461 | 2374 |
| 2462 | |
| 2463 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2375 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2464 ASSERT(locs()->temp(0).reg() == R1); | 2376 ASSERT(locs()->temp(0).reg() == R1); |
| 2465 ASSERT(locs()->out(0).reg() == R0); | 2377 ASSERT(locs()->out(0).reg() == R0); |
| 2466 | 2378 |
| 2467 __ LoadImmediate(R1, num_context_variables()); | 2379 __ LoadImmediate(R1, num_context_variables()); |
| 2468 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), | 2380 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), |
| 2469 RawPcDescriptors::kOther, locs()); | 2381 RawPcDescriptors::kOther, locs()); |
| 2470 } | 2382 } |
| 2471 | 2383 |
| 2472 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2384 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2473 bool opt) const { | 2385 bool opt) const { |
| 2474 const intptr_t kNumInputs = 1; | 2386 const intptr_t kNumInputs = 1; |
| 2475 const intptr_t kNumTemps = 1; | 2387 const intptr_t kNumTemps = 1; |
| 2476 LocationSummary* locs = new (zone) | 2388 LocationSummary* locs = new (zone) |
| 2477 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2389 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2478 locs->set_in(0, Location::RegisterLocation(R0)); | 2390 locs->set_in(0, Location::RegisterLocation(R0)); |
| 2479 locs->set_temp(0, Location::RegisterLocation(R1)); | 2391 locs->set_temp(0, Location::RegisterLocation(R1)); |
| 2480 return locs; | 2392 return locs; |
| 2481 } | 2393 } |
| 2482 | 2394 |
| 2483 | |
| 2484 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2395 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2485 Register field = locs()->in(0).reg(); | 2396 Register field = locs()->in(0).reg(); |
| 2486 Register temp = locs()->temp(0).reg(); | 2397 Register temp = locs()->temp(0).reg(); |
| 2487 Label call_runtime, no_call; | 2398 Label call_runtime, no_call; |
| 2488 | 2399 |
| 2489 __ ldr(temp, FieldAddress(field, Field::static_value_offset())); | 2400 __ ldr(temp, FieldAddress(field, Field::static_value_offset())); |
| 2490 __ CompareObject(temp, Object::sentinel()); | 2401 __ CompareObject(temp, Object::sentinel()); |
| 2491 __ b(&call_runtime, EQ); | 2402 __ b(&call_runtime, EQ); |
| 2492 | 2403 |
| 2493 __ CompareObject(temp, Object::transition_sentinel()); | 2404 __ CompareObject(temp, Object::transition_sentinel()); |
| 2494 __ b(&no_call, NE); | 2405 __ b(&no_call, NE); |
| 2495 | 2406 |
| 2496 __ Bind(&call_runtime); | 2407 __ Bind(&call_runtime); |
| 2497 __ PushObject(Object::null_object()); // Make room for (unused) result. | 2408 __ PushObject(Object::null_object()); // Make room for (unused) result. |
| 2498 __ Push(field); | 2409 __ Push(field); |
| 2499 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2410 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2500 kInitStaticFieldRuntimeEntry, 1, locs()); | 2411 kInitStaticFieldRuntimeEntry, 1, locs()); |
| 2501 __ Drop(2); // Remove argument and result placeholder. | 2412 __ Drop(2); // Remove argument and result placeholder. |
| 2502 __ Bind(&no_call); | 2413 __ Bind(&no_call); |
| 2503 } | 2414 } |
| 2504 | 2415 |
| 2505 | |
| 2506 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2416 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
| 2507 bool opt) const { | 2417 bool opt) const { |
| 2508 const intptr_t kNumInputs = 1; | 2418 const intptr_t kNumInputs = 1; |
| 2509 const intptr_t kNumTemps = 0; | 2419 const intptr_t kNumTemps = 0; |
| 2510 LocationSummary* locs = new (zone) | 2420 LocationSummary* locs = new (zone) |
| 2511 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2421 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2512 locs->set_in(0, Location::RegisterLocation(R0)); | 2422 locs->set_in(0, Location::RegisterLocation(R0)); |
| 2513 locs->set_out(0, Location::RegisterLocation(R0)); | 2423 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2514 return locs; | 2424 return locs; |
| 2515 } | 2425 } |
| 2516 | 2426 |
| 2517 | |
| 2518 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2427 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2519 const Register context_value = locs()->in(0).reg(); | 2428 const Register context_value = locs()->in(0).reg(); |
| 2520 const Register result = locs()->out(0).reg(); | 2429 const Register result = locs()->out(0).reg(); |
| 2521 | 2430 |
| 2522 __ PushObject(Object::null_object()); // Make room for the result. | 2431 __ PushObject(Object::null_object()); // Make room for the result. |
| 2523 __ Push(context_value); | 2432 __ Push(context_value); |
| 2524 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2433 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2525 kCloneContextRuntimeEntry, 1, locs()); | 2434 kCloneContextRuntimeEntry, 1, locs()); |
| 2526 __ Drop(1); // Remove argument. | 2435 __ Drop(1); // Remove argument. |
| 2527 __ Pop(result); // Get result (cloned context). | 2436 __ Pop(result); // Get result (cloned context). |
| 2528 } | 2437 } |
| 2529 | 2438 |
| 2530 | |
| 2531 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2439 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
| 2532 bool opt) const { | 2440 bool opt) const { |
| 2533 UNREACHABLE(); | 2441 UNREACHABLE(); |
| 2534 return NULL; | 2442 return NULL; |
| 2535 } | 2443 } |
| 2536 | 2444 |
| 2537 | |
| 2538 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2445 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2539 __ Bind(compiler->GetJumpLabel(this)); | 2446 __ Bind(compiler->GetJumpLabel(this)); |
| 2540 compiler->AddExceptionHandler(catch_try_index(), try_index(), | 2447 compiler->AddExceptionHandler(catch_try_index(), try_index(), |
| 2541 compiler->assembler()->CodeSize(), | 2448 compiler->assembler()->CodeSize(), |
| 2542 handler_token_pos(), is_generated(), | 2449 handler_token_pos(), is_generated(), |
| 2543 catch_handler_types_, needs_stacktrace()); | 2450 catch_handler_types_, needs_stacktrace()); |
| 2544 // On lazy deoptimization we patch the optimized code here to enter the | 2451 // On lazy deoptimization we patch the optimized code here to enter the |
| 2545 // deoptimization stub. | 2452 // deoptimization stub. |
| 2546 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 2453 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |
| 2547 if (compiler->is_optimizing()) { | 2454 if (compiler->is_optimizing()) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2591 } else { | 2498 } else { |
| 2592 // Restore stack and initialize the two exception variables: | 2499 // Restore stack and initialize the two exception variables: |
| 2593 // exception and stack trace variables. | 2500 // exception and stack trace variables. |
| 2594 __ StoreToOffset(kExceptionObjectReg, FP, | 2501 __ StoreToOffset(kExceptionObjectReg, FP, |
| 2595 exception_var().index() * kWordSize); | 2502 exception_var().index() * kWordSize); |
| 2596 __ StoreToOffset(kStackTraceObjectReg, FP, | 2503 __ StoreToOffset(kStackTraceObjectReg, FP, |
| 2597 stacktrace_var().index() * kWordSize); | 2504 stacktrace_var().index() * kWordSize); |
| 2598 } | 2505 } |
| 2599 } | 2506 } |
| 2600 | 2507 |
| 2601 | |
| 2602 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 2508 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |
| 2603 bool opt) const { | 2509 bool opt) const { |
| 2604 const intptr_t kNumInputs = 0; | 2510 const intptr_t kNumInputs = 0; |
| 2605 const intptr_t kNumTemps = 1; | 2511 const intptr_t kNumTemps = 1; |
| 2606 LocationSummary* summary = new (zone) LocationSummary( | 2512 LocationSummary* summary = new (zone) LocationSummary( |
| 2607 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2513 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2608 summary->set_temp(0, Location::RequiresRegister()); | 2514 summary->set_temp(0, Location::RequiresRegister()); |
| 2609 return summary; | 2515 return summary; |
| 2610 } | 2516 } |
| 2611 | 2517 |
| 2612 | |
| 2613 class CheckStackOverflowSlowPath : public SlowPathCode { | 2518 class CheckStackOverflowSlowPath : public SlowPathCode { |
| 2614 public: | 2519 public: |
| 2615 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2520 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
| 2616 : instruction_(instruction) {} | 2521 : instruction_(instruction) {} |
| 2617 | 2522 |
| 2618 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2523 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2619 if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) { | 2524 if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) { |
| 2620 const Register value = instruction_->locs()->temp(0).reg(); | 2525 const Register value = instruction_->locs()->temp(0).reg(); |
| 2621 __ Comment("CheckStackOverflowSlowPathOsr"); | 2526 __ Comment("CheckStackOverflowSlowPathOsr"); |
| 2622 __ Bind(osr_entry_label()); | 2527 __ Bind(osr_entry_label()); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2650 Label* osr_entry_label() { | 2555 Label* osr_entry_label() { |
| 2651 ASSERT(Isolate::Current()->use_osr()); | 2556 ASSERT(Isolate::Current()->use_osr()); |
| 2652 return &osr_entry_label_; | 2557 return &osr_entry_label_; |
| 2653 } | 2558 } |
| 2654 | 2559 |
| 2655 private: | 2560 private: |
| 2656 CheckStackOverflowInstr* instruction_; | 2561 CheckStackOverflowInstr* instruction_; |
| 2657 Label osr_entry_label_; | 2562 Label osr_entry_label_; |
| 2658 }; | 2563 }; |
| 2659 | 2564 |
| 2660 | |
| 2661 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2565 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2662 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); | 2566 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); |
| 2663 compiler->AddSlowPathCode(slow_path); | 2567 compiler->AddSlowPathCode(slow_path); |
| 2664 | 2568 |
| 2665 __ ldr(TMP, Address(THR, Thread::stack_limit_offset())); | 2569 __ ldr(TMP, Address(THR, Thread::stack_limit_offset())); |
| 2666 // Compare to CSP not SP because CSP is closer to the stack limit. See | 2570 // Compare to CSP not SP because CSP is closer to the stack limit. See |
| 2667 // Assembler::EnterFrame. | 2571 // Assembler::EnterFrame. |
| 2668 __ CompareRegisters(CSP, TMP); | 2572 __ CompareRegisters(CSP, TMP); |
| 2669 __ b(slow_path->entry_label(), LS); | 2573 __ b(slow_path->entry_label(), LS); |
| 2670 if (compiler->CanOSRFunction() && in_loop()) { | 2574 if (compiler->CanOSRFunction() && in_loop()) { |
| 2671 const Register temp = locs()->temp(0).reg(); | 2575 const Register temp = locs()->temp(0).reg(); |
| 2672 // In unoptimized code check the usage counter to trigger OSR at loop | 2576 // In unoptimized code check the usage counter to trigger OSR at loop |
| 2673 // stack checks. Use progressively higher thresholds for more deeply | 2577 // stack checks. Use progressively higher thresholds for more deeply |
| 2674 // nested loops to attempt to hit outer loops with OSR when possible. | 2578 // nested loops to attempt to hit outer loops with OSR when possible. |
| 2675 __ LoadObject(temp, compiler->parsed_function().function()); | 2579 __ LoadObject(temp, compiler->parsed_function().function()); |
| 2676 intptr_t threshold = | 2580 intptr_t threshold = |
| 2677 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2581 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
| 2678 __ LoadFieldFromOffset(temp, temp, Function::usage_counter_offset(), kWord); | 2582 __ LoadFieldFromOffset(temp, temp, Function::usage_counter_offset(), kWord); |
| 2679 __ CompareImmediate(temp, threshold); | 2583 __ CompareImmediate(temp, threshold); |
| 2680 __ b(slow_path->osr_entry_label(), GE); | 2584 __ b(slow_path->osr_entry_label(), GE); |
| 2681 } | 2585 } |
| 2682 if (compiler->ForceSlowPathForStackOverflow()) { | 2586 if (compiler->ForceSlowPathForStackOverflow()) { |
| 2683 __ b(slow_path->entry_label()); | 2587 __ b(slow_path->entry_label()); |
| 2684 } | 2588 } |
| 2685 __ Bind(slow_path->exit_label()); | 2589 __ Bind(slow_path->exit_label()); |
| 2686 } | 2590 } |
| 2687 | 2591 |
| 2688 | |
| 2689 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2592 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
| 2690 BinarySmiOpInstr* shift_left) { | 2593 BinarySmiOpInstr* shift_left) { |
| 2691 const LocationSummary& locs = *shift_left->locs(); | 2594 const LocationSummary& locs = *shift_left->locs(); |
| 2692 const Register left = locs.in(0).reg(); | 2595 const Register left = locs.in(0).reg(); |
| 2693 const Register result = locs.out(0).reg(); | 2596 const Register result = locs.out(0).reg(); |
| 2694 Label* deopt = shift_left->CanDeoptimize() | 2597 Label* deopt = shift_left->CanDeoptimize() |
| 2695 ? compiler->AddDeoptStub(shift_left->deopt_id(), | 2598 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
| 2696 ICData::kDeoptBinarySmiOp) | 2599 ICData::kDeoptBinarySmiOp) |
| 2697 : NULL; | 2600 : NULL; |
| 2698 if (locs.in(1).IsConstant()) { | 2601 if (locs.in(1).IsConstant()) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2776 const Register temp = locs.temp(0).reg(); | 2679 const Register temp = locs.temp(0).reg(); |
| 2777 __ lslv(temp, left, TMP); | 2680 __ lslv(temp, left, TMP); |
| 2778 __ asrv(TMP2, temp, TMP); | 2681 __ asrv(TMP2, temp, TMP); |
| 2779 __ CompareRegisters(left, TMP2); | 2682 __ CompareRegisters(left, TMP2); |
| 2780 __ b(deopt, NE); // Overflow. | 2683 __ b(deopt, NE); // Overflow. |
| 2781 // Shift for result now we know there is no overflow. | 2684 // Shift for result now we know there is no overflow. |
| 2782 __ lslv(result, left, TMP); | 2685 __ lslv(result, left, TMP); |
| 2783 } | 2686 } |
| 2784 } | 2687 } |
| 2785 | 2688 |
| 2786 | |
| 2787 class CheckedSmiSlowPath : public SlowPathCode { | 2689 class CheckedSmiSlowPath : public SlowPathCode { |
| 2788 public: | 2690 public: |
| 2789 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) | 2691 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) |
| 2790 : instruction_(instruction), try_index_(try_index) {} | 2692 : instruction_(instruction), try_index_(try_index) {} |
| 2791 | 2693 |
| 2792 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2694 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2793 if (Assembler::EmittingComments()) { | 2695 if (Assembler::EmittingComments()) { |
| 2794 __ Comment("slow path smi operation"); | 2696 __ Comment("slow path smi operation"); |
| 2795 } | 2697 } |
| 2796 __ Bind(entry_label()); | 2698 __ Bind(entry_label()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2818 compiler->RestoreLiveRegisters(locs); | 2720 compiler->RestoreLiveRegisters(locs); |
| 2819 __ b(exit_label()); | 2721 __ b(exit_label()); |
| 2820 compiler->pending_deoptimization_env_ = NULL; | 2722 compiler->pending_deoptimization_env_ = NULL; |
| 2821 } | 2723 } |
| 2822 | 2724 |
| 2823 private: | 2725 private: |
| 2824 CheckedSmiOpInstr* instruction_; | 2726 CheckedSmiOpInstr* instruction_; |
| 2825 intptr_t try_index_; | 2727 intptr_t try_index_; |
| 2826 }; | 2728 }; |
| 2827 | 2729 |
| 2828 | |
| 2829 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 2730 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
| 2830 bool opt) const { | 2731 bool opt) const { |
| 2831 const intptr_t kNumInputs = 2; | 2732 const intptr_t kNumInputs = 2; |
| 2832 const intptr_t kNumTemps = 0; | 2733 const intptr_t kNumTemps = 0; |
| 2833 LocationSummary* summary = new (zone) LocationSummary( | 2734 LocationSummary* summary = new (zone) LocationSummary( |
| 2834 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2735 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2835 summary->set_in(0, Location::RequiresRegister()); | 2736 summary->set_in(0, Location::RequiresRegister()); |
| 2836 summary->set_in(1, Location::RequiresRegister()); | 2737 summary->set_in(1, Location::RequiresRegister()); |
| 2837 summary->set_out(0, Location::RequiresRegister()); | 2738 summary->set_out(0, Location::RequiresRegister()); |
| 2838 return summary; | 2739 return summary; |
| 2839 } | 2740 } |
| 2840 | 2741 |
| 2841 | |
| 2842 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2742 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2843 CheckedSmiSlowPath* slow_path = | 2743 CheckedSmiSlowPath* slow_path = |
| 2844 new CheckedSmiSlowPath(this, compiler->CurrentTryIndex()); | 2744 new CheckedSmiSlowPath(this, compiler->CurrentTryIndex()); |
| 2845 compiler->AddSlowPathCode(slow_path); | 2745 compiler->AddSlowPathCode(slow_path); |
| 2846 // Test operands if necessary. | 2746 // Test operands if necessary. |
| 2847 Register left = locs()->in(0).reg(); | 2747 Register left = locs()->in(0).reg(); |
| 2848 Register right = locs()->in(1).reg(); | 2748 Register right = locs()->in(1).reg(); |
| 2849 Register result = locs()->out(0).reg(); | 2749 Register result = locs()->out(0).reg(); |
| 2850 intptr_t left_cid = this->left()->Type()->ToCid(); | 2750 intptr_t left_cid = this->left()->Type()->ToCid(); |
| 2851 intptr_t right_cid = this->right()->Type()->ToCid(); | 2751 intptr_t right_cid = this->right()->Type()->ToCid(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2916 __ SmiUntag(TMP, left); | 2816 __ SmiUntag(TMP, left); |
| 2917 __ asrv(result, TMP, result); | 2817 __ asrv(result, TMP, result); |
| 2918 __ SmiTag(result); | 2818 __ SmiTag(result); |
| 2919 break; | 2819 break; |
| 2920 default: | 2820 default: |
| 2921 UNIMPLEMENTED(); | 2821 UNIMPLEMENTED(); |
| 2922 } | 2822 } |
| 2923 __ Bind(slow_path->exit_label()); | 2823 __ Bind(slow_path->exit_label()); |
| 2924 } | 2824 } |
| 2925 | 2825 |
| 2926 | |
| 2927 class CheckedSmiComparisonSlowPath : public SlowPathCode { | 2826 class CheckedSmiComparisonSlowPath : public SlowPathCode { |
| 2928 public: | 2827 public: |
| 2929 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, | 2828 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, |
| 2930 intptr_t try_index, | 2829 intptr_t try_index, |
| 2931 BranchLabels labels, | 2830 BranchLabels labels, |
| 2932 bool merged) | 2831 bool merged) |
| 2933 : instruction_(instruction), | 2832 : instruction_(instruction), |
| 2934 try_index_(try_index), | 2833 try_index_(try_index), |
| 2935 labels_(labels), | 2834 labels_(labels), |
| 2936 merged_(merged) {} | 2835 merged_(merged) {} |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2975 } | 2874 } |
| 2976 } | 2875 } |
| 2977 | 2876 |
| 2978 private: | 2877 private: |
| 2979 CheckedSmiComparisonInstr* instruction_; | 2878 CheckedSmiComparisonInstr* instruction_; |
| 2980 intptr_t try_index_; | 2879 intptr_t try_index_; |
| 2981 BranchLabels labels_; | 2880 BranchLabels labels_; |
| 2982 bool merged_; | 2881 bool merged_; |
| 2983 }; | 2882 }; |
| 2984 | 2883 |
| 2985 | |
| 2986 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 2884 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
| 2987 Zone* zone, | 2885 Zone* zone, |
| 2988 bool opt) const { | 2886 bool opt) const { |
| 2989 const intptr_t kNumInputs = 2; | 2887 const intptr_t kNumInputs = 2; |
| 2990 const intptr_t kNumTemps = 1; | 2888 const intptr_t kNumTemps = 1; |
| 2991 LocationSummary* summary = new (zone) LocationSummary( | 2889 LocationSummary* summary = new (zone) LocationSummary( |
| 2992 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2890 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2993 summary->set_in(0, Location::RequiresRegister()); | 2891 summary->set_in(0, Location::RequiresRegister()); |
| 2994 summary->set_in(1, Location::RequiresRegister()); | 2892 summary->set_in(1, Location::RequiresRegister()); |
| 2995 summary->set_temp(0, Location::RequiresRegister()); | 2893 summary->set_temp(0, Location::RequiresRegister()); |
| 2996 summary->set_out(0, Location::RequiresRegister()); | 2894 summary->set_out(0, Location::RequiresRegister()); |
| 2997 return summary; | 2895 return summary; |
| 2998 } | 2896 } |
| 2999 | 2897 |
| 3000 | |
| 3001 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 2898 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
| 3002 FlowGraphCompiler* compiler, | 2899 FlowGraphCompiler* compiler, |
| 3003 BranchLabels labels) { | 2900 BranchLabels labels) { |
| 3004 return EmitSmiComparisonOp(compiler, locs(), kind()); | 2901 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 3005 } | 2902 } |
| 3006 | 2903 |
| 3007 | |
| 3008 #define EMIT_SMI_CHECK \ | 2904 #define EMIT_SMI_CHECK \ |
| 3009 Register left = locs()->in(0).reg(); \ | 2905 Register left = locs()->in(0).reg(); \ |
| 3010 Register right = locs()->in(1).reg(); \ | 2906 Register right = locs()->in(1).reg(); \ |
| 3011 Register temp = locs()->temp(0).reg(); \ | 2907 Register temp = locs()->temp(0).reg(); \ |
| 3012 intptr_t left_cid = this->left()->Type()->ToCid(); \ | 2908 intptr_t left_cid = this->left()->Type()->ToCid(); \ |
| 3013 intptr_t right_cid = this->right()->Type()->ToCid(); \ | 2909 intptr_t right_cid = this->right()->Type()->ToCid(); \ |
| 3014 if (this->left()->definition() == this->right()->definition()) { \ | 2910 if (this->left()->definition() == this->right()->definition()) { \ |
| 3015 __ tsti(left, Immediate(kSmiTagMask)); \ | 2911 __ tsti(left, Immediate(kSmiTagMask)); \ |
| 3016 } else if (left_cid == kSmiCid) { \ | 2912 } else if (left_cid == kSmiCid) { \ |
| 3017 __ tsti(right, Immediate(kSmiTagMask)); \ | 2913 __ tsti(right, Immediate(kSmiTagMask)); \ |
| 3018 } else if (right_cid == kSmiCid) { \ | 2914 } else if (right_cid == kSmiCid) { \ |
| 3019 __ tsti(left, Immediate(kSmiTagMask)); \ | 2915 __ tsti(left, Immediate(kSmiTagMask)); \ |
| 3020 } else { \ | 2916 } else { \ |
| 3021 __ orr(temp, left, Operand(right)); \ | 2917 __ orr(temp, left, Operand(right)); \ |
| 3022 __ tsti(temp, Immediate(kSmiTagMask)); \ | 2918 __ tsti(temp, Immediate(kSmiTagMask)); \ |
| 3023 } \ | 2919 } \ |
| 3024 __ b(slow_path->entry_label(), NE) | 2920 __ b(slow_path->entry_label(), NE) |
| 3025 | 2921 |
| 3026 | |
| 3027 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 2922 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 3028 BranchInstr* branch) { | 2923 BranchInstr* branch) { |
| 3029 BranchLabels labels = compiler->CreateBranchLabels(branch); | 2924 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 3030 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 2925 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
| 3031 this, compiler->CurrentTryIndex(), labels, | 2926 this, compiler->CurrentTryIndex(), labels, |
| 3032 /* merged = */ true); | 2927 /* merged = */ true); |
| 3033 compiler->AddSlowPathCode(slow_path); | 2928 compiler->AddSlowPathCode(slow_path); |
| 3034 EMIT_SMI_CHECK; | 2929 EMIT_SMI_CHECK; |
| 3035 Condition true_condition = EmitComparisonCode(compiler, labels); | 2930 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3036 ASSERT(true_condition != kInvalidCondition); | 2931 ASSERT(true_condition != kInvalidCondition); |
| 3037 EmitBranchOnCondition(compiler, true_condition, labels); | 2932 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3038 __ Bind(slow_path->exit_label()); | 2933 __ Bind(slow_path->exit_label()); |
| 3039 } | 2934 } |
| 3040 | 2935 |
| 3041 | |
| 3042 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2936 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3043 Label true_label, false_label, done; | 2937 Label true_label, false_label, done; |
| 3044 BranchLabels labels = {&true_label, &false_label, &false_label}; | 2938 BranchLabels labels = {&true_label, &false_label, &false_label}; |
| 3045 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 2939 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
| 3046 this, compiler->CurrentTryIndex(), labels, | 2940 this, compiler->CurrentTryIndex(), labels, |
| 3047 /* merged = */ false); | 2941 /* merged = */ false); |
| 3048 compiler->AddSlowPathCode(slow_path); | 2942 compiler->AddSlowPathCode(slow_path); |
| 3049 EMIT_SMI_CHECK; | 2943 EMIT_SMI_CHECK; |
| 3050 Condition true_condition = EmitComparisonCode(compiler, labels); | 2944 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3051 ASSERT(true_condition != kInvalidCondition); | 2945 ASSERT(true_condition != kInvalidCondition); |
| 3052 EmitBranchOnCondition(compiler, true_condition, labels); | 2946 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3053 Register result = locs()->out(0).reg(); | 2947 Register result = locs()->out(0).reg(); |
| 3054 __ Bind(&false_label); | 2948 __ Bind(&false_label); |
| 3055 __ LoadObject(result, Bool::False()); | 2949 __ LoadObject(result, Bool::False()); |
| 3056 __ b(&done); | 2950 __ b(&done); |
| 3057 __ Bind(&true_label); | 2951 __ Bind(&true_label); |
| 3058 __ LoadObject(result, Bool::True()); | 2952 __ LoadObject(result, Bool::True()); |
| 3059 __ Bind(&done); | 2953 __ Bind(&done); |
| 3060 __ Bind(slow_path->exit_label()); | 2954 __ Bind(slow_path->exit_label()); |
| 3061 } | 2955 } |
| 3062 | 2956 |
| 3063 | |
| 3064 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 2957 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 3065 bool opt) const { | 2958 bool opt) const { |
| 3066 const intptr_t kNumInputs = 2; | 2959 const intptr_t kNumInputs = 2; |
| 3067 const intptr_t kNumTemps = (((op_kind() == Token::kSHL) && can_overflow()) || | 2960 const intptr_t kNumTemps = (((op_kind() == Token::kSHL) && can_overflow()) || |
| 3068 (op_kind() == Token::kSHR)) | 2961 (op_kind() == Token::kSHR)) |
| 3069 ? 1 | 2962 ? 1 |
| 3070 : 0; | 2963 : 0; |
| 3071 LocationSummary* summary = new (zone) | 2964 LocationSummary* summary = new (zone) |
| 3072 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2965 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3073 if (op_kind() == Token::kTRUNCDIV) { | 2966 if (op_kind() == Token::kTRUNCDIV) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3092 if (((op_kind() == Token::kSHL) && can_overflow()) || | 2985 if (((op_kind() == Token::kSHL) && can_overflow()) || |
| 3093 (op_kind() == Token::kSHR)) { | 2986 (op_kind() == Token::kSHR)) { |
| 3094 summary->set_temp(0, Location::RequiresRegister()); | 2987 summary->set_temp(0, Location::RequiresRegister()); |
| 3095 } | 2988 } |
| 3096 // We make use of 3-operand instructions by not requiring result register | 2989 // We make use of 3-operand instructions by not requiring result register |
| 3097 // to be identical to first input register as on Intel. | 2990 // to be identical to first input register as on Intel. |
| 3098 summary->set_out(0, Location::RequiresRegister()); | 2991 summary->set_out(0, Location::RequiresRegister()); |
| 3099 return summary; | 2992 return summary; |
| 3100 } | 2993 } |
| 3101 | 2994 |
| 3102 | |
| 3103 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2995 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3104 if (op_kind() == Token::kSHL) { | 2996 if (op_kind() == Token::kSHL) { |
| 3105 EmitSmiShiftLeft(compiler, this); | 2997 EmitSmiShiftLeft(compiler, this); |
| 3106 return; | 2998 return; |
| 3107 } | 2999 } |
| 3108 | 3000 |
| 3109 const Register left = locs()->in(0).reg(); | 3001 const Register left = locs()->in(0).reg(); |
| 3110 const Register result = locs()->out(0).reg(); | 3002 const Register result = locs()->out(0).reg(); |
| 3111 Label* deopt = NULL; | 3003 Label* deopt = NULL; |
| 3112 if (CanDeoptimize()) { | 3004 if (CanDeoptimize()) { |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3329 // behavior (short-circuit evaluation). | 3221 // behavior (short-circuit evaluation). |
| 3330 UNREACHABLE(); | 3222 UNREACHABLE(); |
| 3331 break; | 3223 break; |
| 3332 } | 3224 } |
| 3333 default: | 3225 default: |
| 3334 UNREACHABLE(); | 3226 UNREACHABLE(); |
| 3335 break; | 3227 break; |
| 3336 } | 3228 } |
| 3337 } | 3229 } |
| 3338 | 3230 |
| 3339 | |
| 3340 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3231 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
| 3341 bool opt) const { | 3232 bool opt) const { |
| 3342 intptr_t left_cid = left()->Type()->ToCid(); | 3233 intptr_t left_cid = left()->Type()->ToCid(); |
| 3343 intptr_t right_cid = right()->Type()->ToCid(); | 3234 intptr_t right_cid = right()->Type()->ToCid(); |
| 3344 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3235 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
| 3345 const intptr_t kNumInputs = 2; | 3236 const intptr_t kNumInputs = 2; |
| 3346 const intptr_t kNumTemps = 0; | 3237 const intptr_t kNumTemps = 0; |
| 3347 LocationSummary* summary = new (zone) | 3238 LocationSummary* summary = new (zone) |
| 3348 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3239 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3349 summary->set_in(0, Location::RequiresRegister()); | 3240 summary->set_in(0, Location::RequiresRegister()); |
| 3350 summary->set_in(1, Location::RequiresRegister()); | 3241 summary->set_in(1, Location::RequiresRegister()); |
| 3351 return summary; | 3242 return summary; |
| 3352 } | 3243 } |
| 3353 | 3244 |
| 3354 | |
| 3355 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3245 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3356 Label* deopt = | 3246 Label* deopt = |
| 3357 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, | 3247 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
| 3358 licm_hoisted_ ? ICData::kHoisted : 0); | 3248 licm_hoisted_ ? ICData::kHoisted : 0); |
| 3359 intptr_t left_cid = left()->Type()->ToCid(); | 3249 intptr_t left_cid = left()->Type()->ToCid(); |
| 3360 intptr_t right_cid = right()->Type()->ToCid(); | 3250 intptr_t right_cid = right()->Type()->ToCid(); |
| 3361 const Register left = locs()->in(0).reg(); | 3251 const Register left = locs()->in(0).reg(); |
| 3362 const Register right = locs()->in(1).reg(); | 3252 const Register right = locs()->in(1).reg(); |
| 3363 if (this->left()->definition() == this->right()->definition()) { | 3253 if (this->left()->definition() == this->right()->definition()) { |
| 3364 __ tsti(left, Immediate(kSmiTagMask)); | 3254 __ tsti(left, Immediate(kSmiTagMask)); |
| 3365 } else if (left_cid == kSmiCid) { | 3255 } else if (left_cid == kSmiCid) { |
| 3366 __ tsti(right, Immediate(kSmiTagMask)); | 3256 __ tsti(right, Immediate(kSmiTagMask)); |
| 3367 } else if (right_cid == kSmiCid) { | 3257 } else if (right_cid == kSmiCid) { |
| 3368 __ tsti(left, Immediate(kSmiTagMask)); | 3258 __ tsti(left, Immediate(kSmiTagMask)); |
| 3369 } else { | 3259 } else { |
| 3370 __ orr(TMP, left, Operand(right)); | 3260 __ orr(TMP, left, Operand(right)); |
| 3371 __ tsti(TMP, Immediate(kSmiTagMask)); | 3261 __ tsti(TMP, Immediate(kSmiTagMask)); |
| 3372 } | 3262 } |
| 3373 __ b(deopt, EQ); | 3263 __ b(deopt, EQ); |
| 3374 } | 3264 } |
| 3375 | 3265 |
| 3376 | |
| 3377 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 3266 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3378 const intptr_t kNumInputs = 1; | 3267 const intptr_t kNumInputs = 1; |
| 3379 const intptr_t kNumTemps = 1; | 3268 const intptr_t kNumTemps = 1; |
| 3380 LocationSummary* summary = new (zone) LocationSummary( | 3269 LocationSummary* summary = new (zone) LocationSummary( |
| 3381 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3270 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3382 summary->set_in(0, Location::RequiresFpuRegister()); | 3271 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3383 summary->set_temp(0, Location::RequiresRegister()); | 3272 summary->set_temp(0, Location::RequiresRegister()); |
| 3384 summary->set_out(0, Location::RequiresRegister()); | 3273 summary->set_out(0, Location::RequiresRegister()); |
| 3385 return summary; | 3274 return summary; |
| 3386 } | 3275 } |
| 3387 | 3276 |
| 3388 | |
| 3389 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3277 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3390 const Register out_reg = locs()->out(0).reg(); | 3278 const Register out_reg = locs()->out(0).reg(); |
| 3391 const Register temp_reg = locs()->temp(0).reg(); | 3279 const Register temp_reg = locs()->temp(0).reg(); |
| 3392 const VRegister value = locs()->in(0).fpu_reg(); | 3280 const VRegister value = locs()->in(0).fpu_reg(); |
| 3393 | 3281 |
| 3394 BoxAllocationSlowPath::Allocate(compiler, this, | 3282 BoxAllocationSlowPath::Allocate(compiler, this, |
| 3395 compiler->BoxClassFor(from_representation()), | 3283 compiler->BoxClassFor(from_representation()), |
| 3396 out_reg, temp_reg); | 3284 out_reg, temp_reg); |
| 3397 | 3285 |
| 3398 switch (from_representation()) { | 3286 switch (from_representation()) { |
| 3399 case kUnboxedDouble: | 3287 case kUnboxedDouble: |
| 3400 __ StoreDFieldToOffset(value, out_reg, ValueOffset()); | 3288 __ StoreDFieldToOffset(value, out_reg, ValueOffset()); |
| 3401 break; | 3289 break; |
| 3402 case kUnboxedFloat32x4: | 3290 case kUnboxedFloat32x4: |
| 3403 case kUnboxedFloat64x2: | 3291 case kUnboxedFloat64x2: |
| 3404 case kUnboxedInt32x4: | 3292 case kUnboxedInt32x4: |
| 3405 __ StoreQFieldToOffset(value, out_reg, ValueOffset()); | 3293 __ StoreQFieldToOffset(value, out_reg, ValueOffset()); |
| 3406 break; | 3294 break; |
| 3407 default: | 3295 default: |
| 3408 UNREACHABLE(); | 3296 UNREACHABLE(); |
| 3409 break; | 3297 break; |
| 3410 } | 3298 } |
| 3411 } | 3299 } |
| 3412 | 3300 |
| 3413 | |
| 3414 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 3301 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3415 const intptr_t kNumInputs = 1; | 3302 const intptr_t kNumInputs = 1; |
| 3416 const intptr_t kNumTemps = 0; | 3303 const intptr_t kNumTemps = 0; |
| 3417 LocationSummary* summary = new (zone) | 3304 LocationSummary* summary = new (zone) |
| 3418 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3305 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3419 summary->set_in(0, Location::RequiresRegister()); | 3306 summary->set_in(0, Location::RequiresRegister()); |
| 3420 summary->set_out(0, Location::RequiresFpuRegister()); | 3307 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3421 return summary; | 3308 return summary; |
| 3422 } | 3309 } |
| 3423 | 3310 |
| 3424 | |
| 3425 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { | 3311 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |
| 3426 const Register box = locs()->in(0).reg(); | 3312 const Register box = locs()->in(0).reg(); |
| 3427 | 3313 |
| 3428 switch (representation()) { | 3314 switch (representation()) { |
| 3429 case kUnboxedMint: { | 3315 case kUnboxedMint: { |
| 3430 UNIMPLEMENTED(); | 3316 UNIMPLEMENTED(); |
| 3431 break; | 3317 break; |
| 3432 } | 3318 } |
| 3433 | 3319 |
| 3434 case kUnboxedDouble: { | 3320 case kUnboxedDouble: { |
| 3435 const VRegister result = locs()->out(0).fpu_reg(); | 3321 const VRegister result = locs()->out(0).fpu_reg(); |
| 3436 __ LoadDFieldFromOffset(result, box, ValueOffset()); | 3322 __ LoadDFieldFromOffset(result, box, ValueOffset()); |
| 3437 break; | 3323 break; |
| 3438 } | 3324 } |
| 3439 | 3325 |
| 3440 case kUnboxedFloat32x4: | 3326 case kUnboxedFloat32x4: |
| 3441 case kUnboxedFloat64x2: | 3327 case kUnboxedFloat64x2: |
| 3442 case kUnboxedInt32x4: { | 3328 case kUnboxedInt32x4: { |
| 3443 const VRegister result = locs()->out(0).fpu_reg(); | 3329 const VRegister result = locs()->out(0).fpu_reg(); |
| 3444 __ LoadQFieldFromOffset(result, box, ValueOffset()); | 3330 __ LoadQFieldFromOffset(result, box, ValueOffset()); |
| 3445 break; | 3331 break; |
| 3446 } | 3332 } |
| 3447 | 3333 |
| 3448 default: | 3334 default: |
| 3449 UNREACHABLE(); | 3335 UNREACHABLE(); |
| 3450 break; | 3336 break; |
| 3451 } | 3337 } |
| 3452 } | 3338 } |
| 3453 | 3339 |
| 3454 | |
| 3455 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { | 3340 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { |
| 3456 const Register box = locs()->in(0).reg(); | 3341 const Register box = locs()->in(0).reg(); |
| 3457 | 3342 |
| 3458 switch (representation()) { | 3343 switch (representation()) { |
| 3459 case kUnboxedMint: { | 3344 case kUnboxedMint: { |
| 3460 UNIMPLEMENTED(); | 3345 UNIMPLEMENTED(); |
| 3461 break; | 3346 break; |
| 3462 } | 3347 } |
| 3463 | 3348 |
| 3464 case kUnboxedDouble: { | 3349 case kUnboxedDouble: { |
| 3465 const VRegister result = locs()->out(0).fpu_reg(); | 3350 const VRegister result = locs()->out(0).fpu_reg(); |
| 3466 __ SmiUntag(TMP, box); | 3351 __ SmiUntag(TMP, box); |
| 3467 __ scvtfdx(result, TMP); | 3352 __ scvtfdx(result, TMP); |
| 3468 break; | 3353 break; |
| 3469 } | 3354 } |
| 3470 | 3355 |
| 3471 default: | 3356 default: |
| 3472 UNREACHABLE(); | 3357 UNREACHABLE(); |
| 3473 break; | 3358 break; |
| 3474 } | 3359 } |
| 3475 } | 3360 } |
| 3476 | 3361 |
| 3477 | |
| 3478 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3362 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3479 const intptr_t value_cid = value()->Type()->ToCid(); | 3363 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3480 const intptr_t box_cid = BoxCid(); | 3364 const intptr_t box_cid = BoxCid(); |
| 3481 | 3365 |
| 3482 if (value_cid == box_cid) { | 3366 if (value_cid == box_cid) { |
| 3483 EmitLoadFromBox(compiler); | 3367 EmitLoadFromBox(compiler); |
| 3484 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 3368 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
| 3485 EmitSmiConversion(compiler); | 3369 EmitSmiConversion(compiler); |
| 3486 } else { | 3370 } else { |
| 3487 const Register box = locs()->in(0).reg(); | 3371 const Register box = locs()->in(0).reg(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3505 if (is_smi.IsLinked()) { | 3389 if (is_smi.IsLinked()) { |
| 3506 Label done; | 3390 Label done; |
| 3507 __ b(&done); | 3391 __ b(&done); |
| 3508 __ Bind(&is_smi); | 3392 __ Bind(&is_smi); |
| 3509 EmitSmiConversion(compiler); | 3393 EmitSmiConversion(compiler); |
| 3510 __ Bind(&done); | 3394 __ Bind(&done); |
| 3511 } | 3395 } |
| 3512 } | 3396 } |
| 3513 } | 3397 } |
| 3514 | 3398 |
| 3515 | |
| 3516 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 3399 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 3517 bool opt) const { | 3400 bool opt) const { |
| 3518 ASSERT((from_representation() == kUnboxedInt32) || | 3401 ASSERT((from_representation() == kUnboxedInt32) || |
| 3519 (from_representation() == kUnboxedUint32)); | 3402 (from_representation() == kUnboxedUint32)); |
| 3520 const intptr_t kNumInputs = 1; | 3403 const intptr_t kNumInputs = 1; |
| 3521 const intptr_t kNumTemps = 0; | 3404 const intptr_t kNumTemps = 0; |
| 3522 LocationSummary* summary = new (zone) | 3405 LocationSummary* summary = new (zone) |
| 3523 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3406 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3524 summary->set_in(0, Location::RequiresRegister()); | 3407 summary->set_in(0, Location::RequiresRegister()); |
| 3525 summary->set_out(0, Location::RequiresRegister()); | 3408 summary->set_out(0, Location::RequiresRegister()); |
| 3526 return summary; | 3409 return summary; |
| 3527 } | 3410 } |
| 3528 | 3411 |
| 3529 | |
| 3530 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3412 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3531 Register value = locs()->in(0).reg(); | 3413 Register value = locs()->in(0).reg(); |
| 3532 Register out = locs()->out(0).reg(); | 3414 Register out = locs()->out(0).reg(); |
| 3533 ASSERT(value != out); | 3415 ASSERT(value != out); |
| 3534 | 3416 |
| 3535 ASSERT(kSmiTagSize == 1); | 3417 ASSERT(kSmiTagSize == 1); |
| 3536 // TODO(vegorov) implement and use UBFM/SBFM for this. | 3418 // TODO(vegorov) implement and use UBFM/SBFM for this. |
| 3537 __ LslImmediate(out, value, 32); | 3419 __ LslImmediate(out, value, 32); |
| 3538 if (from_representation() == kUnboxedInt32) { | 3420 if (from_representation() == kUnboxedInt32) { |
| 3539 __ AsrImmediate(out, out, 32 - kSmiTagSize); | 3421 __ AsrImmediate(out, out, 32 - kSmiTagSize); |
| 3540 } else { | 3422 } else { |
| 3541 ASSERT(from_representation() == kUnboxedUint32); | 3423 ASSERT(from_representation() == kUnboxedUint32); |
| 3542 __ LsrImmediate(out, out, 32 - kSmiTagSize); | 3424 __ LsrImmediate(out, out, 32 - kSmiTagSize); |
| 3543 } | 3425 } |
| 3544 } | 3426 } |
| 3545 | 3427 |
| 3546 | |
| 3547 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr) | 3428 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr) |
| 3548 | 3429 |
| 3549 | |
| 3550 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 3430 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 3551 bool opt) const { | 3431 bool opt) const { |
| 3552 const intptr_t kNumInputs = 1; | 3432 const intptr_t kNumInputs = 1; |
| 3553 const intptr_t kNumTemps = 0; | 3433 const intptr_t kNumTemps = 0; |
| 3554 LocationSummary* summary = new (zone) | 3434 LocationSummary* summary = new (zone) |
| 3555 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3435 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3556 summary->set_in(0, Location::RequiresRegister()); | 3436 summary->set_in(0, Location::RequiresRegister()); |
| 3557 summary->set_out(0, Location::RequiresRegister()); | 3437 summary->set_out(0, Location::RequiresRegister()); |
| 3558 return summary; | 3438 return summary; |
| 3559 } | 3439 } |
| 3560 | 3440 |
| 3561 | |
| 3562 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3441 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3563 const intptr_t value_cid = value()->Type()->ToCid(); | 3442 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3564 const Register out = locs()->out(0).reg(); | 3443 const Register out = locs()->out(0).reg(); |
| 3565 const Register value = locs()->in(0).reg(); | 3444 const Register value = locs()->in(0).reg(); |
| 3566 Label* deopt = | 3445 Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub( |
| 3567 CanDeoptimize() | 3446 GetDeoptId(), ICData::kDeoptUnboxInteger) |
| 3568 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) | 3447 : NULL; |
| 3569 : NULL; | |
| 3570 | 3448 |
| 3571 if (value_cid == kSmiCid) { | 3449 if (value_cid == kSmiCid) { |
| 3572 __ SmiUntag(out, value); | 3450 __ SmiUntag(out, value); |
| 3573 } else if (value_cid == kMintCid) { | 3451 } else if (value_cid == kMintCid) { |
| 3574 __ LoadFieldFromOffset(out, value, Mint::value_offset()); | 3452 __ LoadFieldFromOffset(out, value, Mint::value_offset()); |
| 3575 } else if (!CanDeoptimize()) { | 3453 } else if (!CanDeoptimize()) { |
| 3576 // Type information is not conclusive, but range analysis found | 3454 // Type information is not conclusive, but range analysis found |
| 3577 // the value to be in int64 range. Therefore it must be a smi | 3455 // the value to be in int64 range. Therefore it must be a smi |
| 3578 // or mint value. | 3456 // or mint value. |
| 3579 ASSERT(is_truncating()); | 3457 ASSERT(is_truncating()); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3596 | 3474 |
| 3597 // TODO(vegorov): as it is implemented right now truncating unboxing would | 3475 // TODO(vegorov): as it is implemented right now truncating unboxing would |
| 3598 // leave "garbage" in the higher word. | 3476 // leave "garbage" in the higher word. |
| 3599 if (!is_truncating() && (deopt != NULL)) { | 3477 if (!is_truncating() && (deopt != NULL)) { |
| 3600 ASSERT(representation() == kUnboxedInt32); | 3478 ASSERT(representation() == kUnboxedInt32); |
| 3601 __ cmp(out, Operand(out, SXTW, 0)); | 3479 __ cmp(out, Operand(out, SXTW, 0)); |
| 3602 __ b(deopt, NE); | 3480 __ b(deopt, NE); |
| 3603 } | 3481 } |
| 3604 } | 3482 } |
| 3605 | 3483 |
| 3606 | |
| 3607 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 3484 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 3608 bool opt) const { | 3485 bool opt) const { |
| 3609 const intptr_t kNumInputs = 2; | 3486 const intptr_t kNumInputs = 2; |
| 3610 const intptr_t kNumTemps = 0; | 3487 const intptr_t kNumTemps = 0; |
| 3611 LocationSummary* summary = new (zone) | 3488 LocationSummary* summary = new (zone) |
| 3612 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3489 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3613 summary->set_in(0, Location::RequiresFpuRegister()); | 3490 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3614 summary->set_in(1, Location::RequiresFpuRegister()); | 3491 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3615 summary->set_out(0, Location::RequiresFpuRegister()); | 3492 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3616 return summary; | 3493 return summary; |
| 3617 } | 3494 } |
| 3618 | 3495 |
| 3619 | |
| 3620 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3496 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3621 const VRegister left = locs()->in(0).fpu_reg(); | 3497 const VRegister left = locs()->in(0).fpu_reg(); |
| 3622 const VRegister right = locs()->in(1).fpu_reg(); | 3498 const VRegister right = locs()->in(1).fpu_reg(); |
| 3623 const VRegister result = locs()->out(0).fpu_reg(); | 3499 const VRegister result = locs()->out(0).fpu_reg(); |
| 3624 switch (op_kind()) { | 3500 switch (op_kind()) { |
| 3625 case Token::kADD: | 3501 case Token::kADD: |
| 3626 __ faddd(result, left, right); | 3502 __ faddd(result, left, right); |
| 3627 break; | 3503 break; |
| 3628 case Token::kSUB: | 3504 case Token::kSUB: |
| 3629 __ fsubd(result, left, right); | 3505 __ fsubd(result, left, right); |
| 3630 break; | 3506 break; |
| 3631 case Token::kMUL: | 3507 case Token::kMUL: |
| 3632 __ fmuld(result, left, right); | 3508 __ fmuld(result, left, right); |
| 3633 break; | 3509 break; |
| 3634 case Token::kDIV: | 3510 case Token::kDIV: |
| 3635 __ fdivd(result, left, right); | 3511 __ fdivd(result, left, right); |
| 3636 break; | 3512 break; |
| 3637 default: | 3513 default: |
| 3638 UNREACHABLE(); | 3514 UNREACHABLE(); |
| 3639 } | 3515 } |
| 3640 } | 3516 } |
| 3641 | 3517 |
| 3642 | |
| 3643 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 3518 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |
| 3644 bool opt) const { | 3519 bool opt) const { |
| 3645 const intptr_t kNumInputs = 1; | 3520 const intptr_t kNumInputs = 1; |
| 3646 const intptr_t kNumTemps = | 3521 const intptr_t kNumTemps = |
| 3647 op_kind() == MethodRecognizer::kDouble_getIsInfinite ? 1 : 0; | 3522 op_kind() == MethodRecognizer::kDouble_getIsInfinite ? 1 : 0; |
| 3648 LocationSummary* summary = new (zone) | 3523 LocationSummary* summary = new (zone) |
| 3649 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3524 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3650 summary->set_in(0, Location::RequiresFpuRegister()); | 3525 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3651 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 3526 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
| 3652 summary->set_temp(0, Location::RequiresRegister()); | 3527 summary->set_temp(0, Location::RequiresRegister()); |
| 3653 } | 3528 } |
| 3654 summary->set_out(0, Location::RequiresRegister()); | 3529 summary->set_out(0, Location::RequiresRegister()); |
| 3655 return summary; | 3530 return summary; |
| 3656 } | 3531 } |
| 3657 | 3532 |
| 3658 | |
| 3659 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 3533 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 3660 BranchLabels labels) { | 3534 BranchLabels labels) { |
| 3661 ASSERT(compiler->is_optimizing()); | 3535 ASSERT(compiler->is_optimizing()); |
| 3662 const VRegister value = locs()->in(0).fpu_reg(); | 3536 const VRegister value = locs()->in(0).fpu_reg(); |
| 3663 const bool is_negated = kind() != Token::kEQ; | 3537 const bool is_negated = kind() != Token::kEQ; |
| 3664 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { | 3538 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { |
| 3665 __ fcmpd(value, value); | 3539 __ fcmpd(value, value); |
| 3666 return is_negated ? VC : VS; | 3540 return is_negated ? VC : VS; |
| 3667 } else { | 3541 } else { |
| 3668 ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite); | 3542 ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite); |
| 3669 const Register temp = locs()->temp(0).reg(); | 3543 const Register temp = locs()->temp(0).reg(); |
| 3670 __ vmovrd(temp, value, 0); | 3544 __ vmovrd(temp, value, 0); |
| 3671 // Mask off the sign. | 3545 // Mask off the sign. |
| 3672 __ AndImmediate(temp, temp, 0x7FFFFFFFFFFFFFFFLL); | 3546 __ AndImmediate(temp, temp, 0x7FFFFFFFFFFFFFFFLL); |
| 3673 // Compare with +infinity. | 3547 // Compare with +infinity. |
| 3674 __ CompareImmediate(temp, 0x7FF0000000000000LL); | 3548 __ CompareImmediate(temp, 0x7FF0000000000000LL); |
| 3675 return is_negated ? NE : EQ; | 3549 return is_negated ? NE : EQ; |
| 3676 } | 3550 } |
| 3677 } | 3551 } |
| 3678 | 3552 |
| 3679 | |
| 3680 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 3553 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 3681 bool opt) const { | 3554 bool opt) const { |
| 3682 const intptr_t kNumInputs = 2; | 3555 const intptr_t kNumInputs = 2; |
| 3683 const intptr_t kNumTemps = 0; | 3556 const intptr_t kNumTemps = 0; |
| 3684 LocationSummary* summary = new (zone) | 3557 LocationSummary* summary = new (zone) |
| 3685 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3558 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3686 summary->set_in(0, Location::RequiresFpuRegister()); | 3559 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3687 summary->set_in(1, Location::RequiresFpuRegister()); | 3560 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3688 summary->set_out(0, Location::RequiresFpuRegister()); | 3561 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3689 return summary; | 3562 return summary; |
| 3690 } | 3563 } |
| 3691 | 3564 |
| 3692 | |
| 3693 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3565 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3694 const VRegister left = locs()->in(0).fpu_reg(); | 3566 const VRegister left = locs()->in(0).fpu_reg(); |
| 3695 const VRegister right = locs()->in(1).fpu_reg(); | 3567 const VRegister right = locs()->in(1).fpu_reg(); |
| 3696 const VRegister result = locs()->out(0).fpu_reg(); | 3568 const VRegister result = locs()->out(0).fpu_reg(); |
| 3697 | 3569 |
| 3698 switch (op_kind()) { | 3570 switch (op_kind()) { |
| 3699 case Token::kADD: | 3571 case Token::kADD: |
| 3700 __ vadds(result, left, right); | 3572 __ vadds(result, left, right); |
| 3701 break; | 3573 break; |
| 3702 case Token::kSUB: | 3574 case Token::kSUB: |
| 3703 __ vsubs(result, left, right); | 3575 __ vsubs(result, left, right); |
| 3704 break; | 3576 break; |
| 3705 case Token::kMUL: | 3577 case Token::kMUL: |
| 3706 __ vmuls(result, left, right); | 3578 __ vmuls(result, left, right); |
| 3707 break; | 3579 break; |
| 3708 case Token::kDIV: | 3580 case Token::kDIV: |
| 3709 __ vdivs(result, left, right); | 3581 __ vdivs(result, left, right); |
| 3710 break; | 3582 break; |
| 3711 default: | 3583 default: |
| 3712 UNREACHABLE(); | 3584 UNREACHABLE(); |
| 3713 } | 3585 } |
| 3714 } | 3586 } |
| 3715 | 3587 |
| 3716 | |
| 3717 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, | 3588 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, |
| 3718 bool opt) const { | 3589 bool opt) const { |
| 3719 const intptr_t kNumInputs = 2; | 3590 const intptr_t kNumInputs = 2; |
| 3720 const intptr_t kNumTemps = 0; | 3591 const intptr_t kNumTemps = 0; |
| 3721 LocationSummary* summary = new (zone) | 3592 LocationSummary* summary = new (zone) |
| 3722 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3593 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3723 summary->set_in(0, Location::RequiresFpuRegister()); | 3594 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3724 summary->set_in(1, Location::RequiresFpuRegister()); | 3595 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3725 summary->set_out(0, Location::RequiresFpuRegister()); | 3596 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3726 return summary; | 3597 return summary; |
| 3727 } | 3598 } |
| 3728 | 3599 |
| 3729 | |
| 3730 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3600 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3731 const VRegister left = locs()->in(0).fpu_reg(); | 3601 const VRegister left = locs()->in(0).fpu_reg(); |
| 3732 const VRegister right = locs()->in(1).fpu_reg(); | 3602 const VRegister right = locs()->in(1).fpu_reg(); |
| 3733 const VRegister result = locs()->out(0).fpu_reg(); | 3603 const VRegister result = locs()->out(0).fpu_reg(); |
| 3734 | 3604 |
| 3735 switch (op_kind()) { | 3605 switch (op_kind()) { |
| 3736 case Token::kADD: | 3606 case Token::kADD: |
| 3737 __ vaddd(result, left, right); | 3607 __ vaddd(result, left, right); |
| 3738 break; | 3608 break; |
| 3739 case Token::kSUB: | 3609 case Token::kSUB: |
| 3740 __ vsubd(result, left, right); | 3610 __ vsubd(result, left, right); |
| 3741 break; | 3611 break; |
| 3742 case Token::kMUL: | 3612 case Token::kMUL: |
| 3743 __ vmuld(result, left, right); | 3613 __ vmuld(result, left, right); |
| 3744 break; | 3614 break; |
| 3745 case Token::kDIV: | 3615 case Token::kDIV: |
| 3746 __ vdivd(result, left, right); | 3616 __ vdivd(result, left, right); |
| 3747 break; | 3617 break; |
| 3748 default: | 3618 default: |
| 3749 UNREACHABLE(); | 3619 UNREACHABLE(); |
| 3750 } | 3620 } |
| 3751 } | 3621 } |
| 3752 | 3622 |
| 3753 | |
| 3754 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, | 3623 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 3755 bool opt) const { | 3624 bool opt) const { |
| 3756 const intptr_t kNumInputs = 1; | 3625 const intptr_t kNumInputs = 1; |
| 3757 const intptr_t kNumTemps = 0; | 3626 const intptr_t kNumTemps = 0; |
| 3758 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 3627 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 3759 LocationSummary::kNoCall); | 3628 LocationSummary::kNoCall); |
| 3760 summary->set_in(0, Location::RequiresFpuRegister()); | 3629 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3761 summary->set_out(0, Location::RequiresFpuRegister()); | 3630 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3762 return summary; | 3631 return summary; |
| 3763 } | 3632 } |
| 3764 | 3633 |
| 3765 | |
| 3766 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3634 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3767 const VRegister value = locs()->in(0).fpu_reg(); | 3635 const VRegister value = locs()->in(0).fpu_reg(); |
| 3768 const VRegister result = locs()->out(0).fpu_reg(); | 3636 const VRegister result = locs()->out(0).fpu_reg(); |
| 3769 | 3637 |
| 3770 switch (op_kind()) { | 3638 switch (op_kind()) { |
| 3771 case MethodRecognizer::kFloat32x4ShuffleX: | 3639 case MethodRecognizer::kFloat32x4ShuffleX: |
| 3772 __ vinss(result, 0, value, 0); | 3640 __ vinss(result, 0, value, 0); |
| 3773 __ fcvtds(result, result); | 3641 __ fcvtds(result, result); |
| 3774 break; | 3642 break; |
| 3775 case MethodRecognizer::kFloat32x4ShuffleY: | 3643 case MethodRecognizer::kFloat32x4ShuffleY: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3799 __ vinss(result, 1, value, (mask_ >> 2) & 0x3); | 3667 __ vinss(result, 1, value, (mask_ >> 2) & 0x3); |
| 3800 __ vinss(result, 2, value, (mask_ >> 4) & 0x3); | 3668 __ vinss(result, 2, value, (mask_ >> 4) & 0x3); |
| 3801 __ vinss(result, 3, value, (mask_ >> 6) & 0x3); | 3669 __ vinss(result, 3, value, (mask_ >> 6) & 0x3); |
| 3802 } | 3670 } |
| 3803 break; | 3671 break; |
| 3804 default: | 3672 default: |
| 3805 UNREACHABLE(); | 3673 UNREACHABLE(); |
| 3806 } | 3674 } |
| 3807 } | 3675 } |
| 3808 | 3676 |
| 3809 | |
| 3810 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 3677 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |
| 3811 bool opt) const { | 3678 bool opt) const { |
| 3812 const intptr_t kNumInputs = 2; | 3679 const intptr_t kNumInputs = 2; |
| 3813 const intptr_t kNumTemps = 0; | 3680 const intptr_t kNumTemps = 0; |
| 3814 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 3681 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 3815 LocationSummary::kNoCall); | 3682 LocationSummary::kNoCall); |
| 3816 summary->set_in(0, Location::RequiresFpuRegister()); | 3683 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3817 summary->set_in(1, Location::RequiresFpuRegister()); | 3684 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3818 summary->set_out(0, Location::RequiresFpuRegister()); | 3685 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3819 return summary; | 3686 return summary; |
| 3820 } | 3687 } |
| 3821 | 3688 |
| 3822 | |
| 3823 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3689 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3824 const VRegister left = locs()->in(0).fpu_reg(); | 3690 const VRegister left = locs()->in(0).fpu_reg(); |
| 3825 const VRegister right = locs()->in(1).fpu_reg(); | 3691 const VRegister right = locs()->in(1).fpu_reg(); |
| 3826 const VRegister result = locs()->out(0).fpu_reg(); | 3692 const VRegister result = locs()->out(0).fpu_reg(); |
| 3827 | 3693 |
| 3828 switch (op_kind()) { | 3694 switch (op_kind()) { |
| 3829 case MethodRecognizer::kFloat32x4ShuffleMix: | 3695 case MethodRecognizer::kFloat32x4ShuffleMix: |
| 3830 case MethodRecognizer::kInt32x4ShuffleMix: | 3696 case MethodRecognizer::kInt32x4ShuffleMix: |
| 3831 __ vinss(result, 0, left, mask_ & 0x3); | 3697 __ vinss(result, 0, left, mask_ & 0x3); |
| 3832 __ vinss(result, 1, left, (mask_ >> 2) & 0x3); | 3698 __ vinss(result, 1, left, (mask_ >> 2) & 0x3); |
| 3833 __ vinss(result, 2, right, (mask_ >> 4) & 0x3); | 3699 __ vinss(result, 2, right, (mask_ >> 4) & 0x3); |
| 3834 __ vinss(result, 3, right, (mask_ >> 6) & 0x3); | 3700 __ vinss(result, 3, right, (mask_ >> 6) & 0x3); |
| 3835 break; | 3701 break; |
| 3836 default: | 3702 default: |
| 3837 UNREACHABLE(); | 3703 UNREACHABLE(); |
| 3838 } | 3704 } |
| 3839 } | 3705 } |
| 3840 | 3706 |
| 3841 | |
| 3842 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, | 3707 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, |
| 3843 bool opt) const { | 3708 bool opt) const { |
| 3844 const intptr_t kNumInputs = 1; | 3709 const intptr_t kNumInputs = 1; |
| 3845 const intptr_t kNumTemps = 1; | 3710 const intptr_t kNumTemps = 1; |
| 3846 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 3711 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 3847 LocationSummary::kNoCall); | 3712 LocationSummary::kNoCall); |
| 3848 summary->set_in(0, Location::RequiresFpuRegister()); | 3713 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3849 summary->set_temp(0, Location::RequiresRegister()); | 3714 summary->set_temp(0, Location::RequiresRegister()); |
| 3850 summary->set_out(0, Location::RequiresRegister()); | 3715 summary->set_out(0, Location::RequiresRegister()); |
| 3851 return summary; | 3716 return summary; |
| 3852 } | 3717 } |
| 3853 | 3718 |
| 3854 | |
| 3855 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3719 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3856 const VRegister value = locs()->in(0).fpu_reg(); | 3720 const VRegister value = locs()->in(0).fpu_reg(); |
| 3857 const Register out = locs()->out(0).reg(); | 3721 const Register out = locs()->out(0).reg(); |
| 3858 const Register temp = locs()->temp(0).reg(); | 3722 const Register temp = locs()->temp(0).reg(); |
| 3859 | 3723 |
| 3860 // X lane. | 3724 // X lane. |
| 3861 __ vmovrs(out, value, 0); | 3725 __ vmovrs(out, value, 0); |
| 3862 __ LsrImmediate(out, out, 31); | 3726 __ LsrImmediate(out, out, 31); |
| 3863 // Y lane. | 3727 // Y lane. |
| 3864 __ vmovrs(temp, value, 1); | 3728 __ vmovrs(temp, value, 1); |
| 3865 __ LsrImmediate(temp, temp, 31); | 3729 __ LsrImmediate(temp, temp, 31); |
| 3866 __ orr(out, out, Operand(temp, LSL, 1)); | 3730 __ orr(out, out, Operand(temp, LSL, 1)); |
| 3867 // Z lane. | 3731 // Z lane. |
| 3868 __ vmovrs(temp, value, 2); | 3732 __ vmovrs(temp, value, 2); |
| 3869 __ LsrImmediate(temp, temp, 31); | 3733 __ LsrImmediate(temp, temp, 31); |
| 3870 __ orr(out, out, Operand(temp, LSL, 2)); | 3734 __ orr(out, out, Operand(temp, LSL, 2)); |
| 3871 // W lane. | 3735 // W lane. |
| 3872 __ vmovrs(temp, value, 3); | 3736 __ vmovrs(temp, value, 3); |
| 3873 __ LsrImmediate(temp, temp, 31); | 3737 __ LsrImmediate(temp, temp, 31); |
| 3874 __ orr(out, out, Operand(temp, LSL, 3)); | 3738 __ orr(out, out, Operand(temp, LSL, 3)); |
| 3875 // Tag. | 3739 // Tag. |
| 3876 __ SmiTag(out); | 3740 __ SmiTag(out); |
| 3877 } | 3741 } |
| 3878 | 3742 |
| 3879 | |
| 3880 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 3743 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
| 3881 Zone* zone, | 3744 Zone* zone, |
| 3882 bool opt) const { | 3745 bool opt) const { |
| 3883 const intptr_t kNumInputs = 4; | 3746 const intptr_t kNumInputs = 4; |
| 3884 const intptr_t kNumTemps = 0; | 3747 const intptr_t kNumTemps = 0; |
| 3885 LocationSummary* summary = new (zone) | 3748 LocationSummary* summary = new (zone) |
| 3886 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3749 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3887 summary->set_in(0, Location::RequiresFpuRegister()); | 3750 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3888 summary->set_in(1, Location::RequiresFpuRegister()); | 3751 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3889 summary->set_in(2, Location::RequiresFpuRegister()); | 3752 summary->set_in(2, Location::RequiresFpuRegister()); |
| 3890 summary->set_in(3, Location::RequiresFpuRegister()); | 3753 summary->set_in(3, Location::RequiresFpuRegister()); |
| 3891 summary->set_out(0, Location::RequiresFpuRegister()); | 3754 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3892 return summary; | 3755 return summary; |
| 3893 } | 3756 } |
| 3894 | 3757 |
| 3895 | |
| 3896 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3758 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3897 const VRegister v0 = locs()->in(0).fpu_reg(); | 3759 const VRegister v0 = locs()->in(0).fpu_reg(); |
| 3898 const VRegister v1 = locs()->in(1).fpu_reg(); | 3760 const VRegister v1 = locs()->in(1).fpu_reg(); |
| 3899 const VRegister v2 = locs()->in(2).fpu_reg(); | 3761 const VRegister v2 = locs()->in(2).fpu_reg(); |
| 3900 const VRegister v3 = locs()->in(3).fpu_reg(); | 3762 const VRegister v3 = locs()->in(3).fpu_reg(); |
| 3901 const VRegister r = locs()->out(0).fpu_reg(); | 3763 const VRegister r = locs()->out(0).fpu_reg(); |
| 3902 | 3764 |
| 3903 __ fcvtsd(VTMP, v0); | 3765 __ fcvtsd(VTMP, v0); |
| 3904 __ vinss(r, 0, VTMP, 0); | 3766 __ vinss(r, 0, VTMP, 0); |
| 3905 __ fcvtsd(VTMP, v1); | 3767 __ fcvtsd(VTMP, v1); |
| 3906 __ vinss(r, 1, VTMP, 0); | 3768 __ vinss(r, 1, VTMP, 0); |
| 3907 __ fcvtsd(VTMP, v2); | 3769 __ fcvtsd(VTMP, v2); |
| 3908 __ vinss(r, 2, VTMP, 0); | 3770 __ vinss(r, 2, VTMP, 0); |
| 3909 __ fcvtsd(VTMP, v3); | 3771 __ fcvtsd(VTMP, v3); |
| 3910 __ vinss(r, 3, VTMP, 0); | 3772 __ vinss(r, 3, VTMP, 0); |
| 3911 } | 3773 } |
| 3912 | 3774 |
| 3913 | |
| 3914 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, | 3775 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, |
| 3915 bool opt) const { | 3776 bool opt) const { |
| 3916 const intptr_t kNumInputs = 0; | 3777 const intptr_t kNumInputs = 0; |
| 3917 const intptr_t kNumTemps = 0; | 3778 const intptr_t kNumTemps = 0; |
| 3918 LocationSummary* summary = new (zone) | 3779 LocationSummary* summary = new (zone) |
| 3919 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3780 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3920 summary->set_out(0, Location::RequiresFpuRegister()); | 3781 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3921 return summary; | 3782 return summary; |
| 3922 } | 3783 } |
| 3923 | 3784 |
| 3924 | |
| 3925 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3785 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3926 const VRegister v = locs()->out(0).fpu_reg(); | 3786 const VRegister v = locs()->out(0).fpu_reg(); |
| 3927 __ veor(v, v, v); | 3787 __ veor(v, v, v); |
| 3928 } | 3788 } |
| 3929 | 3789 |
| 3930 | |
| 3931 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, | 3790 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, |
| 3932 bool opt) const { | 3791 bool opt) const { |
| 3933 const intptr_t kNumInputs = 1; | 3792 const intptr_t kNumInputs = 1; |
| 3934 const intptr_t kNumTemps = 0; | 3793 const intptr_t kNumTemps = 0; |
| 3935 LocationSummary* summary = new (zone) | 3794 LocationSummary* summary = new (zone) |
| 3936 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3795 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3937 summary->set_in(0, Location::RequiresFpuRegister()); | 3796 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3938 summary->set_out(0, Location::RequiresFpuRegister()); | 3797 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3939 return summary; | 3798 return summary; |
| 3940 } | 3799 } |
| 3941 | 3800 |
| 3942 | |
| 3943 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3801 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3944 const VRegister value = locs()->in(0).fpu_reg(); | 3802 const VRegister value = locs()->in(0).fpu_reg(); |
| 3945 const VRegister result = locs()->out(0).fpu_reg(); | 3803 const VRegister result = locs()->out(0).fpu_reg(); |
| 3946 | 3804 |
| 3947 // Convert to Float32. | 3805 // Convert to Float32. |
| 3948 __ fcvtsd(VTMP, value); | 3806 __ fcvtsd(VTMP, value); |
| 3949 | 3807 |
| 3950 // Splat across all lanes. | 3808 // Splat across all lanes. |
| 3951 __ vdups(result, VTMP, 0); | 3809 __ vdups(result, VTMP, 0); |
| 3952 } | 3810 } |
| 3953 | 3811 |
| 3954 | |
| 3955 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, | 3812 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, |
| 3956 bool opt) const { | 3813 bool opt) const { |
| 3957 const intptr_t kNumInputs = 2; | 3814 const intptr_t kNumInputs = 2; |
| 3958 const intptr_t kNumTemps = 0; | 3815 const intptr_t kNumTemps = 0; |
| 3959 LocationSummary* summary = new (zone) | 3816 LocationSummary* summary = new (zone) |
| 3960 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3817 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3961 summary->set_in(0, Location::RequiresFpuRegister()); | 3818 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3962 summary->set_in(1, Location::RequiresFpuRegister()); | 3819 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3963 summary->set_out(0, Location::RequiresFpuRegister()); | 3820 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3964 return summary; | 3821 return summary; |
| 3965 } | 3822 } |
| 3966 | 3823 |
| 3967 | |
| 3968 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3824 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3969 const VRegister left = locs()->in(0).fpu_reg(); | 3825 const VRegister left = locs()->in(0).fpu_reg(); |
| 3970 const VRegister right = locs()->in(1).fpu_reg(); | 3826 const VRegister right = locs()->in(1).fpu_reg(); |
| 3971 const VRegister result = locs()->out(0).fpu_reg(); | 3827 const VRegister result = locs()->out(0).fpu_reg(); |
| 3972 | 3828 |
| 3973 switch (op_kind()) { | 3829 switch (op_kind()) { |
| 3974 case MethodRecognizer::kFloat32x4Equal: | 3830 case MethodRecognizer::kFloat32x4Equal: |
| 3975 __ vceqs(result, left, right); | 3831 __ vceqs(result, left, right); |
| 3976 break; | 3832 break; |
| 3977 case MethodRecognizer::kFloat32x4NotEqual: | 3833 case MethodRecognizer::kFloat32x4NotEqual: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3990 break; | 3846 break; |
| 3991 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 3847 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
| 3992 __ vcges(result, right, left); | 3848 __ vcges(result, right, left); |
| 3993 break; | 3849 break; |
| 3994 | 3850 |
| 3995 default: | 3851 default: |
| 3996 UNREACHABLE(); | 3852 UNREACHABLE(); |
| 3997 } | 3853 } |
| 3998 } | 3854 } |
| 3999 | 3855 |
| 4000 | |
| 4001 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, | 3856 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, |
| 4002 bool opt) const { | 3857 bool opt) const { |
| 4003 const intptr_t kNumInputs = 2; | 3858 const intptr_t kNumInputs = 2; |
| 4004 const intptr_t kNumTemps = 0; | 3859 const intptr_t kNumTemps = 0; |
| 4005 LocationSummary* summary = new (zone) | 3860 LocationSummary* summary = new (zone) |
| 4006 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3861 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4007 summary->set_in(0, Location::RequiresFpuRegister()); | 3862 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4008 summary->set_in(1, Location::RequiresFpuRegister()); | 3863 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4009 summary->set_out(0, Location::RequiresFpuRegister()); | 3864 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4010 return summary; | 3865 return summary; |
| 4011 } | 3866 } |
| 4012 | 3867 |
| 4013 | |
| 4014 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3868 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4015 const VRegister left = locs()->in(0).fpu_reg(); | 3869 const VRegister left = locs()->in(0).fpu_reg(); |
| 4016 const VRegister right = locs()->in(1).fpu_reg(); | 3870 const VRegister right = locs()->in(1).fpu_reg(); |
| 4017 const VRegister result = locs()->out(0).fpu_reg(); | 3871 const VRegister result = locs()->out(0).fpu_reg(); |
| 4018 | 3872 |
| 4019 switch (op_kind()) { | 3873 switch (op_kind()) { |
| 4020 case MethodRecognizer::kFloat32x4Min: | 3874 case MethodRecognizer::kFloat32x4Min: |
| 4021 __ vmins(result, left, right); | 3875 __ vmins(result, left, right); |
| 4022 break; | 3876 break; |
| 4023 case MethodRecognizer::kFloat32x4Max: | 3877 case MethodRecognizer::kFloat32x4Max: |
| 4024 __ vmaxs(result, left, right); | 3878 __ vmaxs(result, left, right); |
| 4025 break; | 3879 break; |
| 4026 default: | 3880 default: |
| 4027 UNREACHABLE(); | 3881 UNREACHABLE(); |
| 4028 } | 3882 } |
| 4029 } | 3883 } |
| 4030 | 3884 |
| 4031 | |
| 4032 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, | 3885 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, |
| 4033 bool opt) const { | 3886 bool opt) const { |
| 4034 const intptr_t kNumInputs = 1; | 3887 const intptr_t kNumInputs = 1; |
| 4035 const intptr_t kNumTemps = 0; | 3888 const intptr_t kNumTemps = 0; |
| 4036 LocationSummary* summary = new (zone) | 3889 LocationSummary* summary = new (zone) |
| 4037 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3890 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4038 summary->set_in(0, Location::RequiresFpuRegister()); | 3891 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4039 summary->set_out(0, Location::RequiresFpuRegister()); | 3892 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4040 return summary; | 3893 return summary; |
| 4041 } | 3894 } |
| 4042 | 3895 |
| 4043 | |
| 4044 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3896 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4045 const VRegister left = locs()->in(0).fpu_reg(); | 3897 const VRegister left = locs()->in(0).fpu_reg(); |
| 4046 const VRegister result = locs()->out(0).fpu_reg(); | 3898 const VRegister result = locs()->out(0).fpu_reg(); |
| 4047 | 3899 |
| 4048 switch (op_kind()) { | 3900 switch (op_kind()) { |
| 4049 case MethodRecognizer::kFloat32x4Sqrt: | 3901 case MethodRecognizer::kFloat32x4Sqrt: |
| 4050 __ vsqrts(result, left); | 3902 __ vsqrts(result, left); |
| 4051 break; | 3903 break; |
| 4052 case MethodRecognizer::kFloat32x4Reciprocal: | 3904 case MethodRecognizer::kFloat32x4Reciprocal: |
| 4053 __ VRecps(result, left); | 3905 __ VRecps(result, left); |
| 4054 break; | 3906 break; |
| 4055 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 3907 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
| 4056 __ VRSqrts(result, left); | 3908 __ VRSqrts(result, left); |
| 4057 break; | 3909 break; |
| 4058 default: | 3910 default: |
| 4059 UNREACHABLE(); | 3911 UNREACHABLE(); |
| 4060 } | 3912 } |
| 4061 } | 3913 } |
| 4062 | 3914 |
| 4063 | |
| 4064 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, | 3915 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, |
| 4065 bool opt) const { | 3916 bool opt) const { |
| 4066 const intptr_t kNumInputs = 2; | 3917 const intptr_t kNumInputs = 2; |
| 4067 const intptr_t kNumTemps = 0; | 3918 const intptr_t kNumTemps = 0; |
| 4068 LocationSummary* summary = new (zone) | 3919 LocationSummary* summary = new (zone) |
| 4069 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3920 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4070 summary->set_in(0, Location::RequiresFpuRegister()); | 3921 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4071 summary->set_in(1, Location::RequiresFpuRegister()); | 3922 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4072 summary->set_out(0, Location::RequiresFpuRegister()); | 3923 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4073 return summary; | 3924 return summary; |
| 4074 } | 3925 } |
| 4075 | 3926 |
| 4076 | |
| 4077 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3927 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4078 const VRegister left = locs()->in(0).fpu_reg(); | 3928 const VRegister left = locs()->in(0).fpu_reg(); |
| 4079 const VRegister right = locs()->in(1).fpu_reg(); | 3929 const VRegister right = locs()->in(1).fpu_reg(); |
| 4080 const VRegister result = locs()->out(0).fpu_reg(); | 3930 const VRegister result = locs()->out(0).fpu_reg(); |
| 4081 | 3931 |
| 4082 switch (op_kind()) { | 3932 switch (op_kind()) { |
| 4083 case MethodRecognizer::kFloat32x4Scale: | 3933 case MethodRecognizer::kFloat32x4Scale: |
| 4084 __ fcvtsd(VTMP, left); | 3934 __ fcvtsd(VTMP, left); |
| 4085 __ vdups(result, VTMP, 0); | 3935 __ vdups(result, VTMP, 0); |
| 4086 __ vmuls(result, result, right); | 3936 __ vmuls(result, result, right); |
| 4087 break; | 3937 break; |
| 4088 default: | 3938 default: |
| 4089 UNREACHABLE(); | 3939 UNREACHABLE(); |
| 4090 } | 3940 } |
| 4091 } | 3941 } |
| 4092 | 3942 |
| 4093 | |
| 4094 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, | 3943 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, |
| 4095 bool opt) const { | 3944 bool opt) const { |
| 4096 const intptr_t kNumInputs = 1; | 3945 const intptr_t kNumInputs = 1; |
| 4097 const intptr_t kNumTemps = 0; | 3946 const intptr_t kNumTemps = 0; |
| 4098 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 3947 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4099 LocationSummary::kNoCall); | 3948 LocationSummary::kNoCall); |
| 4100 summary->set_in(0, Location::RequiresFpuRegister()); | 3949 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4101 summary->set_out(0, Location::RequiresFpuRegister()); | 3950 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4102 return summary; | 3951 return summary; |
| 4103 } | 3952 } |
| 4104 | 3953 |
| 4105 | |
| 4106 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3954 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4107 const VRegister left = locs()->in(0).fpu_reg(); | 3955 const VRegister left = locs()->in(0).fpu_reg(); |
| 4108 const VRegister result = locs()->out(0).fpu_reg(); | 3956 const VRegister result = locs()->out(0).fpu_reg(); |
| 4109 | 3957 |
| 4110 switch (op_kind()) { | 3958 switch (op_kind()) { |
| 4111 case MethodRecognizer::kFloat32x4Negate: | 3959 case MethodRecognizer::kFloat32x4Negate: |
| 4112 __ vnegs(result, left); | 3960 __ vnegs(result, left); |
| 4113 break; | 3961 break; |
| 4114 case MethodRecognizer::kFloat32x4Absolute: | 3962 case MethodRecognizer::kFloat32x4Absolute: |
| 4115 __ vabss(result, left); | 3963 __ vabss(result, left); |
| 4116 break; | 3964 break; |
| 4117 default: | 3965 default: |
| 4118 UNREACHABLE(); | 3966 UNREACHABLE(); |
| 4119 } | 3967 } |
| 4120 } | 3968 } |
| 4121 | 3969 |
| 4122 | |
| 4123 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, | 3970 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, |
| 4124 bool opt) const { | 3971 bool opt) const { |
| 4125 const intptr_t kNumInputs = 3; | 3972 const intptr_t kNumInputs = 3; |
| 4126 const intptr_t kNumTemps = 0; | 3973 const intptr_t kNumTemps = 0; |
| 4127 LocationSummary* summary = new (zone) | 3974 LocationSummary* summary = new (zone) |
| 4128 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3975 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4129 summary->set_in(0, Location::RequiresFpuRegister()); | 3976 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4130 summary->set_in(1, Location::RequiresFpuRegister()); | 3977 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4131 summary->set_in(2, Location::RequiresFpuRegister()); | 3978 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4132 summary->set_out(0, Location::RequiresFpuRegister()); | 3979 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4133 return summary; | 3980 return summary; |
| 4134 } | 3981 } |
| 4135 | 3982 |
| 4136 | |
| 4137 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3983 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4138 const VRegister left = locs()->in(0).fpu_reg(); | 3984 const VRegister left = locs()->in(0).fpu_reg(); |
| 4139 const VRegister lower = locs()->in(1).fpu_reg(); | 3985 const VRegister lower = locs()->in(1).fpu_reg(); |
| 4140 const VRegister upper = locs()->in(2).fpu_reg(); | 3986 const VRegister upper = locs()->in(2).fpu_reg(); |
| 4141 const VRegister result = locs()->out(0).fpu_reg(); | 3987 const VRegister result = locs()->out(0).fpu_reg(); |
| 4142 __ vmins(result, left, upper); | 3988 __ vmins(result, left, upper); |
| 4143 __ vmaxs(result, result, lower); | 3989 __ vmaxs(result, result, lower); |
| 4144 } | 3990 } |
| 4145 | 3991 |
| 4146 | |
| 4147 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, | 3992 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, |
| 4148 bool opt) const { | 3993 bool opt) const { |
| 4149 const intptr_t kNumInputs = 2; | 3994 const intptr_t kNumInputs = 2; |
| 4150 const intptr_t kNumTemps = 0; | 3995 const intptr_t kNumTemps = 0; |
| 4151 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 3996 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4152 LocationSummary::kNoCall); | 3997 LocationSummary::kNoCall); |
| 4153 summary->set_in(0, Location::RequiresFpuRegister()); | 3998 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4154 summary->set_in(1, Location::RequiresFpuRegister()); | 3999 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4155 summary->set_out(0, Location::RequiresFpuRegister()); | 4000 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4156 return summary; | 4001 return summary; |
| 4157 } | 4002 } |
| 4158 | 4003 |
| 4159 | |
| 4160 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4004 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4161 const VRegister replacement = locs()->in(0).fpu_reg(); | 4005 const VRegister replacement = locs()->in(0).fpu_reg(); |
| 4162 const VRegister value = locs()->in(1).fpu_reg(); | 4006 const VRegister value = locs()->in(1).fpu_reg(); |
| 4163 const VRegister result = locs()->out(0).fpu_reg(); | 4007 const VRegister result = locs()->out(0).fpu_reg(); |
| 4164 | 4008 |
| 4165 __ fcvtsd(VTMP, replacement); | 4009 __ fcvtsd(VTMP, replacement); |
| 4166 if (result != value) { | 4010 if (result != value) { |
| 4167 __ vmov(result, value); | 4011 __ vmov(result, value); |
| 4168 } | 4012 } |
| 4169 | 4013 |
| 4170 switch (op_kind()) { | 4014 switch (op_kind()) { |
| 4171 case MethodRecognizer::kFloat32x4WithX: | 4015 case MethodRecognizer::kFloat32x4WithX: |
| 4172 __ vinss(result, 0, VTMP, 0); | 4016 __ vinss(result, 0, VTMP, 0); |
| 4173 break; | 4017 break; |
| 4174 case MethodRecognizer::kFloat32x4WithY: | 4018 case MethodRecognizer::kFloat32x4WithY: |
| 4175 __ vinss(result, 1, VTMP, 0); | 4019 __ vinss(result, 1, VTMP, 0); |
| 4176 break; | 4020 break; |
| 4177 case MethodRecognizer::kFloat32x4WithZ: | 4021 case MethodRecognizer::kFloat32x4WithZ: |
| 4178 __ vinss(result, 2, VTMP, 0); | 4022 __ vinss(result, 2, VTMP, 0); |
| 4179 break; | 4023 break; |
| 4180 case MethodRecognizer::kFloat32x4WithW: | 4024 case MethodRecognizer::kFloat32x4WithW: |
| 4181 __ vinss(result, 3, VTMP, 0); | 4025 __ vinss(result, 3, VTMP, 0); |
| 4182 break; | 4026 break; |
| 4183 default: | 4027 default: |
| 4184 UNREACHABLE(); | 4028 UNREACHABLE(); |
| 4185 } | 4029 } |
| 4186 } | 4030 } |
| 4187 | 4031 |
| 4188 | |
| 4189 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, | 4032 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, |
| 4190 bool opt) const { | 4033 bool opt) const { |
| 4191 const intptr_t kNumInputs = 1; | 4034 const intptr_t kNumInputs = 1; |
| 4192 const intptr_t kNumTemps = 0; | 4035 const intptr_t kNumTemps = 0; |
| 4193 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 4036 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4194 LocationSummary::kNoCall); | 4037 LocationSummary::kNoCall); |
| 4195 summary->set_in(0, Location::RequiresFpuRegister()); | 4038 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4196 summary->set_out(0, Location::RequiresFpuRegister()); | 4039 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4197 return summary; | 4040 return summary; |
| 4198 } | 4041 } |
| 4199 | 4042 |
| 4200 | |
| 4201 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4043 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4202 const VRegister value = locs()->in(0).fpu_reg(); | 4044 const VRegister value = locs()->in(0).fpu_reg(); |
| 4203 const VRegister result = locs()->out(0).fpu_reg(); | 4045 const VRegister result = locs()->out(0).fpu_reg(); |
| 4204 | 4046 |
| 4205 if (value != result) { | 4047 if (value != result) { |
| 4206 __ vmov(result, value); | 4048 __ vmov(result, value); |
| 4207 } | 4049 } |
| 4208 } | 4050 } |
| 4209 | 4051 |
| 4210 | |
| 4211 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 4052 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 4212 bool opt) const { | 4053 bool opt) const { |
| 4213 const intptr_t kNumInputs = 1; | 4054 const intptr_t kNumInputs = 1; |
| 4214 const intptr_t kNumTemps = 0; | 4055 const intptr_t kNumTemps = 0; |
| 4215 LocationSummary* summary = new (zone) | 4056 LocationSummary* summary = new (zone) |
| 4216 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4057 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4217 summary->set_in(0, Location::RequiresFpuRegister()); | 4058 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4218 summary->set_out(0, Location::RequiresFpuRegister()); | 4059 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4219 return summary; | 4060 return summary; |
| 4220 } | 4061 } |
| 4221 | 4062 |
| 4222 | |
| 4223 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4063 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4224 const VRegister value = locs()->in(0).fpu_reg(); | 4064 const VRegister value = locs()->in(0).fpu_reg(); |
| 4225 const VRegister result = locs()->out(0).fpu_reg(); | 4065 const VRegister result = locs()->out(0).fpu_reg(); |
| 4226 | 4066 |
| 4227 switch (op_kind()) { | 4067 switch (op_kind()) { |
| 4228 case MethodRecognizer::kFloat64x2GetX: | 4068 case MethodRecognizer::kFloat64x2GetX: |
| 4229 __ vinsd(result, 0, value, 0); | 4069 __ vinsd(result, 0, value, 0); |
| 4230 break; | 4070 break; |
| 4231 case MethodRecognizer::kFloat64x2GetY: | 4071 case MethodRecognizer::kFloat64x2GetY: |
| 4232 __ vinsd(result, 0, value, 1); | 4072 __ vinsd(result, 0, value, 1); |
| 4233 break; | 4073 break; |
| 4234 default: | 4074 default: |
| 4235 UNREACHABLE(); | 4075 UNREACHABLE(); |
| 4236 } | 4076 } |
| 4237 } | 4077 } |
| 4238 | 4078 |
| 4239 | |
| 4240 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 4079 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |
| 4241 bool opt) const { | 4080 bool opt) const { |
| 4242 const intptr_t kNumInputs = 0; | 4081 const intptr_t kNumInputs = 0; |
| 4243 const intptr_t kNumTemps = 0; | 4082 const intptr_t kNumTemps = 0; |
| 4244 LocationSummary* summary = new (zone) | 4083 LocationSummary* summary = new (zone) |
| 4245 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4084 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4246 summary->set_out(0, Location::RequiresFpuRegister()); | 4085 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4247 return summary; | 4086 return summary; |
| 4248 } | 4087 } |
| 4249 | 4088 |
| 4250 | |
| 4251 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4089 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4252 const VRegister v = locs()->out(0).fpu_reg(); | 4090 const VRegister v = locs()->out(0).fpu_reg(); |
| 4253 __ veor(v, v, v); | 4091 __ veor(v, v, v); |
| 4254 } | 4092 } |
| 4255 | 4093 |
| 4256 | |
| 4257 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 4094 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |
| 4258 bool opt) const { | 4095 bool opt) const { |
| 4259 const intptr_t kNumInputs = 1; | 4096 const intptr_t kNumInputs = 1; |
| 4260 const intptr_t kNumTemps = 0; | 4097 const intptr_t kNumTemps = 0; |
| 4261 LocationSummary* summary = new (zone) | 4098 LocationSummary* summary = new (zone) |
| 4262 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4099 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4263 summary->set_in(0, Location::RequiresFpuRegister()); | 4100 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4264 summary->set_out(0, Location::RequiresFpuRegister()); | 4101 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4265 return summary; | 4102 return summary; |
| 4266 } | 4103 } |
| 4267 | 4104 |
| 4268 | |
| 4269 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4105 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4270 const VRegister value = locs()->in(0).fpu_reg(); | 4106 const VRegister value = locs()->in(0).fpu_reg(); |
| 4271 const VRegister result = locs()->out(0).fpu_reg(); | 4107 const VRegister result = locs()->out(0).fpu_reg(); |
| 4272 __ vdupd(result, value, 0); | 4108 __ vdupd(result, value, 0); |
| 4273 } | 4109 } |
| 4274 | 4110 |
| 4275 | |
| 4276 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 4111 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
| 4277 Zone* zone, | 4112 Zone* zone, |
| 4278 bool opt) const { | 4113 bool opt) const { |
| 4279 const intptr_t kNumInputs = 2; | 4114 const intptr_t kNumInputs = 2; |
| 4280 const intptr_t kNumTemps = 0; | 4115 const intptr_t kNumTemps = 0; |
| 4281 LocationSummary* summary = new (zone) | 4116 LocationSummary* summary = new (zone) |
| 4282 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4117 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4283 summary->set_in(0, Location::RequiresFpuRegister()); | 4118 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4284 summary->set_in(1, Location::RequiresFpuRegister()); | 4119 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4285 summary->set_out(0, Location::RequiresFpuRegister()); | 4120 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4286 return summary; | 4121 return summary; |
| 4287 } | 4122 } |
| 4288 | 4123 |
| 4289 | |
| 4290 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4124 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4291 const VRegister v0 = locs()->in(0).fpu_reg(); | 4125 const VRegister v0 = locs()->in(0).fpu_reg(); |
| 4292 const VRegister v1 = locs()->in(1).fpu_reg(); | 4126 const VRegister v1 = locs()->in(1).fpu_reg(); |
| 4293 const VRegister r = locs()->out(0).fpu_reg(); | 4127 const VRegister r = locs()->out(0).fpu_reg(); |
| 4294 __ vinsd(r, 0, v0, 0); | 4128 __ vinsd(r, 0, v0, 0); |
| 4295 __ vinsd(r, 1, v1, 0); | 4129 __ vinsd(r, 1, v1, 0); |
| 4296 } | 4130 } |
| 4297 | 4131 |
| 4298 | |
| 4299 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 4132 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
| 4300 Zone* zone, | 4133 Zone* zone, |
| 4301 bool opt) const { | 4134 bool opt) const { |
| 4302 const intptr_t kNumInputs = 1; | 4135 const intptr_t kNumInputs = 1; |
| 4303 const intptr_t kNumTemps = 0; | 4136 const intptr_t kNumTemps = 0; |
| 4304 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 4137 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4305 LocationSummary::kNoCall); | 4138 LocationSummary::kNoCall); |
| 4306 summary->set_in(0, Location::RequiresFpuRegister()); | 4139 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4307 summary->set_out(0, Location::RequiresFpuRegister()); | 4140 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4308 return summary; | 4141 return summary; |
| 4309 } | 4142 } |
| 4310 | 4143 |
| 4311 | |
| 4312 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4144 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4313 const VRegister q = locs()->in(0).fpu_reg(); | 4145 const VRegister q = locs()->in(0).fpu_reg(); |
| 4314 const VRegister r = locs()->out(0).fpu_reg(); | 4146 const VRegister r = locs()->out(0).fpu_reg(); |
| 4315 | 4147 |
| 4316 // Zero register. | 4148 // Zero register. |
| 4317 __ veor(r, r, r); | 4149 __ veor(r, r, r); |
| 4318 // Set X lane. | 4150 // Set X lane. |
| 4319 __ vinsd(VTMP, 0, q, 0); | 4151 __ vinsd(VTMP, 0, q, 0); |
| 4320 __ fcvtsd(VTMP, VTMP); | 4152 __ fcvtsd(VTMP, VTMP); |
| 4321 __ vinss(r, 0, VTMP, 0); | 4153 __ vinss(r, 0, VTMP, 0); |
| 4322 // Set Y lane. | 4154 // Set Y lane. |
| 4323 __ vinsd(VTMP, 0, q, 1); | 4155 __ vinsd(VTMP, 0, q, 1); |
| 4324 __ fcvtsd(VTMP, VTMP); | 4156 __ fcvtsd(VTMP, VTMP); |
| 4325 __ vinss(r, 1, VTMP, 0); | 4157 __ vinss(r, 1, VTMP, 0); |
| 4326 } | 4158 } |
| 4327 | 4159 |
| 4328 | |
| 4329 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 4160 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
| 4330 Zone* zone, | 4161 Zone* zone, |
| 4331 bool opt) const { | 4162 bool opt) const { |
| 4332 const intptr_t kNumInputs = 1; | 4163 const intptr_t kNumInputs = 1; |
| 4333 const intptr_t kNumTemps = 0; | 4164 const intptr_t kNumTemps = 0; |
| 4334 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 4165 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4335 LocationSummary::kNoCall); | 4166 LocationSummary::kNoCall); |
| 4336 summary->set_in(0, Location::RequiresFpuRegister()); | 4167 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4337 summary->set_out(0, Location::RequiresFpuRegister()); | 4168 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4338 return summary; | 4169 return summary; |
| 4339 } | 4170 } |
| 4340 | 4171 |
| 4341 | |
| 4342 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4172 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4343 const VRegister q = locs()->in(0).fpu_reg(); | 4173 const VRegister q = locs()->in(0).fpu_reg(); |
| 4344 const VRegister r = locs()->out(0).fpu_reg(); | 4174 const VRegister r = locs()->out(0).fpu_reg(); |
| 4345 | 4175 |
| 4346 // Set X. | 4176 // Set X. |
| 4347 __ vinss(VTMP, 0, q, 0); | 4177 __ vinss(VTMP, 0, q, 0); |
| 4348 __ fcvtds(VTMP, VTMP); | 4178 __ fcvtds(VTMP, VTMP); |
| 4349 __ vinsd(r, 0, VTMP, 0); | 4179 __ vinsd(r, 0, VTMP, 0); |
| 4350 // Set Y. | 4180 // Set Y. |
| 4351 __ vinss(VTMP, 0, q, 1); | 4181 __ vinss(VTMP, 0, q, 1); |
| 4352 __ fcvtds(VTMP, VTMP); | 4182 __ fcvtds(VTMP, VTMP); |
| 4353 __ vinsd(r, 1, VTMP, 0); | 4183 __ vinsd(r, 1, VTMP, 0); |
| 4354 } | 4184 } |
| 4355 | 4185 |
| 4356 | |
| 4357 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4186 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, |
| 4358 bool opt) const { | 4187 bool opt) const { |
| 4359 const intptr_t kNumInputs = 1; | 4188 const intptr_t kNumInputs = 1; |
| 4360 const intptr_t kNumTemps = 0; | 4189 const intptr_t kNumTemps = 0; |
| 4361 LocationSummary* summary = new (zone) | 4190 LocationSummary* summary = new (zone) |
| 4362 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4191 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4363 | 4192 |
| 4364 if (representation() == kTagged) { | 4193 if (representation() == kTagged) { |
| 4365 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 4194 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |
| 4366 summary->set_in(0, Location::RequiresFpuRegister()); | 4195 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4367 summary->set_out(0, Location::RequiresRegister()); | 4196 summary->set_out(0, Location::RequiresRegister()); |
| 4368 } else { | 4197 } else { |
| 4369 summary->set_in(0, Location::RequiresFpuRegister()); | 4198 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4370 summary->set_out(0, Location::RequiresFpuRegister()); | 4199 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4371 } | 4200 } |
| 4372 return summary; | 4201 return summary; |
| 4373 } | 4202 } |
| 4374 | 4203 |
| 4375 | |
| 4376 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4204 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4377 const VRegister value = locs()->in(0).fpu_reg(); | 4205 const VRegister value = locs()->in(0).fpu_reg(); |
| 4378 | 4206 |
| 4379 if ((op_kind() == MethodRecognizer::kFloat64x2GetSignMask)) { | 4207 if ((op_kind() == MethodRecognizer::kFloat64x2GetSignMask)) { |
| 4380 const Register out = locs()->out(0).reg(); | 4208 const Register out = locs()->out(0).reg(); |
| 4381 | 4209 |
| 4382 // Bits of X lane. | 4210 // Bits of X lane. |
| 4383 __ vmovrd(out, value, 0); | 4211 __ vmovrd(out, value, 0); |
| 4384 __ LsrImmediate(out, out, 63); | 4212 __ LsrImmediate(out, out, 63); |
| 4385 // Bits of Y lane. | 4213 // Bits of Y lane. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4401 __ vabsd(result, value); | 4229 __ vabsd(result, value); |
| 4402 break; | 4230 break; |
| 4403 case MethodRecognizer::kFloat64x2Sqrt: | 4231 case MethodRecognizer::kFloat64x2Sqrt: |
| 4404 __ vsqrtd(result, value); | 4232 __ vsqrtd(result, value); |
| 4405 break; | 4233 break; |
| 4406 default: | 4234 default: |
| 4407 UNREACHABLE(); | 4235 UNREACHABLE(); |
| 4408 } | 4236 } |
| 4409 } | 4237 } |
| 4410 | 4238 |
| 4411 | |
| 4412 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, | 4239 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, |
| 4413 bool opt) const { | 4240 bool opt) const { |
| 4414 const intptr_t kNumInputs = 2; | 4241 const intptr_t kNumInputs = 2; |
| 4415 const intptr_t kNumTemps = 0; | 4242 const intptr_t kNumTemps = 0; |
| 4416 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 4243 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4417 LocationSummary::kNoCall); | 4244 LocationSummary::kNoCall); |
| 4418 summary->set_in(0, Location::RequiresFpuRegister()); | 4245 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4419 summary->set_in(1, Location::RequiresFpuRegister()); | 4246 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4420 summary->set_out(0, Location::SameAsFirstInput()); | 4247 summary->set_out(0, Location::SameAsFirstInput()); |
| 4421 return summary; | 4248 return summary; |
| 4422 } | 4249 } |
| 4423 | 4250 |
| 4424 | |
| 4425 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4251 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4426 const VRegister left = locs()->in(0).fpu_reg(); | 4252 const VRegister left = locs()->in(0).fpu_reg(); |
| 4427 const VRegister right = locs()->in(1).fpu_reg(); | 4253 const VRegister right = locs()->in(1).fpu_reg(); |
| 4428 const VRegister out = locs()->out(0).fpu_reg(); | 4254 const VRegister out = locs()->out(0).fpu_reg(); |
| 4429 ASSERT(left == out); | 4255 ASSERT(left == out); |
| 4430 | 4256 |
| 4431 switch (op_kind()) { | 4257 switch (op_kind()) { |
| 4432 case MethodRecognizer::kFloat64x2Scale: | 4258 case MethodRecognizer::kFloat64x2Scale: |
| 4433 __ vdupd(VTMP, right, 0); | 4259 __ vdupd(VTMP, right, 0); |
| 4434 __ vmuld(out, left, VTMP); | 4260 __ vmuld(out, left, VTMP); |
| 4435 break; | 4261 break; |
| 4436 case MethodRecognizer::kFloat64x2WithX: | 4262 case MethodRecognizer::kFloat64x2WithX: |
| 4437 __ vinsd(out, 0, right, 0); | 4263 __ vinsd(out, 0, right, 0); |
| 4438 break; | 4264 break; |
| 4439 case MethodRecognizer::kFloat64x2WithY: | 4265 case MethodRecognizer::kFloat64x2WithY: |
| 4440 __ vinsd(out, 1, right, 0); | 4266 __ vinsd(out, 1, right, 0); |
| 4441 break; | 4267 break; |
| 4442 case MethodRecognizer::kFloat64x2Min: | 4268 case MethodRecognizer::kFloat64x2Min: |
| 4443 __ vmind(out, left, right); | 4269 __ vmind(out, left, right); |
| 4444 break; | 4270 break; |
| 4445 case MethodRecognizer::kFloat64x2Max: | 4271 case MethodRecognizer::kFloat64x2Max: |
| 4446 __ vmaxd(out, left, right); | 4272 __ vmaxd(out, left, right); |
| 4447 break; | 4273 break; |
| 4448 default: | 4274 default: |
| 4449 UNREACHABLE(); | 4275 UNREACHABLE(); |
| 4450 } | 4276 } |
| 4451 } | 4277 } |
| 4452 | 4278 |
| 4453 | |
| 4454 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, | 4279 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, |
| 4455 bool opt) const { | 4280 bool opt) const { |
| 4456 const intptr_t kNumInputs = 4; | 4281 const intptr_t kNumInputs = 4; |
| 4457 const intptr_t kNumTemps = 0; | 4282 const intptr_t kNumTemps = 0; |
| 4458 LocationSummary* summary = new (zone) | 4283 LocationSummary* summary = new (zone) |
| 4459 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4284 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4460 summary->set_in(0, Location::RequiresRegister()); | 4285 summary->set_in(0, Location::RequiresRegister()); |
| 4461 summary->set_in(1, Location::RequiresRegister()); | 4286 summary->set_in(1, Location::RequiresRegister()); |
| 4462 summary->set_in(2, Location::RequiresRegister()); | 4287 summary->set_in(2, Location::RequiresRegister()); |
| 4463 summary->set_in(3, Location::RequiresRegister()); | 4288 summary->set_in(3, Location::RequiresRegister()); |
| 4464 summary->set_out(0, Location::RequiresFpuRegister()); | 4289 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4465 return summary; | 4290 return summary; |
| 4466 } | 4291 } |
| 4467 | 4292 |
| 4468 | |
| 4469 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4293 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4470 const Register v0 = locs()->in(0).reg(); | 4294 const Register v0 = locs()->in(0).reg(); |
| 4471 const Register v1 = locs()->in(1).reg(); | 4295 const Register v1 = locs()->in(1).reg(); |
| 4472 const Register v2 = locs()->in(2).reg(); | 4296 const Register v2 = locs()->in(2).reg(); |
| 4473 const Register v3 = locs()->in(3).reg(); | 4297 const Register v3 = locs()->in(3).reg(); |
| 4474 const VRegister result = locs()->out(0).fpu_reg(); | 4298 const VRegister result = locs()->out(0).fpu_reg(); |
| 4475 __ veor(result, result, result); | 4299 __ veor(result, result, result); |
| 4476 __ vinsw(result, 0, v0); | 4300 __ vinsw(result, 0, v0); |
| 4477 __ vinsw(result, 1, v1); | 4301 __ vinsw(result, 1, v1); |
| 4478 __ vinsw(result, 2, v2); | 4302 __ vinsw(result, 2, v2); |
| 4479 __ vinsw(result, 3, v3); | 4303 __ vinsw(result, 3, v3); |
| 4480 } | 4304 } |
| 4481 | 4305 |
| 4482 | |
| 4483 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 4306 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
| 4484 Zone* zone, | 4307 Zone* zone, |
| 4485 bool opt) const { | 4308 bool opt) const { |
| 4486 const intptr_t kNumInputs = 4; | 4309 const intptr_t kNumInputs = 4; |
| 4487 const intptr_t kNumTemps = 1; | 4310 const intptr_t kNumTemps = 1; |
| 4488 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 4311 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4489 LocationSummary::kNoCall); | 4312 LocationSummary::kNoCall); |
| 4490 summary->set_in(0, Location::RequiresRegister()); | 4313 summary->set_in(0, Location::RequiresRegister()); |
| 4491 summary->set_in(1, Location::RequiresRegister()); | 4314 summary->set_in(1, Location::RequiresRegister()); |
| 4492 summary->set_in(2, Location::RequiresRegister()); | 4315 summary->set_in(2, Location::RequiresRegister()); |
| 4493 summary->set_in(3, Location::RequiresRegister()); | 4316 summary->set_in(3, Location::RequiresRegister()); |
| 4494 summary->set_temp(0, Location::RequiresRegister()); | 4317 summary->set_temp(0, Location::RequiresRegister()); |
| 4495 summary->set_out(0, Location::RequiresFpuRegister()); | 4318 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4496 return summary; | 4319 return summary; |
| 4497 } | 4320 } |
| 4498 | 4321 |
| 4499 | |
| 4500 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4322 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4501 const Register v0 = locs()->in(0).reg(); | 4323 const Register v0 = locs()->in(0).reg(); |
| 4502 const Register v1 = locs()->in(1).reg(); | 4324 const Register v1 = locs()->in(1).reg(); |
| 4503 const Register v2 = locs()->in(2).reg(); | 4325 const Register v2 = locs()->in(2).reg(); |
| 4504 const Register v3 = locs()->in(3).reg(); | 4326 const Register v3 = locs()->in(3).reg(); |
| 4505 const Register temp = locs()->temp(0).reg(); | 4327 const Register temp = locs()->temp(0).reg(); |
| 4506 const VRegister result = locs()->out(0).fpu_reg(); | 4328 const VRegister result = locs()->out(0).fpu_reg(); |
| 4507 | 4329 |
| 4508 __ veor(result, result, result); | 4330 __ veor(result, result, result); |
| 4509 __ LoadImmediate(temp, 0xffffffff); | 4331 __ LoadImmediate(temp, 0xffffffff); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4523 __ CompareRegisters(v2, TMP2); | 4345 __ CompareRegisters(v2, TMP2); |
| 4524 __ csel(TMP, temp, ZR, EQ); | 4346 __ csel(TMP, temp, ZR, EQ); |
| 4525 __ vinsw(result, 2, TMP); | 4347 __ vinsw(result, 2, TMP); |
| 4526 | 4348 |
| 4527 // __ CompareObject(v3, Bool::True()); | 4349 // __ CompareObject(v3, Bool::True()); |
| 4528 __ CompareRegisters(v3, TMP2); | 4350 __ CompareRegisters(v3, TMP2); |
| 4529 __ csel(TMP, temp, ZR, EQ); | 4351 __ csel(TMP, temp, ZR, EQ); |
| 4530 __ vinsw(result, 3, TMP); | 4352 __ vinsw(result, 3, TMP); |
| 4531 } | 4353 } |
| 4532 | 4354 |
| 4533 | |
| 4534 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, | 4355 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, |
| 4535 bool opt) const { | 4356 bool opt) const { |
| 4536 const intptr_t kNumInputs = 1; | 4357 const intptr_t kNumInputs = 1; |
| 4537 const intptr_t kNumTemps = 0; | 4358 const intptr_t kNumTemps = 0; |
| 4538 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 4359 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4539 LocationSummary::kNoCall); | 4360 LocationSummary::kNoCall); |
| 4540 summary->set_in(0, Location::RequiresFpuRegister()); | 4361 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4541 summary->set_out(0, Location::RequiresRegister()); | 4362 summary->set_out(0, Location::RequiresRegister()); |
| 4542 return summary; | 4363 return summary; |
| 4543 } | 4364 } |
| 4544 | 4365 |
| 4545 | |
| 4546 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4366 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4547 const VRegister value = locs()->in(0).fpu_reg(); | 4367 const VRegister value = locs()->in(0).fpu_reg(); |
| 4548 const Register result = locs()->out(0).reg(); | 4368 const Register result = locs()->out(0).reg(); |
| 4549 | 4369 |
| 4550 switch (op_kind()) { | 4370 switch (op_kind()) { |
| 4551 case MethodRecognizer::kInt32x4GetFlagX: | 4371 case MethodRecognizer::kInt32x4GetFlagX: |
| 4552 __ vmovrs(result, value, 0); | 4372 __ vmovrs(result, value, 0); |
| 4553 break; | 4373 break; |
| 4554 case MethodRecognizer::kInt32x4GetFlagY: | 4374 case MethodRecognizer::kInt32x4GetFlagY: |
| 4555 __ vmovrs(result, value, 1); | 4375 __ vmovrs(result, value, 1); |
| 4556 break; | 4376 break; |
| 4557 case MethodRecognizer::kInt32x4GetFlagZ: | 4377 case MethodRecognizer::kInt32x4GetFlagZ: |
| 4558 __ vmovrs(result, value, 2); | 4378 __ vmovrs(result, value, 2); |
| 4559 break; | 4379 break; |
| 4560 case MethodRecognizer::kInt32x4GetFlagW: | 4380 case MethodRecognizer::kInt32x4GetFlagW: |
| 4561 __ vmovrs(result, value, 3); | 4381 __ vmovrs(result, value, 3); |
| 4562 break; | 4382 break; |
| 4563 default: | 4383 default: |
| 4564 UNREACHABLE(); | 4384 UNREACHABLE(); |
| 4565 } | 4385 } |
| 4566 | 4386 |
| 4567 __ tst(result, Operand(result)); | 4387 __ tst(result, Operand(result)); |
| 4568 __ LoadObject(result, Bool::True()); | 4388 __ LoadObject(result, Bool::True()); |
| 4569 __ LoadObject(TMP, Bool::False()); | 4389 __ LoadObject(TMP, Bool::False()); |
| 4570 __ csel(result, TMP, result, EQ); | 4390 __ csel(result, TMP, result, EQ); |
| 4571 } | 4391 } |
| 4572 | 4392 |
| 4573 | |
| 4574 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, | 4393 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, |
| 4575 bool opt) const { | 4394 bool opt) const { |
| 4576 const intptr_t kNumInputs = 3; | 4395 const intptr_t kNumInputs = 3; |
| 4577 const intptr_t kNumTemps = 1; | 4396 const intptr_t kNumTemps = 1; |
| 4578 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 4397 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4579 LocationSummary::kNoCall); | 4398 LocationSummary::kNoCall); |
| 4580 summary->set_in(0, Location::RequiresFpuRegister()); | 4399 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4581 summary->set_in(1, Location::RequiresFpuRegister()); | 4400 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4582 summary->set_in(2, Location::RequiresFpuRegister()); | 4401 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4583 summary->set_temp(0, Location::RequiresFpuRegister()); | 4402 summary->set_temp(0, Location::RequiresFpuRegister()); |
| 4584 summary->set_out(0, Location::RequiresFpuRegister()); | 4403 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4585 return summary; | 4404 return summary; |
| 4586 } | 4405 } |
| 4587 | 4406 |
| 4588 | |
| 4589 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4407 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4590 const VRegister mask = locs()->in(0).fpu_reg(); | 4408 const VRegister mask = locs()->in(0).fpu_reg(); |
| 4591 const VRegister trueValue = locs()->in(1).fpu_reg(); | 4409 const VRegister trueValue = locs()->in(1).fpu_reg(); |
| 4592 const VRegister falseValue = locs()->in(2).fpu_reg(); | 4410 const VRegister falseValue = locs()->in(2).fpu_reg(); |
| 4593 const VRegister out = locs()->out(0).fpu_reg(); | 4411 const VRegister out = locs()->out(0).fpu_reg(); |
| 4594 const VRegister temp = locs()->temp(0).fpu_reg(); | 4412 const VRegister temp = locs()->temp(0).fpu_reg(); |
| 4595 | 4413 |
| 4596 // Copy mask. | 4414 // Copy mask. |
| 4597 __ vmov(temp, mask); | 4415 __ vmov(temp, mask); |
| 4598 // Invert it. | 4416 // Invert it. |
| 4599 __ vnot(temp, temp); | 4417 __ vnot(temp, temp); |
| 4600 // mask = mask & trueValue. | 4418 // mask = mask & trueValue. |
| 4601 __ vand(mask, mask, trueValue); | 4419 __ vand(mask, mask, trueValue); |
| 4602 // temp = temp & falseValue. | 4420 // temp = temp & falseValue. |
| 4603 __ vand(temp, temp, falseValue); | 4421 __ vand(temp, temp, falseValue); |
| 4604 // out = mask | temp. | 4422 // out = mask | temp. |
| 4605 __ vorr(out, mask, temp); | 4423 __ vorr(out, mask, temp); |
| 4606 } | 4424 } |
| 4607 | 4425 |
| 4608 | |
| 4609 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, | 4426 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, |
| 4610 bool opt) const { | 4427 bool opt) const { |
| 4611 const intptr_t kNumInputs = 2; | 4428 const intptr_t kNumInputs = 2; |
| 4612 const intptr_t kNumTemps = 0; | 4429 const intptr_t kNumTemps = 0; |
| 4613 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 4430 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4614 LocationSummary::kNoCall); | 4431 LocationSummary::kNoCall); |
| 4615 summary->set_in(0, Location::RequiresFpuRegister()); | 4432 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4616 summary->set_in(1, Location::RequiresRegister()); | 4433 summary->set_in(1, Location::RequiresRegister()); |
| 4617 summary->set_out(0, Location::RequiresFpuRegister()); | 4434 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4618 return summary; | 4435 return summary; |
| 4619 } | 4436 } |
| 4620 | 4437 |
| 4621 | |
| 4622 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4438 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4623 const VRegister mask = locs()->in(0).fpu_reg(); | 4439 const VRegister mask = locs()->in(0).fpu_reg(); |
| 4624 const Register flag = locs()->in(1).reg(); | 4440 const Register flag = locs()->in(1).reg(); |
| 4625 const VRegister result = locs()->out(0).fpu_reg(); | 4441 const VRegister result = locs()->out(0).fpu_reg(); |
| 4626 | 4442 |
| 4627 if (result != mask) { | 4443 if (result != mask) { |
| 4628 __ vmov(result, mask); | 4444 __ vmov(result, mask); |
| 4629 } | 4445 } |
| 4630 | 4446 |
| 4631 __ CompareObject(flag, Bool::True()); | 4447 __ CompareObject(flag, Bool::True()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4642 __ vinsw(result, 2, TMP); | 4458 __ vinsw(result, 2, TMP); |
| 4643 break; | 4459 break; |
| 4644 case MethodRecognizer::kInt32x4WithFlagW: | 4460 case MethodRecognizer::kInt32x4WithFlagW: |
| 4645 __ vinsw(result, 3, TMP); | 4461 __ vinsw(result, 3, TMP); |
| 4646 break; | 4462 break; |
| 4647 default: | 4463 default: |
| 4648 UNREACHABLE(); | 4464 UNREACHABLE(); |
| 4649 } | 4465 } |
| 4650 } | 4466 } |
| 4651 | 4467 |
| 4652 | |
| 4653 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, | 4468 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, |
| 4654 bool opt) const { | 4469 bool opt) const { |
| 4655 const intptr_t kNumInputs = 1; | 4470 const intptr_t kNumInputs = 1; |
| 4656 const intptr_t kNumTemps = 0; | 4471 const intptr_t kNumTemps = 0; |
| 4657 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 4472 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4658 LocationSummary::kNoCall); | 4473 LocationSummary::kNoCall); |
| 4659 summary->set_in(0, Location::RequiresFpuRegister()); | 4474 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4660 summary->set_out(0, Location::RequiresFpuRegister()); | 4475 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4661 return summary; | 4476 return summary; |
| 4662 } | 4477 } |
| 4663 | 4478 |
| 4664 | |
| 4665 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4479 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4666 const VRegister value = locs()->in(0).fpu_reg(); | 4480 const VRegister value = locs()->in(0).fpu_reg(); |
| 4667 const VRegister result = locs()->out(0).fpu_reg(); | 4481 const VRegister result = locs()->out(0).fpu_reg(); |
| 4668 | 4482 |
| 4669 if (value != result) { | 4483 if (value != result) { |
| 4670 __ vmov(result, value); | 4484 __ vmov(result, value); |
| 4671 } | 4485 } |
| 4672 } | 4486 } |
| 4673 | 4487 |
| 4674 | |
| 4675 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, | 4488 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 4676 bool opt) const { | 4489 bool opt) const { |
| 4677 const intptr_t kNumInputs = 2; | 4490 const intptr_t kNumInputs = 2; |
| 4678 const intptr_t kNumTemps = 0; | 4491 const intptr_t kNumTemps = 0; |
| 4679 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, | 4492 LocationSummary* summary = new LocationSummary(zone, kNumInputs, kNumTemps, |
| 4680 LocationSummary::kNoCall); | 4493 LocationSummary::kNoCall); |
| 4681 summary->set_in(0, Location::RequiresFpuRegister()); | 4494 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4682 summary->set_in(1, Location::RequiresFpuRegister()); | 4495 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4683 summary->set_out(0, Location::RequiresFpuRegister()); | 4496 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4684 return summary; | 4497 return summary; |
| 4685 } | 4498 } |
| 4686 | 4499 |
| 4687 | |
| 4688 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4500 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4689 const VRegister left = locs()->in(0).fpu_reg(); | 4501 const VRegister left = locs()->in(0).fpu_reg(); |
| 4690 const VRegister right = locs()->in(1).fpu_reg(); | 4502 const VRegister right = locs()->in(1).fpu_reg(); |
| 4691 const VRegister result = locs()->out(0).fpu_reg(); | 4503 const VRegister result = locs()->out(0).fpu_reg(); |
| 4692 switch (op_kind()) { | 4504 switch (op_kind()) { |
| 4693 case Token::kBIT_AND: | 4505 case Token::kBIT_AND: |
| 4694 __ vand(result, left, right); | 4506 __ vand(result, left, right); |
| 4695 break; | 4507 break; |
| 4696 case Token::kBIT_OR: | 4508 case Token::kBIT_OR: |
| 4697 __ vorr(result, left, right); | 4509 __ vorr(result, left, right); |
| 4698 break; | 4510 break; |
| 4699 case Token::kBIT_XOR: | 4511 case Token::kBIT_XOR: |
| 4700 __ veor(result, left, right); | 4512 __ veor(result, left, right); |
| 4701 break; | 4513 break; |
| 4702 case Token::kADD: | 4514 case Token::kADD: |
| 4703 __ vaddw(result, left, right); | 4515 __ vaddw(result, left, right); |
| 4704 break; | 4516 break; |
| 4705 case Token::kSUB: | 4517 case Token::kSUB: |
| 4706 __ vsubw(result, left, right); | 4518 __ vsubw(result, left, right); |
| 4707 break; | 4519 break; |
| 4708 default: | 4520 default: |
| 4709 UNREACHABLE(); | 4521 UNREACHABLE(); |
| 4710 } | 4522 } |
| 4711 } | 4523 } |
| 4712 | 4524 |
| 4713 | |
| 4714 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 4525 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |
| 4715 bool opt) const { | 4526 bool opt) const { |
| 4716 ASSERT((kind() == MathUnaryInstr::kSqrt) || | 4527 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
| 4717 (kind() == MathUnaryInstr::kDoubleSquare)); | 4528 (kind() == MathUnaryInstr::kDoubleSquare)); |
| 4718 const intptr_t kNumInputs = 1; | 4529 const intptr_t kNumInputs = 1; |
| 4719 const intptr_t kNumTemps = 0; | 4530 const intptr_t kNumTemps = 0; |
| 4720 LocationSummary* summary = new (zone) | 4531 LocationSummary* summary = new (zone) |
| 4721 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4532 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4722 summary->set_in(0, Location::RequiresFpuRegister()); | 4533 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4723 summary->set_out(0, Location::RequiresFpuRegister()); | 4534 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4724 return summary; | 4535 return summary; |
| 4725 } | 4536 } |
| 4726 | 4537 |
| 4727 | |
| 4728 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4538 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4729 if (kind() == MathUnaryInstr::kSqrt) { | 4539 if (kind() == MathUnaryInstr::kSqrt) { |
| 4730 const VRegister val = locs()->in(0).fpu_reg(); | 4540 const VRegister val = locs()->in(0).fpu_reg(); |
| 4731 const VRegister result = locs()->out(0).fpu_reg(); | 4541 const VRegister result = locs()->out(0).fpu_reg(); |
| 4732 __ fsqrtd(result, val); | 4542 __ fsqrtd(result, val); |
| 4733 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 4543 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
| 4734 const VRegister val = locs()->in(0).fpu_reg(); | 4544 const VRegister val = locs()->in(0).fpu_reg(); |
| 4735 const VRegister result = locs()->out(0).fpu_reg(); | 4545 const VRegister result = locs()->out(0).fpu_reg(); |
| 4736 __ fmuld(result, val, val); | 4546 __ fmuld(result, val, val); |
| 4737 } else { | 4547 } else { |
| 4738 UNREACHABLE(); | 4548 UNREACHABLE(); |
| 4739 } | 4549 } |
| 4740 } | 4550 } |
| 4741 | 4551 |
| 4742 | |
| 4743 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 4552 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |
| 4744 Zone* zone, | 4553 Zone* zone, |
| 4745 bool opt) const { | 4554 bool opt) const { |
| 4746 const intptr_t kNumTemps = 0; | 4555 const intptr_t kNumTemps = 0; |
| 4747 LocationSummary* summary = new (zone) | 4556 LocationSummary* summary = new (zone) |
| 4748 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); | 4557 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 4749 summary->set_in(0, Location::RegisterLocation(R0)); | 4558 summary->set_in(0, Location::RegisterLocation(R0)); |
| 4750 summary->set_in(1, Location::RegisterLocation(R1)); | 4559 summary->set_in(1, Location::RegisterLocation(R1)); |
| 4751 summary->set_in(2, Location::RegisterLocation(R2)); | 4560 summary->set_in(2, Location::RegisterLocation(R2)); |
| 4752 summary->set_in(3, Location::RegisterLocation(R3)); | 4561 summary->set_in(3, Location::RegisterLocation(R3)); |
| 4753 summary->set_out(0, Location::RegisterLocation(R0)); | 4562 summary->set_out(0, Location::RegisterLocation(R0)); |
| 4754 return summary; | 4563 return summary; |
| 4755 } | 4564 } |
| 4756 | 4565 |
| 4757 | |
| 4758 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 4566 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |
| 4759 FlowGraphCompiler* compiler) { | 4567 FlowGraphCompiler* compiler) { |
| 4760 // Call the function. | 4568 // Call the function. |
| 4761 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 4569 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |
| 4762 } | 4570 } |
| 4763 | 4571 |
| 4764 | |
| 4765 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 4572 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |
| 4766 bool opt) const { | 4573 bool opt) const { |
| 4767 if (result_cid() == kDoubleCid) { | 4574 if (result_cid() == kDoubleCid) { |
| 4768 const intptr_t kNumInputs = 2; | 4575 const intptr_t kNumInputs = 2; |
| 4769 const intptr_t kNumTemps = 0; | 4576 const intptr_t kNumTemps = 0; |
| 4770 LocationSummary* summary = new (zone) | 4577 LocationSummary* summary = new (zone) |
| 4771 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4578 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4772 summary->set_in(0, Location::RequiresFpuRegister()); | 4579 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4773 summary->set_in(1, Location::RequiresFpuRegister()); | 4580 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4774 // Reuse the left register so that code can be made shorter. | 4581 // Reuse the left register so that code can be made shorter. |
| 4775 summary->set_out(0, Location::SameAsFirstInput()); | 4582 summary->set_out(0, Location::SameAsFirstInput()); |
| 4776 return summary; | 4583 return summary; |
| 4777 } | 4584 } |
| 4778 ASSERT(result_cid() == kSmiCid); | 4585 ASSERT(result_cid() == kSmiCid); |
| 4779 const intptr_t kNumInputs = 2; | 4586 const intptr_t kNumInputs = 2; |
| 4780 const intptr_t kNumTemps = 0; | 4587 const intptr_t kNumTemps = 0; |
| 4781 LocationSummary* summary = new (zone) | 4588 LocationSummary* summary = new (zone) |
| 4782 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4589 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4783 summary->set_in(0, Location::RequiresRegister()); | 4590 summary->set_in(0, Location::RequiresRegister()); |
| 4784 summary->set_in(1, Location::RequiresRegister()); | 4591 summary->set_in(1, Location::RequiresRegister()); |
| 4785 // Reuse the left register so that code can be made shorter. | 4592 // Reuse the left register so that code can be made shorter. |
| 4786 summary->set_out(0, Location::SameAsFirstInput()); | 4593 summary->set_out(0, Location::SameAsFirstInput()); |
| 4787 return summary; | 4594 return summary; |
| 4788 } | 4595 } |
| 4789 | 4596 |
| 4790 | |
| 4791 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4597 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4792 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 4598 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
| 4793 (op_kind() == MethodRecognizer::kMathMax)); | 4599 (op_kind() == MethodRecognizer::kMathMax)); |
| 4794 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); | 4600 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); |
| 4795 if (result_cid() == kDoubleCid) { | 4601 if (result_cid() == kDoubleCid) { |
| 4796 Label done, returns_nan, are_equal; | 4602 Label done, returns_nan, are_equal; |
| 4797 const VRegister left = locs()->in(0).fpu_reg(); | 4603 const VRegister left = locs()->in(0).fpu_reg(); |
| 4798 const VRegister right = locs()->in(1).fpu_reg(); | 4604 const VRegister right = locs()->in(1).fpu_reg(); |
| 4799 const VRegister result = locs()->out(0).fpu_reg(); | 4605 const VRegister result = locs()->out(0).fpu_reg(); |
| 4800 __ fcmpd(left, right); | 4606 __ fcmpd(left, right); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4840 const Register result = locs()->out(0).reg(); | 4646 const Register result = locs()->out(0).reg(); |
| 4841 __ CompareRegisters(left, right); | 4647 __ CompareRegisters(left, right); |
| 4842 ASSERT(result == left); | 4648 ASSERT(result == left); |
| 4843 if (is_min) { | 4649 if (is_min) { |
| 4844 __ csel(result, right, left, GT); | 4650 __ csel(result, right, left, GT); |
| 4845 } else { | 4651 } else { |
| 4846 __ csel(result, right, left, LT); | 4652 __ csel(result, right, left, LT); |
| 4847 } | 4653 } |
| 4848 } | 4654 } |
| 4849 | 4655 |
| 4850 | |
| 4851 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 4656 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 4852 bool opt) const { | 4657 bool opt) const { |
| 4853 const intptr_t kNumInputs = 1; | 4658 const intptr_t kNumInputs = 1; |
| 4854 const intptr_t kNumTemps = 0; | 4659 const intptr_t kNumTemps = 0; |
| 4855 LocationSummary* summary = new (zone) | 4660 LocationSummary* summary = new (zone) |
| 4856 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4661 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4857 summary->set_in(0, Location::RequiresRegister()); | 4662 summary->set_in(0, Location::RequiresRegister()); |
| 4858 // We make use of 3-operand instructions by not requiring result register | 4663 // We make use of 3-operand instructions by not requiring result register |
| 4859 // to be identical to first input register as on Intel. | 4664 // to be identical to first input register as on Intel. |
| 4860 summary->set_out(0, Location::RequiresRegister()); | 4665 summary->set_out(0, Location::RequiresRegister()); |
| 4861 return summary; | 4666 return summary; |
| 4862 } | 4667 } |
| 4863 | 4668 |
| 4864 | |
| 4865 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4669 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4866 const Register value = locs()->in(0).reg(); | 4670 const Register value = locs()->in(0).reg(); |
| 4867 const Register result = locs()->out(0).reg(); | 4671 const Register result = locs()->out(0).reg(); |
| 4868 switch (op_kind()) { | 4672 switch (op_kind()) { |
| 4869 case Token::kNEGATE: { | 4673 case Token::kNEGATE: { |
| 4870 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); | 4674 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); |
| 4871 __ subs(result, ZR, Operand(value)); | 4675 __ subs(result, ZR, Operand(value)); |
| 4872 __ b(deopt, VS); | 4676 __ b(deopt, VS); |
| 4873 break; | 4677 break; |
| 4874 } | 4678 } |
| 4875 case Token::kBIT_NOT: | 4679 case Token::kBIT_NOT: |
| 4876 __ mvn(result, value); | 4680 __ mvn(result, value); |
| 4877 // Remove inverted smi-tag. | 4681 // Remove inverted smi-tag. |
| 4878 __ andi(result, result, Immediate(~kSmiTagMask)); | 4682 __ andi(result, result, Immediate(~kSmiTagMask)); |
| 4879 break; | 4683 break; |
| 4880 default: | 4684 default: |
| 4881 UNREACHABLE(); | 4685 UNREACHABLE(); |
| 4882 } | 4686 } |
| 4883 } | 4687 } |
| 4884 | 4688 |
| 4885 | |
| 4886 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 4689 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 4887 bool opt) const { | 4690 bool opt) const { |
| 4888 const intptr_t kNumInputs = 1; | 4691 const intptr_t kNumInputs = 1; |
| 4889 const intptr_t kNumTemps = 0; | 4692 const intptr_t kNumTemps = 0; |
| 4890 LocationSummary* summary = new (zone) | 4693 LocationSummary* summary = new (zone) |
| 4891 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4694 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4892 summary->set_in(0, Location::RequiresFpuRegister()); | 4695 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4893 summary->set_out(0, Location::RequiresFpuRegister()); | 4696 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4894 return summary; | 4697 return summary; |
| 4895 } | 4698 } |
| 4896 | 4699 |
| 4897 | |
| 4898 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4700 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4899 const VRegister result = locs()->out(0).fpu_reg(); | 4701 const VRegister result = locs()->out(0).fpu_reg(); |
| 4900 const VRegister value = locs()->in(0).fpu_reg(); | 4702 const VRegister value = locs()->in(0).fpu_reg(); |
| 4901 __ fnegd(result, value); | 4703 __ fnegd(result, value); |
| 4902 } | 4704 } |
| 4903 | 4705 |
| 4904 | |
| 4905 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 4706 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 4906 bool opt) const { | 4707 bool opt) const { |
| 4907 const intptr_t kNumInputs = 1; | 4708 const intptr_t kNumInputs = 1; |
| 4908 const intptr_t kNumTemps = 0; | 4709 const intptr_t kNumTemps = 0; |
| 4909 LocationSummary* result = new (zone) | 4710 LocationSummary* result = new (zone) |
| 4910 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4711 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4911 result->set_in(0, Location::RequiresRegister()); | 4712 result->set_in(0, Location::RequiresRegister()); |
| 4912 result->set_out(0, Location::RequiresFpuRegister()); | 4713 result->set_out(0, Location::RequiresFpuRegister()); |
| 4913 return result; | 4714 return result; |
| 4914 } | 4715 } |
| 4915 | 4716 |
| 4916 | |
| 4917 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4717 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4918 const Register value = locs()->in(0).reg(); | 4718 const Register value = locs()->in(0).reg(); |
| 4919 const VRegister result = locs()->out(0).fpu_reg(); | 4719 const VRegister result = locs()->out(0).fpu_reg(); |
| 4920 __ scvtfdw(result, value); | 4720 __ scvtfdw(result, value); |
| 4921 } | 4721 } |
| 4922 | 4722 |
| 4923 | |
| 4924 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 4723 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 4925 bool opt) const { | 4724 bool opt) const { |
| 4926 const intptr_t kNumInputs = 1; | 4725 const intptr_t kNumInputs = 1; |
| 4927 const intptr_t kNumTemps = 0; | 4726 const intptr_t kNumTemps = 0; |
| 4928 LocationSummary* result = new (zone) | 4727 LocationSummary* result = new (zone) |
| 4929 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4728 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4930 result->set_in(0, Location::RequiresRegister()); | 4729 result->set_in(0, Location::RequiresRegister()); |
| 4931 result->set_out(0, Location::RequiresFpuRegister()); | 4730 result->set_out(0, Location::RequiresFpuRegister()); |
| 4932 return result; | 4731 return result; |
| 4933 } | 4732 } |
| 4934 | 4733 |
| 4935 | |
| 4936 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4734 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4937 const Register value = locs()->in(0).reg(); | 4735 const Register value = locs()->in(0).reg(); |
| 4938 const VRegister result = locs()->out(0).fpu_reg(); | 4736 const VRegister result = locs()->out(0).fpu_reg(); |
| 4939 __ SmiUntag(TMP, value); | 4737 __ SmiUntag(TMP, value); |
| 4940 __ scvtfdx(result, TMP); | 4738 __ scvtfdx(result, TMP); |
| 4941 } | 4739 } |
| 4942 | 4740 |
| 4943 | |
| 4944 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone, | 4741 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 4945 bool opt) const { | 4742 bool opt) const { |
| 4946 UNIMPLEMENTED(); | 4743 UNIMPLEMENTED(); |
| 4947 return NULL; | 4744 return NULL; |
| 4948 } | 4745 } |
| 4949 | 4746 |
| 4950 | |
| 4951 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4747 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4952 UNIMPLEMENTED(); | 4748 UNIMPLEMENTED(); |
| 4953 } | 4749 } |
| 4954 | 4750 |
| 4955 | |
| 4956 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 4751 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |
| 4957 bool opt) const { | 4752 bool opt) const { |
| 4958 const intptr_t kNumInputs = 1; | 4753 const intptr_t kNumInputs = 1; |
| 4959 const intptr_t kNumTemps = 0; | 4754 const intptr_t kNumTemps = 0; |
| 4960 LocationSummary* result = new (zone) | 4755 LocationSummary* result = new (zone) |
| 4961 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 4756 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 4962 result->set_in(0, Location::RegisterLocation(R1)); | 4757 result->set_in(0, Location::RegisterLocation(R1)); |
| 4963 result->set_out(0, Location::RegisterLocation(R0)); | 4758 result->set_out(0, Location::RegisterLocation(R0)); |
| 4964 return result; | 4759 return result; |
| 4965 } | 4760 } |
| 4966 | 4761 |
| 4967 | |
| 4968 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4762 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4969 const Register result = locs()->out(0).reg(); | 4763 const Register result = locs()->out(0).reg(); |
| 4970 const Register value_obj = locs()->in(0).reg(); | 4764 const Register value_obj = locs()->in(0).reg(); |
| 4971 ASSERT(result == R0); | 4765 ASSERT(result == R0); |
| 4972 ASSERT(result != value_obj); | 4766 ASSERT(result != value_obj); |
| 4973 __ LoadDFieldFromOffset(VTMP, value_obj, Double::value_offset()); | 4767 __ LoadDFieldFromOffset(VTMP, value_obj, Double::value_offset()); |
| 4974 | 4768 |
| 4975 Label do_call, done; | 4769 Label do_call, done; |
| 4976 // First check for NaN. Checking for minint after the conversion doesn't work | 4770 // First check for NaN. Checking for minint after the conversion doesn't work |
| 4977 // on ARM64 because fcvtzds gives 0 for NaN. | 4771 // on ARM64 because fcvtzds gives 0 for NaN. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 4994 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 4788 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
| 4995 const int kTypeArgsLen = 0; | 4789 const int kTypeArgsLen = 0; |
| 4996 const int kNumberOfArguments = 1; | 4790 const int kNumberOfArguments = 1; |
| 4997 const Array& kNoArgumentNames = Object::null_array(); | 4791 const Array& kNoArgumentNames = Object::null_array(); |
| 4998 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); | 4792 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); |
| 4999 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, | 4793 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, |
| 5000 args_info, locs(), ICData::Handle()); | 4794 args_info, locs(), ICData::Handle()); |
| 5001 __ Bind(&done); | 4795 __ Bind(&done); |
| 5002 } | 4796 } |
| 5003 | 4797 |
| 5004 | |
| 5005 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 4798 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |
| 5006 bool opt) const { | 4799 bool opt) const { |
| 5007 const intptr_t kNumInputs = 1; | 4800 const intptr_t kNumInputs = 1; |
| 5008 const intptr_t kNumTemps = 0; | 4801 const intptr_t kNumTemps = 0; |
| 5009 LocationSummary* result = new (zone) | 4802 LocationSummary* result = new (zone) |
| 5010 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4803 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5011 result->set_in(0, Location::RequiresFpuRegister()); | 4804 result->set_in(0, Location::RequiresFpuRegister()); |
| 5012 result->set_out(0, Location::RequiresRegister()); | 4805 result->set_out(0, Location::RequiresRegister()); |
| 5013 return result; | 4806 return result; |
| 5014 } | 4807 } |
| 5015 | 4808 |
| 5016 | |
| 5017 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4809 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5018 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 4810 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
| 5019 const Register result = locs()->out(0).reg(); | 4811 const Register result = locs()->out(0).reg(); |
| 5020 const VRegister value = locs()->in(0).fpu_reg(); | 4812 const VRegister value = locs()->in(0).fpu_reg(); |
| 5021 // First check for NaN. Checking for minint after the conversion doesn't work | 4813 // First check for NaN. Checking for minint after the conversion doesn't work |
| 5022 // on ARM64 because fcvtzds gives 0 for NaN. | 4814 // on ARM64 because fcvtzds gives 0 for NaN. |
| 5023 // TODO(zra): Check spec that this is true. | 4815 // TODO(zra): Check spec that this is true. |
| 5024 __ fcmpd(value, value); | 4816 __ fcmpd(value, value); |
| 5025 __ b(deopt, VS); | 4817 __ b(deopt, VS); |
| 5026 | 4818 |
| 5027 __ fcvtzds(result, value); | 4819 __ fcvtzds(result, value); |
| 5028 // Check for overflow and that it fits into Smi. | 4820 // Check for overflow and that it fits into Smi. |
| 5029 __ CompareImmediate(result, 0xC000000000000000); | 4821 __ CompareImmediate(result, 0xC000000000000000); |
| 5030 __ b(deopt, MI); | 4822 __ b(deopt, MI); |
| 5031 __ SmiTag(result); | 4823 __ SmiTag(result); |
| 5032 } | 4824 } |
| 5033 | 4825 |
| 5034 | |
| 5035 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, | 4826 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5036 bool opt) const { | 4827 bool opt) const { |
| 5037 UNIMPLEMENTED(); | 4828 UNIMPLEMENTED(); |
| 5038 return NULL; | 4829 return NULL; |
| 5039 } | 4830 } |
| 5040 | 4831 |
| 5041 | |
| 5042 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4832 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5043 UNIMPLEMENTED(); | 4833 UNIMPLEMENTED(); |
| 5044 } | 4834 } |
| 5045 | 4835 |
| 5046 | |
| 5047 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 4836 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |
| 5048 bool opt) const { | 4837 bool opt) const { |
| 5049 const intptr_t kNumInputs = 1; | 4838 const intptr_t kNumInputs = 1; |
| 5050 const intptr_t kNumTemps = 0; | 4839 const intptr_t kNumTemps = 0; |
| 5051 LocationSummary* result = new (zone) | 4840 LocationSummary* result = new (zone) |
| 5052 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4841 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5053 result->set_in(0, Location::RequiresFpuRegister()); | 4842 result->set_in(0, Location::RequiresFpuRegister()); |
| 5054 result->set_out(0, Location::RequiresFpuRegister()); | 4843 result->set_out(0, Location::RequiresFpuRegister()); |
| 5055 return result; | 4844 return result; |
| 5056 } | 4845 } |
| 5057 | 4846 |
| 5058 | |
| 5059 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4847 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5060 const VRegister value = locs()->in(0).fpu_reg(); | 4848 const VRegister value = locs()->in(0).fpu_reg(); |
| 5061 const VRegister result = locs()->out(0).fpu_reg(); | 4849 const VRegister result = locs()->out(0).fpu_reg(); |
| 5062 __ fcvtsd(result, value); | 4850 __ fcvtsd(result, value); |
| 5063 } | 4851 } |
| 5064 | 4852 |
| 5065 | |
| 5066 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 4853 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5067 bool opt) const { | 4854 bool opt) const { |
| 5068 const intptr_t kNumInputs = 1; | 4855 const intptr_t kNumInputs = 1; |
| 5069 const intptr_t kNumTemps = 0; | 4856 const intptr_t kNumTemps = 0; |
| 5070 LocationSummary* result = new (zone) | 4857 LocationSummary* result = new (zone) |
| 5071 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4858 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5072 result->set_in(0, Location::RequiresFpuRegister()); | 4859 result->set_in(0, Location::RequiresFpuRegister()); |
| 5073 result->set_out(0, Location::RequiresFpuRegister()); | 4860 result->set_out(0, Location::RequiresFpuRegister()); |
| 5074 return result; | 4861 return result; |
| 5075 } | 4862 } |
| 5076 | 4863 |
| 5077 | |
| 5078 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4864 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5079 const VRegister value = locs()->in(0).fpu_reg(); | 4865 const VRegister value = locs()->in(0).fpu_reg(); |
| 5080 const VRegister result = locs()->out(0).fpu_reg(); | 4866 const VRegister result = locs()->out(0).fpu_reg(); |
| 5081 __ fcvtds(result, value); | 4867 __ fcvtds(result, value); |
| 5082 } | 4868 } |
| 5083 | 4869 |
| 5084 | |
| 5085 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 4870 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |
| 5086 bool opt) const { | 4871 bool opt) const { |
| 5087 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 4872 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
| 5088 const intptr_t kNumTemps = | 4873 const intptr_t kNumTemps = |
| 5089 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0; | 4874 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0; |
| 5090 LocationSummary* result = new (zone) | 4875 LocationSummary* result = new (zone) |
| 5091 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); | 4876 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 5092 result->set_in(0, Location::FpuRegisterLocation(V0)); | 4877 result->set_in(0, Location::FpuRegisterLocation(V0)); |
| 5093 if (InputCount() == 2) { | 4878 if (InputCount() == 2) { |
| 5094 result->set_in(1, Location::FpuRegisterLocation(V1)); | 4879 result->set_in(1, Location::FpuRegisterLocation(V1)); |
| 5095 } | 4880 } |
| 5096 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 4881 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 5097 result->set_temp(0, Location::FpuRegisterLocation(V30)); | 4882 result->set_temp(0, Location::FpuRegisterLocation(V30)); |
| 5098 } | 4883 } |
| 5099 result->set_out(0, Location::FpuRegisterLocation(V0)); | 4884 result->set_out(0, Location::FpuRegisterLocation(V0)); |
| 5100 return result; | 4885 return result; |
| 5101 } | 4886 } |
| 5102 | 4887 |
| 5103 | |
| 5104 // Pseudo code: | 4888 // Pseudo code: |
| 5105 // if (exponent == 0.0) return 1.0; | 4889 // if (exponent == 0.0) return 1.0; |
| 5106 // // Speed up simple cases. | 4890 // // Speed up simple cases. |
| 5107 // if (exponent == 1.0) return base; | 4891 // if (exponent == 1.0) return base; |
| 5108 // if (exponent == 2.0) return base * base; | 4892 // if (exponent == 2.0) return base * base; |
| 5109 // if (exponent == 3.0) return base * base * base; | 4893 // if (exponent == 3.0) return base * base * base; |
| 5110 // if (base == 1.0) return 1.0; | 4894 // if (base == 1.0) return 1.0; |
| 5111 // if (base.isNaN || exponent.isNaN) { | 4895 // if (base.isNaN || exponent.isNaN) { |
| 5112 // return double.NAN; | 4896 // return double.NAN; |
| 5113 // } | 4897 // } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5206 __ LoadDImmediate(result, 0.0); | 4990 __ LoadDImmediate(result, 0.0); |
| 5207 __ b(&skip_call); | 4991 __ b(&skip_call); |
| 5208 | 4992 |
| 5209 __ Bind(&do_pow); | 4993 __ Bind(&do_pow); |
| 5210 __ fmovdd(base, saved_base); // Restore base. | 4994 __ fmovdd(base, saved_base); // Restore base. |
| 5211 | 4995 |
| 5212 __ CallRuntime(instr->TargetFunction(), kInputCount); | 4996 __ CallRuntime(instr->TargetFunction(), kInputCount); |
| 5213 __ Bind(&skip_call); | 4997 __ Bind(&skip_call); |
| 5214 } | 4998 } |
| 5215 | 4999 |
| 5216 | |
| 5217 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5000 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5218 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5001 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 5219 InvokeDoublePow(compiler, this); | 5002 InvokeDoublePow(compiler, this); |
| 5220 return; | 5003 return; |
| 5221 } | 5004 } |
| 5222 __ CallRuntime(TargetFunction(), InputCount()); | 5005 __ CallRuntime(TargetFunction(), InputCount()); |
| 5223 } | 5006 } |
| 5224 | 5007 |
| 5225 | |
| 5226 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 5008 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |
| 5227 bool opt) const { | 5009 bool opt) const { |
| 5228 // Only use this instruction in optimized code. | 5010 // Only use this instruction in optimized code. |
| 5229 ASSERT(opt); | 5011 ASSERT(opt); |
| 5230 const intptr_t kNumInputs = 1; | 5012 const intptr_t kNumInputs = 1; |
| 5231 LocationSummary* summary = | 5013 LocationSummary* summary = |
| 5232 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); | 5014 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 5233 if (representation() == kUnboxedDouble) { | 5015 if (representation() == kUnboxedDouble) { |
| 5234 if (index() == 0) { | 5016 if (index() == 0) { |
| 5235 summary->set_in( | 5017 summary->set_in( |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5248 } else { | 5030 } else { |
| 5249 ASSERT(index() == 1); | 5031 ASSERT(index() == 1); |
| 5250 summary->set_in( | 5032 summary->set_in( |
| 5251 0, Location::Pair(Location::Any(), Location::RequiresRegister())); | 5033 0, Location::Pair(Location::Any(), Location::RequiresRegister())); |
| 5252 } | 5034 } |
| 5253 summary->set_out(0, Location::RequiresRegister()); | 5035 summary->set_out(0, Location::RequiresRegister()); |
| 5254 } | 5036 } |
| 5255 return summary; | 5037 return summary; |
| 5256 } | 5038 } |
| 5257 | 5039 |
| 5258 | |
| 5259 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5040 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5260 ASSERT(locs()->in(0).IsPairLocation()); | 5041 ASSERT(locs()->in(0).IsPairLocation()); |
| 5261 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5042 PairLocation* pair = locs()->in(0).AsPairLocation(); |
| 5262 Location in_loc = pair->At(index()); | 5043 Location in_loc = pair->At(index()); |
| 5263 if (representation() == kUnboxedDouble) { | 5044 if (representation() == kUnboxedDouble) { |
| 5264 const VRegister out = locs()->out(0).fpu_reg(); | 5045 const VRegister out = locs()->out(0).fpu_reg(); |
| 5265 const VRegister in = in_loc.fpu_reg(); | 5046 const VRegister in = in_loc.fpu_reg(); |
| 5266 __ fmovdd(out, in); | 5047 __ fmovdd(out, in); |
| 5267 } else { | 5048 } else { |
| 5268 ASSERT(representation() == kTagged); | 5049 ASSERT(representation() == kTagged); |
| 5269 const Register out = locs()->out(0).reg(); | 5050 const Register out = locs()->out(0).reg(); |
| 5270 const Register in = in_loc.reg(); | 5051 const Register in = in_loc.reg(); |
| 5271 __ mov(out, in); | 5052 __ mov(out, in); |
| 5272 } | 5053 } |
| 5273 } | 5054 } |
| 5274 | 5055 |
| 5275 | |
| 5276 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone, | 5056 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone, |
| 5277 bool opt) const { | 5057 bool opt) const { |
| 5278 const intptr_t kNumInputs = 2; | 5058 const intptr_t kNumInputs = 2; |
| 5279 const intptr_t kNumTemps = 0; | 5059 const intptr_t kNumTemps = 0; |
| 5280 LocationSummary* summary = new (zone) | 5060 LocationSummary* summary = new (zone) |
| 5281 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5061 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5282 summary->set_in(0, Location::RequiresRegister()); | 5062 summary->set_in(0, Location::RequiresRegister()); |
| 5283 summary->set_in(1, Location::RequiresRegister()); | 5063 summary->set_in(1, Location::RequiresRegister()); |
| 5284 // Output is a pair of registers. | 5064 // Output is a pair of registers. |
| 5285 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 5065 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 5286 Location::RequiresRegister())); | 5066 Location::RequiresRegister())); |
| 5287 return summary; | 5067 return summary; |
| 5288 } | 5068 } |
| 5289 | 5069 |
| 5290 | |
| 5291 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5070 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5292 ASSERT(CanDeoptimize()); | 5071 ASSERT(CanDeoptimize()); |
| 5293 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 5072 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
| 5294 const Register left = locs()->in(0).reg(); | 5073 const Register left = locs()->in(0).reg(); |
| 5295 const Register right = locs()->in(1).reg(); | 5074 const Register right = locs()->in(1).reg(); |
| 5296 ASSERT(locs()->out(0).IsPairLocation()); | 5075 ASSERT(locs()->out(0).IsPairLocation()); |
| 5297 const PairLocation* pair = locs()->out(0).AsPairLocation(); | 5076 const PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 5298 const Register result_div = pair->At(0).reg(); | 5077 const Register result_div = pair->At(0).reg(); |
| 5299 const Register result_mod = pair->At(1).reg(); | 5078 const Register result_mod = pair->At(1).reg(); |
| 5300 if (RangeUtils::CanBeZero(divisor_range())) { | 5079 if (RangeUtils::CanBeZero(divisor_range())) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 5329 __ CompareRegisters(result_mod, ZR); | 5108 __ CompareRegisters(result_mod, ZR); |
| 5330 __ b(&done, GE); | 5109 __ b(&done, GE); |
| 5331 // Result is negative, adjust it. | 5110 // Result is negative, adjust it. |
| 5332 __ CompareRegisters(right, ZR); | 5111 __ CompareRegisters(right, ZR); |
| 5333 __ sub(TMP2, result_mod, Operand(right)); | 5112 __ sub(TMP2, result_mod, Operand(right)); |
| 5334 __ add(TMP, result_mod, Operand(right)); | 5113 __ add(TMP, result_mod, Operand(right)); |
| 5335 __ csel(result_mod, TMP, TMP2, GE); | 5114 __ csel(result_mod, TMP, TMP2, GE); |
| 5336 __ Bind(&done); | 5115 __ Bind(&done); |
| 5337 } | 5116 } |
| 5338 | 5117 |
| 5339 | |
| 5340 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 5118 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
| 5341 Zone* zone, | 5119 Zone* zone, |
| 5342 bool opt) const { | 5120 bool opt) const { |
| 5343 return MakeCallSummary(zone); | 5121 return MakeCallSummary(zone); |
| 5344 } | 5122 } |
| 5345 | 5123 |
| 5346 | |
| 5347 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 5124 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5348 comparison()->InitializeLocationSummary(zone, opt); | 5125 comparison()->InitializeLocationSummary(zone, opt); |
| 5349 // Branches don't produce a result. | 5126 // Branches don't produce a result. |
| 5350 comparison()->locs()->set_out(0, Location::NoLocation()); | 5127 comparison()->locs()->set_out(0, Location::NoLocation()); |
| 5351 return comparison()->locs(); | 5128 return comparison()->locs(); |
| 5352 } | 5129 } |
| 5353 | 5130 |
| 5354 | |
| 5355 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5131 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5356 comparison()->EmitBranchCode(compiler, this); | 5132 comparison()->EmitBranchCode(compiler, this); |
| 5357 } | 5133 } |
| 5358 | 5134 |
| 5359 | |
| 5360 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 5135 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
| 5361 bool opt) const { | 5136 bool opt) const { |
| 5362 const intptr_t kNumInputs = 1; | 5137 const intptr_t kNumInputs = 1; |
| 5363 const bool need_mask_temp = IsBitTest(); | 5138 const bool need_mask_temp = IsBitTest(); |
| 5364 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 5139 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
| 5365 LocationSummary* summary = new (zone) | 5140 LocationSummary* summary = new (zone) |
| 5366 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5141 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5367 summary->set_in(0, Location::RequiresRegister()); | 5142 summary->set_in(0, Location::RequiresRegister()); |
| 5368 if (!IsNullCheck()) { | 5143 if (!IsNullCheck()) { |
| 5369 summary->set_temp(0, Location::RequiresRegister()); | 5144 summary->set_temp(0, Location::RequiresRegister()); |
| 5370 if (need_mask_temp) { | 5145 if (need_mask_temp) { |
| 5371 summary->set_temp(1, Location::RequiresRegister()); | 5146 summary->set_temp(1, Location::RequiresRegister()); |
| 5372 } | 5147 } |
| 5373 } | 5148 } |
| 5374 return summary; | 5149 return summary; |
| 5375 } | 5150 } |
| 5376 | 5151 |
| 5377 | |
| 5378 void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) { | 5152 void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) { |
| 5379 __ CompareObject(locs()->in(0).reg(), Object::null_object()); | 5153 __ CompareObject(locs()->in(0).reg(), Object::null_object()); |
| 5380 ASSERT(IsDeoptIfNull() || IsDeoptIfNotNull()); | 5154 ASSERT(IsDeoptIfNull() || IsDeoptIfNotNull()); |
| 5381 Condition cond = IsDeoptIfNull() ? EQ : NE; | 5155 Condition cond = IsDeoptIfNull() ? EQ : NE; |
| 5382 __ b(deopt, cond); | 5156 __ b(deopt, cond); |
| 5383 } | 5157 } |
| 5384 | 5158 |
| 5385 | |
| 5386 void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler, | 5159 void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler, |
| 5387 intptr_t min, | 5160 intptr_t min, |
| 5388 intptr_t max, | 5161 intptr_t max, |
| 5389 intptr_t mask, | 5162 intptr_t mask, |
| 5390 Label* deopt) { | 5163 Label* deopt) { |
| 5391 Register biased_cid = locs()->temp(0).reg(); | 5164 Register biased_cid = locs()->temp(0).reg(); |
| 5392 __ AddImmediate(biased_cid, -min); | 5165 __ AddImmediate(biased_cid, -min); |
| 5393 __ CompareImmediate(biased_cid, max - min); | 5166 __ CompareImmediate(biased_cid, max - min); |
| 5394 __ b(deopt, HI); | 5167 __ b(deopt, HI); |
| 5395 | 5168 |
| 5396 Register bit_reg = locs()->temp(1).reg(); | 5169 Register bit_reg = locs()->temp(1).reg(); |
| 5397 __ LoadImmediate(bit_reg, 1); | 5170 __ LoadImmediate(bit_reg, 1); |
| 5398 __ lslv(bit_reg, bit_reg, biased_cid); | 5171 __ lslv(bit_reg, bit_reg, biased_cid); |
| 5399 __ TestImmediate(bit_reg, mask); | 5172 __ TestImmediate(bit_reg, mask); |
| 5400 __ b(deopt, EQ); | 5173 __ b(deopt, EQ); |
| 5401 } | 5174 } |
| 5402 | 5175 |
| 5403 | |
| 5404 int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler, | 5176 int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler, |
| 5405 int bias, | 5177 int bias, |
| 5406 intptr_t cid_start, | 5178 intptr_t cid_start, |
| 5407 intptr_t cid_end, | 5179 intptr_t cid_end, |
| 5408 bool is_last, | 5180 bool is_last, |
| 5409 Label* is_ok, | 5181 Label* is_ok, |
| 5410 Label* deopt, | 5182 Label* deopt, |
| 5411 bool use_near_jump) { | 5183 bool use_near_jump) { |
| 5412 Register biased_cid = locs()->temp(0).reg(); | 5184 Register biased_cid = locs()->temp(0).reg(); |
| 5413 Condition no_match, match; | 5185 Condition no_match, match; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5425 match = LS; // Unsigned lower or same. | 5197 match = LS; // Unsigned lower or same. |
| 5426 } | 5198 } |
| 5427 if (is_last) { | 5199 if (is_last) { |
| 5428 __ b(deopt, no_match); | 5200 __ b(deopt, no_match); |
| 5429 } else { | 5201 } else { |
| 5430 __ b(is_ok, match); | 5202 __ b(is_ok, match); |
| 5431 } | 5203 } |
| 5432 return bias; | 5204 return bias; |
| 5433 } | 5205 } |
| 5434 | 5206 |
| 5435 | |
| 5436 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 5207 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
| 5437 bool opt) const { | 5208 bool opt) const { |
| 5438 const intptr_t kNumInputs = 1; | 5209 const intptr_t kNumInputs = 1; |
| 5439 const intptr_t kNumTemps = 0; | 5210 const intptr_t kNumTemps = 0; |
| 5440 LocationSummary* summary = new (zone) | 5211 LocationSummary* summary = new (zone) |
| 5441 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5212 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5442 summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister() | 5213 summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister() |
| 5443 : Location::WritableRegister()); | 5214 : Location::WritableRegister()); |
| 5444 return summary; | 5215 return summary; |
| 5445 } | 5216 } |
| 5446 | 5217 |
| 5447 | |
| 5448 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5218 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5449 Register value = locs()->in(0).reg(); | 5219 Register value = locs()->in(0).reg(); |
| 5450 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 5220 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
| 5451 if (cids_.IsSingleCid()) { | 5221 if (cids_.IsSingleCid()) { |
| 5452 __ CompareImmediate(value, Smi::RawValue(cids_.cid_start)); | 5222 __ CompareImmediate(value, Smi::RawValue(cids_.cid_start)); |
| 5453 __ b(deopt, NE); | 5223 __ b(deopt, NE); |
| 5454 } else { | 5224 } else { |
| 5455 __ AddImmediate(value, -Smi::RawValue(cids_.cid_start)); | 5225 __ AddImmediate(value, -Smi::RawValue(cids_.cid_start)); |
| 5456 __ CompareImmediate(value, Smi::RawValue(cids_.cid_end - cids_.cid_start)); | 5226 __ CompareImmediate(value, Smi::RawValue(cids_.cid_end - cids_.cid_start)); |
| 5457 __ b(deopt, HI); // Unsigned higher. | 5227 __ b(deopt, HI); // Unsigned higher. |
| 5458 } | 5228 } |
| 5459 } | 5229 } |
| 5460 | 5230 |
| 5461 | |
| 5462 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 5231 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
| 5463 bool opt) const { | 5232 bool opt) const { |
| 5464 const intptr_t kNumInputs = 1; | 5233 const intptr_t kNumInputs = 1; |
| 5465 const intptr_t kNumTemps = 0; | 5234 const intptr_t kNumTemps = 0; |
| 5466 LocationSummary* summary = new (zone) | 5235 LocationSummary* summary = new (zone) |
| 5467 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5236 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5468 summary->set_in(0, Location::RequiresRegister()); | 5237 summary->set_in(0, Location::RequiresRegister()); |
| 5469 return summary; | 5238 return summary; |
| 5470 } | 5239 } |
| 5471 | 5240 |
| 5472 | |
| 5473 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5241 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5474 const Register value = locs()->in(0).reg(); | 5242 const Register value = locs()->in(0).reg(); |
| 5475 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, | 5243 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, |
| 5476 licm_hoisted_ ? ICData::kHoisted : 0); | 5244 licm_hoisted_ ? ICData::kHoisted : 0); |
| 5477 __ BranchIfNotSmi(value, deopt); | 5245 __ BranchIfNotSmi(value, deopt); |
| 5478 } | 5246 } |
| 5479 | 5247 |
| 5480 | |
| 5481 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, | 5248 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, |
| 5482 bool opt) const { | 5249 bool opt) const { |
| 5483 const intptr_t kNumInputs = 2; | 5250 const intptr_t kNumInputs = 2; |
| 5484 const intptr_t kNumTemps = 0; | 5251 const intptr_t kNumTemps = 0; |
| 5485 LocationSummary* locs = new (zone) LocationSummary( | 5252 LocationSummary* locs = new (zone) LocationSummary( |
| 5486 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 5253 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 5487 locs->set_in(kLengthPos, Location::RequiresRegister()); | 5254 locs->set_in(kLengthPos, Location::RequiresRegister()); |
| 5488 locs->set_in(kIndexPos, Location::RequiresRegister()); | 5255 locs->set_in(kIndexPos, Location::RequiresRegister()); |
| 5489 return locs; | 5256 return locs; |
| 5490 } | 5257 } |
| 5491 | 5258 |
| 5492 | |
| 5493 class RangeErrorSlowPath : public SlowPathCode { | 5259 class RangeErrorSlowPath : public SlowPathCode { |
| 5494 public: | 5260 public: |
| 5495 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) | 5261 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) |
| 5496 : instruction_(instruction), try_index_(try_index) {} | 5262 : instruction_(instruction), try_index_(try_index) {} |
| 5497 | 5263 |
| 5498 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 5264 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5499 if (Assembler::EmittingComments()) { | 5265 if (Assembler::EmittingComments()) { |
| 5500 __ Comment("slow path check bound operation"); | 5266 __ Comment("slow path check bound operation"); |
| 5501 } | 5267 } |
| 5502 __ Bind(entry_label()); | 5268 __ Bind(entry_label()); |
| 5503 LocationSummary* locs = instruction_->locs(); | 5269 LocationSummary* locs = instruction_->locs(); |
| 5504 compiler->SaveLiveRegisters(locs); | 5270 compiler->SaveLiveRegisters(locs); |
| 5505 __ Push(locs->in(0).reg()); | 5271 __ Push(locs->in(0).reg()); |
| 5506 __ Push(locs->in(1).reg()); | 5272 __ Push(locs->in(1).reg()); |
| 5507 __ CallRuntime(kRangeErrorRuntimeEntry, 2); | 5273 __ CallRuntime(kRangeErrorRuntimeEntry, 2); |
| 5508 compiler->AddDescriptor( | 5274 compiler->AddDescriptor( |
| 5509 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), | 5275 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), |
| 5510 instruction_->deopt_id(), instruction_->token_pos(), try_index_); | 5276 instruction_->deopt_id(), instruction_->token_pos(), try_index_); |
| 5511 compiler->RecordSafepoint(locs, 2); | 5277 compiler->RecordSafepoint(locs, 2); |
| 5512 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); | 5278 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |
| 5513 compiler->EmitCatchEntryState(env, try_index_); | 5279 compiler->EmitCatchEntryState(env, try_index_); |
| 5514 __ brk(0); | 5280 __ brk(0); |
| 5515 } | 5281 } |
| 5516 | 5282 |
| 5517 private: | 5283 private: |
| 5518 GenericCheckBoundInstr* instruction_; | 5284 GenericCheckBoundInstr* instruction_; |
| 5519 intptr_t try_index_; | 5285 intptr_t try_index_; |
| 5520 }; | 5286 }; |
| 5521 | 5287 |
| 5522 | |
| 5523 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5288 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5524 RangeErrorSlowPath* slow_path = | 5289 RangeErrorSlowPath* slow_path = |
| 5525 new RangeErrorSlowPath(this, compiler->CurrentTryIndex()); | 5290 new RangeErrorSlowPath(this, compiler->CurrentTryIndex()); |
| 5526 compiler->AddSlowPathCode(slow_path); | 5291 compiler->AddSlowPathCode(slow_path); |
| 5527 | 5292 |
| 5528 Location length_loc = locs()->in(kLengthPos); | 5293 Location length_loc = locs()->in(kLengthPos); |
| 5529 Location index_loc = locs()->in(kIndexPos); | 5294 Location index_loc = locs()->in(kIndexPos); |
| 5530 Register length = length_loc.reg(); | 5295 Register length = length_loc.reg(); |
| 5531 Register index = index_loc.reg(); | 5296 Register index = index_loc.reg(); |
| 5532 const intptr_t index_cid = this->index()->Type()->ToCid(); | 5297 const intptr_t index_cid = this->index()->Type()->ToCid(); |
| 5533 if (index_cid != kSmiCid) { | 5298 if (index_cid != kSmiCid) { |
| 5534 __ BranchIfNotSmi(index, slow_path->entry_label()); | 5299 __ BranchIfNotSmi(index, slow_path->entry_label()); |
| 5535 } | 5300 } |
| 5536 __ cmp(index, Operand(length)); | 5301 __ cmp(index, Operand(length)); |
| 5537 __ b(slow_path->entry_label(), CS); | 5302 __ b(slow_path->entry_label(), CS); |
| 5538 } | 5303 } |
| 5539 | 5304 |
| 5540 | |
| 5541 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 5305 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
| 5542 bool opt) const { | 5306 bool opt) const { |
| 5543 const intptr_t kNumInputs = 2; | 5307 const intptr_t kNumInputs = 2; |
| 5544 const intptr_t kNumTemps = 0; | 5308 const intptr_t kNumTemps = 0; |
| 5545 LocationSummary* locs = new (zone) | 5309 LocationSummary* locs = new (zone) |
| 5546 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5310 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5547 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 5311 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
| 5548 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 5312 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
| 5549 return locs; | 5313 return locs; |
| 5550 } | 5314 } |
| 5551 | 5315 |
| 5552 | |
| 5553 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5316 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5554 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 5317 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |
| 5555 flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 5318 flags |= licm_hoisted_ ? ICData::kHoisted : 0; |
| 5556 Label* deopt = | 5319 Label* deopt = |
| 5557 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); | 5320 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); |
| 5558 | 5321 |
| 5559 Location length_loc = locs()->in(kLengthPos); | 5322 Location length_loc = locs()->in(kLengthPos); |
| 5560 Location index_loc = locs()->in(kIndexPos); | 5323 Location index_loc = locs()->in(kIndexPos); |
| 5561 | 5324 |
| 5562 const intptr_t index_cid = index()->Type()->ToCid(); | 5325 const intptr_t index_cid = index()->Type()->ToCid(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5599 const Register length = length_loc.reg(); | 5362 const Register length = length_loc.reg(); |
| 5600 const Register index = index_loc.reg(); | 5363 const Register index = index_loc.reg(); |
| 5601 if (index_cid != kSmiCid) { | 5364 if (index_cid != kSmiCid) { |
| 5602 __ BranchIfNotSmi(index, deopt); | 5365 __ BranchIfNotSmi(index, deopt); |
| 5603 } | 5366 } |
| 5604 __ CompareRegisters(index, length); | 5367 __ CompareRegisters(index, length); |
| 5605 __ b(deopt, CS); | 5368 __ b(deopt, CS); |
| 5606 } | 5369 } |
| 5607 } | 5370 } |
| 5608 | 5371 |
| 5609 | |
| 5610 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5372 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, |
| 5611 bool opt) const { | 5373 bool opt) const { |
| 5612 UNIMPLEMENTED(); | 5374 UNIMPLEMENTED(); |
| 5613 return NULL; | 5375 return NULL; |
| 5614 } | 5376 } |
| 5615 | 5377 |
| 5616 | |
| 5617 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5378 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5618 UNIMPLEMENTED(); | 5379 UNIMPLEMENTED(); |
| 5619 } | 5380 } |
| 5620 | 5381 |
| 5621 | |
| 5622 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, | 5382 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, |
| 5623 bool opt) const { | 5383 bool opt) const { |
| 5624 UNIMPLEMENTED(); | 5384 UNIMPLEMENTED(); |
| 5625 return NULL; | 5385 return NULL; |
| 5626 } | 5386 } |
| 5627 | 5387 |
| 5628 | |
| 5629 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5388 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5630 UNIMPLEMENTED(); | 5389 UNIMPLEMENTED(); |
| 5631 } | 5390 } |
| 5632 | 5391 |
| 5633 | |
| 5634 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5392 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, |
| 5635 bool opt) const { | 5393 bool opt) const { |
| 5636 UNIMPLEMENTED(); | 5394 UNIMPLEMENTED(); |
| 5637 return NULL; | 5395 return NULL; |
| 5638 } | 5396 } |
| 5639 | 5397 |
| 5640 | |
| 5641 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5398 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5642 UNIMPLEMENTED(); | 5399 UNIMPLEMENTED(); |
| 5643 } | 5400 } |
| 5644 | 5401 |
| 5645 | |
| 5646 CompileType BinaryUint32OpInstr::ComputeType() const { | 5402 CompileType BinaryUint32OpInstr::ComputeType() const { |
| 5647 return CompileType::FromCid(kSmiCid); | 5403 return CompileType::FromCid(kSmiCid); |
| 5648 } | 5404 } |
| 5649 | 5405 |
| 5650 | |
| 5651 CompileType ShiftUint32OpInstr::ComputeType() const { | 5406 CompileType ShiftUint32OpInstr::ComputeType() const { |
| 5652 return CompileType::FromCid(kSmiCid); | 5407 return CompileType::FromCid(kSmiCid); |
| 5653 } | 5408 } |
| 5654 | 5409 |
| 5655 | |
| 5656 CompileType UnaryUint32OpInstr::ComputeType() const { | 5410 CompileType UnaryUint32OpInstr::ComputeType() const { |
| 5657 return CompileType::FromCid(kSmiCid); | 5411 return CompileType::FromCid(kSmiCid); |
| 5658 } | 5412 } |
| 5659 | 5413 |
| 5660 | |
| 5661 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) | 5414 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) |
| 5662 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) | 5415 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) |
| 5663 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) | 5416 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) |
| 5664 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 5417 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
| 5665 | 5418 |
| 5666 | |
| 5667 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 5419 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |
| 5668 bool opt) const { | 5420 bool opt) const { |
| 5669 const intptr_t kNumInputs = 1; | 5421 const intptr_t kNumInputs = 1; |
| 5670 const intptr_t kNumTemps = 0; | 5422 const intptr_t kNumTemps = 0; |
| 5671 LocationSummary* summary = new (zone) | 5423 LocationSummary* summary = new (zone) |
| 5672 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5424 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5673 if (from() == kUnboxedMint) { | 5425 if (from() == kUnboxedMint) { |
| 5674 UNREACHABLE(); | 5426 UNREACHABLE(); |
| 5675 } else if (to() == kUnboxedMint) { | 5427 } else if (to() == kUnboxedMint) { |
| 5676 UNREACHABLE(); | 5428 UNREACHABLE(); |
| 5677 } else { | 5429 } else { |
| 5678 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 5430 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 5679 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 5431 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5680 summary->set_in(0, Location::RequiresRegister()); | 5432 summary->set_in(0, Location::RequiresRegister()); |
| 5681 summary->set_out(0, Location::RequiresRegister()); | 5433 summary->set_out(0, Location::RequiresRegister()); |
| 5682 } | 5434 } |
| 5683 return summary; | 5435 return summary; |
| 5684 } | 5436 } |
| 5685 | 5437 |
| 5686 | |
| 5687 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5438 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5688 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { | 5439 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { |
| 5689 const Register value = locs()->in(0).reg(); | 5440 const Register value = locs()->in(0).reg(); |
| 5690 const Register out = locs()->out(0).reg(); | 5441 const Register out = locs()->out(0).reg(); |
| 5691 // Representations are bitwise equivalent but we want to normalize | 5442 // Representations are bitwise equivalent but we want to normalize |
| 5692 // upperbits for safety reasons. | 5443 // upperbits for safety reasons. |
| 5693 // TODO(vegorov) if we ensure that we never use kDoubleWord size | 5444 // TODO(vegorov) if we ensure that we never use kDoubleWord size |
| 5694 // with it then we could avoid this. | 5445 // with it then we could avoid this. |
| 5695 // TODO(vegorov) implement and use UBFM for zero extension. | 5446 // TODO(vegorov) implement and use UBFM for zero extension. |
| 5696 __ LslImmediate(out, value, 32); | 5447 __ LslImmediate(out, value, 32); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 5713 } else if (from() == kUnboxedMint) { | 5464 } else if (from() == kUnboxedMint) { |
| 5714 UNREACHABLE(); | 5465 UNREACHABLE(); |
| 5715 } else if (to() == kUnboxedMint) { | 5466 } else if (to() == kUnboxedMint) { |
| 5716 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 5467 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5717 UNREACHABLE(); | 5468 UNREACHABLE(); |
| 5718 } else { | 5469 } else { |
| 5719 UNREACHABLE(); | 5470 UNREACHABLE(); |
| 5720 } | 5471 } |
| 5721 } | 5472 } |
| 5722 | 5473 |
| 5723 | |
| 5724 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 5474 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5725 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | 5475 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 5726 } | 5476 } |
| 5727 | 5477 |
| 5728 | |
| 5729 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5478 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5730 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, | 5479 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, |
| 5731 locs()); | 5480 locs()); |
| 5732 __ brk(0); | 5481 __ brk(0); |
| 5733 } | 5482 } |
| 5734 | 5483 |
| 5735 | |
| 5736 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 5484 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5737 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | 5485 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 5738 } | 5486 } |
| 5739 | 5487 |
| 5740 | |
| 5741 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5488 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5742 compiler->SetNeedsStackTrace(catch_try_index()); | 5489 compiler->SetNeedsStackTrace(catch_try_index()); |
| 5743 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, | 5490 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, |
| 5744 2, locs()); | 5491 2, locs()); |
| 5745 __ brk(0); | 5492 __ brk(0); |
| 5746 } | 5493 } |
| 5747 | 5494 |
| 5748 | |
| 5749 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 5495 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5750 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | 5496 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 5751 } | 5497 } |
| 5752 | 5498 |
| 5753 | |
| 5754 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5499 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5755 __ Stop(message()); | 5500 __ Stop(message()); |
| 5756 } | 5501 } |
| 5757 | 5502 |
| 5758 | |
| 5759 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5503 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5760 if (!compiler->CanFallThroughTo(normal_entry())) { | 5504 if (!compiler->CanFallThroughTo(normal_entry())) { |
| 5761 __ b(compiler->GetJumpLabel(normal_entry())); | 5505 __ b(compiler->GetJumpLabel(normal_entry())); |
| 5762 } | 5506 } |
| 5763 } | 5507 } |
| 5764 | 5508 |
| 5765 | |
| 5766 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 5509 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5767 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | 5510 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 5768 } | 5511 } |
| 5769 | 5512 |
| 5770 | |
| 5771 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5513 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5772 if (!compiler->is_optimizing()) { | 5514 if (!compiler->is_optimizing()) { |
| 5773 if (FLAG_reorder_basic_blocks) { | 5515 if (FLAG_reorder_basic_blocks) { |
| 5774 compiler->EmitEdgeCounter(block()->preorder_number()); | 5516 compiler->EmitEdgeCounter(block()->preorder_number()); |
| 5775 } | 5517 } |
| 5776 // Add a deoptimization descriptor for deoptimizing instructions that | 5518 // Add a deoptimization descriptor for deoptimizing instructions that |
| 5777 // may be inserted before this instruction. | 5519 // may be inserted before this instruction. |
| 5778 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), | 5520 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), |
| 5779 TokenPosition::kNoSource); | 5521 TokenPosition::kNoSource); |
| 5780 } | 5522 } |
| 5781 if (HasParallelMove()) { | 5523 if (HasParallelMove()) { |
| 5782 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 5524 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 5783 } | 5525 } |
| 5784 | 5526 |
| 5785 // We can fall through if the successor is the next block in the list. | 5527 // We can fall through if the successor is the next block in the list. |
| 5786 // Otherwise, we need a jump. | 5528 // Otherwise, we need a jump. |
| 5787 if (!compiler->CanFallThroughTo(successor())) { | 5529 if (!compiler->CanFallThroughTo(successor())) { |
| 5788 __ b(compiler->GetJumpLabel(successor())); | 5530 __ b(compiler->GetJumpLabel(successor())); |
| 5789 } | 5531 } |
| 5790 } | 5532 } |
| 5791 | 5533 |
| 5792 | |
| 5793 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 5534 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |
| 5794 bool opt) const { | 5535 bool opt) const { |
| 5795 const intptr_t kNumInputs = 1; | 5536 const intptr_t kNumInputs = 1; |
| 5796 const intptr_t kNumTemps = 1; | 5537 const intptr_t kNumTemps = 1; |
| 5797 | 5538 |
| 5798 LocationSummary* summary = new (zone) | 5539 LocationSummary* summary = new (zone) |
| 5799 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5540 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5800 | 5541 |
| 5801 summary->set_in(0, Location::RequiresRegister()); | 5542 summary->set_in(0, Location::RequiresRegister()); |
| 5802 summary->set_temp(0, Location::RequiresRegister()); | 5543 summary->set_temp(0, Location::RequiresRegister()); |
| 5803 | 5544 |
| 5804 return summary; | 5545 return summary; |
| 5805 } | 5546 } |
| 5806 | 5547 |
| 5807 | |
| 5808 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5548 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5809 Register target_address_reg = locs()->temp_slot(0)->reg(); | 5549 Register target_address_reg = locs()->temp_slot(0)->reg(); |
| 5810 | 5550 |
| 5811 // Load code entry point. | 5551 // Load code entry point. |
| 5812 const intptr_t entry_offset = __ CodeSize(); | 5552 const intptr_t entry_offset = __ CodeSize(); |
| 5813 if (Utils::IsInt(21, -entry_offset)) { | 5553 if (Utils::IsInt(21, -entry_offset)) { |
| 5814 __ adr(target_address_reg, Immediate(-entry_offset)); | 5554 __ adr(target_address_reg, Immediate(-entry_offset)); |
| 5815 } else { | 5555 } else { |
| 5816 __ adr(target_address_reg, Immediate(0)); | 5556 __ adr(target_address_reg, Immediate(0)); |
| 5817 __ AddImmediate(target_address_reg, -entry_offset); | 5557 __ AddImmediate(target_address_reg, -entry_offset); |
| 5818 } | 5558 } |
| 5819 | 5559 |
| 5820 // Add the offset. | 5560 // Add the offset. |
| 5821 Register offset_reg = locs()->in(0).reg(); | 5561 Register offset_reg = locs()->in(0).reg(); |
| 5822 Operand offset_opr = (offset()->definition()->representation() == kTagged) | 5562 Operand offset_opr = (offset()->definition()->representation() == kTagged) |
| 5823 ? Operand(offset_reg, ASR, kSmiTagSize) | 5563 ? Operand(offset_reg, ASR, kSmiTagSize) |
| 5824 : Operand(offset_reg); | 5564 : Operand(offset_reg); |
| 5825 __ add(target_address_reg, target_address_reg, offset_opr); | 5565 __ add(target_address_reg, target_address_reg, offset_opr); |
| 5826 | 5566 |
| 5827 // Jump to the absolute address. | 5567 // Jump to the absolute address. |
| 5828 __ br(target_address_reg); | 5568 __ br(target_address_reg); |
| 5829 } | 5569 } |
| 5830 | 5570 |
| 5831 | |
| 5832 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, | 5571 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, |
| 5833 bool opt) const { | 5572 bool opt) const { |
| 5834 const intptr_t kNumInputs = 2; | 5573 const intptr_t kNumInputs = 2; |
| 5835 const intptr_t kNumTemps = 0; | 5574 const intptr_t kNumTemps = 0; |
| 5836 if (needs_number_check()) { | 5575 if (needs_number_check()) { |
| 5837 LocationSummary* locs = new (zone) | 5576 LocationSummary* locs = new (zone) |
| 5838 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5577 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 5839 locs->set_in(0, Location::RegisterLocation(R0)); | 5578 locs->set_in(0, Location::RegisterLocation(R0)); |
| 5840 locs->set_in(1, Location::RegisterLocation(R1)); | 5579 locs->set_in(1, Location::RegisterLocation(R1)); |
| 5841 locs->set_out(0, Location::RegisterLocation(R0)); | 5580 locs->set_out(0, Location::RegisterLocation(R0)); |
| 5842 return locs; | 5581 return locs; |
| 5843 } | 5582 } |
| 5844 LocationSummary* locs = new (zone) | 5583 LocationSummary* locs = new (zone) |
| 5845 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5584 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5846 locs->set_in(0, Location::RegisterOrConstant(left())); | 5585 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 5847 // Only one of the inputs can be a constant. Choose register if the first one | 5586 // Only one of the inputs can be a constant. Choose register if the first one |
| 5848 // is a constant. | 5587 // is a constant. |
| 5849 locs->set_in(1, locs->in(0).IsConstant() | 5588 locs->set_in(1, locs->in(0).IsConstant() |
| 5850 ? Location::RequiresRegister() | 5589 ? Location::RequiresRegister() |
| 5851 : Location::RegisterOrConstant(right())); | 5590 : Location::RegisterOrConstant(right())); |
| 5852 locs->set_out(0, Location::RequiresRegister()); | 5591 locs->set_out(0, Location::RequiresRegister()); |
| 5853 return locs; | 5592 return locs; |
| 5854 } | 5593 } |
| 5855 | 5594 |
| 5856 | |
| 5857 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 5595 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 5858 BranchLabels labels) { | 5596 BranchLabels labels) { |
| 5859 Location left = locs()->in(0); | 5597 Location left = locs()->in(0); |
| 5860 Location right = locs()->in(1); | 5598 Location right = locs()->in(1); |
| 5861 ASSERT(!left.IsConstant() || !right.IsConstant()); | 5599 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 5862 Condition true_condition; | 5600 Condition true_condition; |
| 5863 if (left.IsConstant()) { | 5601 if (left.IsConstant()) { |
| 5864 true_condition = compiler->EmitEqualityRegConstCompare( | 5602 true_condition = compiler->EmitEqualityRegConstCompare( |
| 5865 right.reg(), left.constant(), needs_number_check(), token_pos(), | 5603 right.reg(), left.constant(), needs_number_check(), token_pos(), |
| 5866 deopt_id_); | 5604 deopt_id_); |
| 5867 } else if (right.IsConstant()) { | 5605 } else if (right.IsConstant()) { |
| 5868 true_condition = compiler->EmitEqualityRegConstCompare( | 5606 true_condition = compiler->EmitEqualityRegConstCompare( |
| 5869 left.reg(), right.constant(), needs_number_check(), token_pos(), | 5607 left.reg(), right.constant(), needs_number_check(), token_pos(), |
| 5870 deopt_id_); | 5608 deopt_id_); |
| 5871 } else { | 5609 } else { |
| 5872 true_condition = compiler->EmitEqualityRegRegCompare( | 5610 true_condition = compiler->EmitEqualityRegRegCompare( |
| 5873 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); | 5611 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); |
| 5874 } | 5612 } |
| 5875 if (kind() != Token::kEQ_STRICT) { | 5613 if (kind() != Token::kEQ_STRICT) { |
| 5876 ASSERT(kind() == Token::kNE_STRICT); | 5614 ASSERT(kind() == Token::kNE_STRICT); |
| 5877 true_condition = NegateCondition(true_condition); | 5615 true_condition = NegateCondition(true_condition); |
| 5878 } | 5616 } |
| 5879 return true_condition; | 5617 return true_condition; |
| 5880 } | 5618 } |
| 5881 | 5619 |
| 5882 | |
| 5883 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5620 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5884 Label is_true, is_false; | 5621 Label is_true, is_false; |
| 5885 BranchLabels labels = {&is_true, &is_false, &is_false}; | 5622 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 5886 Condition true_condition = EmitComparisonCode(compiler, labels); | 5623 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 5887 const Register result = this->locs()->out(0).reg(); | 5624 const Register result = this->locs()->out(0).reg(); |
| 5888 | 5625 |
| 5889 // TODO(dartbug.com/29908): Use csel here for better branch prediction? | 5626 // TODO(dartbug.com/29908): Use csel here for better branch prediction? |
| 5890 if (true_condition != kInvalidCondition) { | 5627 if (true_condition != kInvalidCondition) { |
| 5891 EmitBranchOnCondition(compiler, true_condition, labels); | 5628 EmitBranchOnCondition(compiler, true_condition, labels); |
| 5892 } | 5629 } |
| 5893 Label done; | 5630 Label done; |
| 5894 __ Bind(&is_false); | 5631 __ Bind(&is_false); |
| 5895 __ LoadObject(result, Bool::False()); | 5632 __ LoadObject(result, Bool::False()); |
| 5896 __ b(&done); | 5633 __ b(&done); |
| 5897 __ Bind(&is_true); | 5634 __ Bind(&is_true); |
| 5898 __ LoadObject(result, Bool::True()); | 5635 __ LoadObject(result, Bool::True()); |
| 5899 __ Bind(&done); | 5636 __ Bind(&done); |
| 5900 } | 5637 } |
| 5901 | 5638 |
| 5902 | |
| 5903 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 5639 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 5904 BranchInstr* branch) { | 5640 BranchInstr* branch) { |
| 5905 BranchLabels labels = compiler->CreateBranchLabels(branch); | 5641 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 5906 Condition true_condition = EmitComparisonCode(compiler, labels); | 5642 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 5907 if (true_condition != kInvalidCondition) { | 5643 if (true_condition != kInvalidCondition) { |
| 5908 EmitBranchOnCondition(compiler, true_condition, labels); | 5644 EmitBranchOnCondition(compiler, true_condition, labels); |
| 5909 } | 5645 } |
| 5910 } | 5646 } |
| 5911 | 5647 |
| 5912 | |
| 5913 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 5648 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
| 5914 bool opt) const { | 5649 bool opt) const { |
| 5915 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), | 5650 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
| 5916 LocationSummary::kNoCall); | 5651 LocationSummary::kNoCall); |
| 5917 } | 5652 } |
| 5918 | 5653 |
| 5919 | |
| 5920 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5654 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5921 const Register value = locs()->in(0).reg(); | 5655 const Register value = locs()->in(0).reg(); |
| 5922 const Register result = locs()->out(0).reg(); | 5656 const Register result = locs()->out(0).reg(); |
| 5923 | 5657 |
| 5924 __ LoadObject(result, Bool::True()); | 5658 __ LoadObject(result, Bool::True()); |
| 5925 __ LoadObject(TMP, Bool::False()); | 5659 __ LoadObject(TMP, Bool::False()); |
| 5926 __ CompareRegisters(result, value); | 5660 __ CompareRegisters(result, value); |
| 5927 __ csel(result, TMP, result, EQ); | 5661 __ csel(result, TMP, result, EQ); |
| 5928 } | 5662 } |
| 5929 | 5663 |
| 5930 | |
| 5931 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 5664 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
| 5932 bool opt) const { | 5665 bool opt) const { |
| 5933 return MakeCallSummary(zone); | 5666 return MakeCallSummary(zone); |
| 5934 } | 5667 } |
| 5935 | 5668 |
| 5936 | |
| 5937 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5669 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5938 const Code& stub = Code::ZoneHandle( | 5670 const Code& stub = Code::ZoneHandle( |
| 5939 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 5671 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |
| 5940 const StubEntry stub_entry(stub); | 5672 const StubEntry stub_entry(stub); |
| 5941 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, | 5673 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, |
| 5942 locs()); | 5674 locs()); |
| 5943 compiler->AddStubCallTarget(stub); | 5675 compiler->AddStubCallTarget(stub); |
| 5944 __ Drop(ArgumentCount()); // Discard arguments. | 5676 __ Drop(ArgumentCount()); // Discard arguments. |
| 5945 } | 5677 } |
| 5946 | 5678 |
| 5947 | |
| 5948 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5679 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5949 ASSERT(!compiler->is_optimizing()); | 5680 ASSERT(!compiler->is_optimizing()); |
| 5950 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); | 5681 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); |
| 5951 compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos()); | 5682 compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos()); |
| 5952 compiler->RecordSafepoint(locs()); | 5683 compiler->RecordSafepoint(locs()); |
| 5953 } | 5684 } |
| 5954 | 5685 |
| 5955 | |
| 5956 } // namespace dart | 5686 } // namespace dart |
| 5957 | 5687 |
| 5958 #endif // defined TARGET_ARCH_ARM64 | 5688 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |