| OLD | NEW |
| 1 | 1 |
| 2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
| 4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
| 5 | 5 |
| 6 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 6 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 7 #if defined(TARGET_ARCH_ARM) | 7 #if defined(TARGET_ARCH_ARM) |
| 8 | 8 |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 | 10 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 #include "vm/symbols.h" | 24 #include "vm/symbols.h" |
| 25 | 25 |
| 26 #define __ compiler->assembler()-> | 26 #define __ compiler->assembler()-> |
| 27 #define Z (compiler->zone()) | 27 #define Z (compiler->zone()) |
| 28 | 28 |
| 29 namespace dart { | 29 namespace dart { |
| 30 | 30 |
| 31 // Generic summary for call instructions that have all arguments pushed | 31 // Generic summary for call instructions that have all arguments pushed |
| 32 // on the stack and return the result in a fixed register R0. | 32 // on the stack and return the result in a fixed register R0. |
| 33 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { | 33 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { |
| 34 LocationSummary* result = new(zone) LocationSummary( | 34 LocationSummary* result = |
| 35 zone, 0, 0, LocationSummary::kCall); | 35 new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 36 result->set_out(0, Location::RegisterLocation(R0)); | 36 result->set_out(0, Location::RegisterLocation(R0)); |
| 37 return result; | 37 return result; |
| 38 } | 38 } |
| 39 | 39 |
| 40 | 40 |
| 41 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, | 41 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, |
| 42 bool opt) const { | 42 bool opt) const { |
| 43 const intptr_t kNumInputs = 1; | 43 const intptr_t kNumInputs = 1; |
| 44 const intptr_t kNumTemps = 0; | 44 const intptr_t kNumTemps = 0; |
| 45 LocationSummary* locs = new(zone) LocationSummary( | 45 LocationSummary* locs = new (zone) |
| 46 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 46 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 47 locs->set_in(0, Location::AnyOrConstant(value())); | 47 locs->set_in(0, Location::AnyOrConstant(value())); |
| 48 return locs; | 48 return locs; |
| 49 } | 49 } |
| 50 | 50 |
| 51 | 51 |
| 52 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 52 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 53 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 53 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
| 54 // where PushArgument is handled by BindInstr::EmitNativeCode. | 54 // where PushArgument is handled by BindInstr::EmitNativeCode. |
| 55 if (compiler->is_optimizing()) { | 55 if (compiler->is_optimizing()) { |
| 56 Location value = locs()->in(0); | 56 Location value = locs()->in(0); |
| 57 if (value.IsRegister()) { | 57 if (value.IsRegister()) { |
| 58 __ Push(value.reg()); | 58 __ Push(value.reg()); |
| 59 } else if (value.IsConstant()) { | 59 } else if (value.IsConstant()) { |
| 60 __ PushObject(value.constant()); | 60 __ PushObject(value.constant()); |
| 61 } else { | 61 } else { |
| 62 ASSERT(value.IsStackSlot()); | 62 ASSERT(value.IsStackSlot()); |
| 63 const intptr_t value_offset = value.ToStackSlotOffset(); | 63 const intptr_t value_offset = value.ToStackSlotOffset(); |
| 64 __ LoadFromOffset(kWord, IP, value.base_reg(), value_offset); | 64 __ LoadFromOffset(kWord, IP, value.base_reg(), value_offset); |
| 65 __ Push(IP); | 65 __ Push(IP); |
| 66 } | 66 } |
| 67 } | 67 } |
| 68 } | 68 } |
| 69 | 69 |
| 70 | 70 |
| 71 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, | 71 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 72 bool opt) const { | |
| 73 const intptr_t kNumInputs = 1; | 72 const intptr_t kNumInputs = 1; |
| 74 const intptr_t kNumTemps = 0; | 73 const intptr_t kNumTemps = 0; |
| 75 LocationSummary* locs = new(zone) LocationSummary( | 74 LocationSummary* locs = new (zone) |
| 76 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 75 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 77 locs->set_in(0, Location::RegisterLocation(R0)); | 76 locs->set_in(0, Location::RegisterLocation(R0)); |
| 78 return locs; | 77 return locs; |
| 79 } | 78 } |
| 80 | 79 |
| 81 | 80 |
| 82 // Attempt optimized compilation at return instruction instead of at the entry. | 81 // Attempt optimized compilation at return instruction instead of at the entry. |
| 83 // The entry needs to be patchable, no inlined objects are allowed in the area | 82 // The entry needs to be patchable, no inlined objects are allowed in the area |
| 84 // that will be overwritten by the patch instructions: a branch macro sequence. | 83 // that will be overwritten by the patch instructions: a branch macro sequence. |
| 85 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 84 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 86 const Register result = locs()->in(0).reg(); | 85 const Register result = locs()->in(0).reg(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 108 __ LeaveDartFrame(); // Disallows constant pool use. | 107 __ LeaveDartFrame(); // Disallows constant pool use. |
| 109 __ Ret(); | 108 __ Ret(); |
| 110 // This ReturnInstr may be emitted out of order by the optimizer. The next | 109 // This ReturnInstr may be emitted out of order by the optimizer. The next |
| 111 // block may be a target expecting a properly set constant pool pointer. | 110 // block may be a target expecting a properly set constant pool pointer. |
| 112 __ set_constant_pool_allowed(true); | 111 __ set_constant_pool_allowed(true); |
| 113 } | 112 } |
| 114 | 113 |
| 115 | 114 |
| 116 static Condition NegateCondition(Condition condition) { | 115 static Condition NegateCondition(Condition condition) { |
| 117 switch (condition) { | 116 switch (condition) { |
| 118 case EQ: return NE; | 117 case EQ: |
| 119 case NE: return EQ; | 118 return NE; |
| 120 case LT: return GE; | 119 case NE: |
| 121 case LE: return GT; | 120 return EQ; |
| 122 case GT: return LE; | 121 case LT: |
| 123 case GE: return LT; | 122 return GE; |
| 124 case CC: return CS; | 123 case LE: |
| 125 case LS: return HI; | 124 return GT; |
| 126 case HI: return LS; | 125 case GT: |
| 127 case CS: return CC; | 126 return LE; |
| 128 case VC: return VS; | 127 case GE: |
| 129 case VS: return VC; | 128 return LT; |
| 129 case CC: |
| 130 return CS; |
| 131 case LS: |
| 132 return HI; |
| 133 case HI: |
| 134 return LS; |
| 135 case CS: |
| 136 return CC; |
| 137 case VC: |
| 138 return VS; |
| 139 case VS: |
| 140 return VC; |
| 130 default: | 141 default: |
| 131 UNREACHABLE(); | 142 UNREACHABLE(); |
| 132 return EQ; | 143 return EQ; |
| 133 } | 144 } |
| 134 } | 145 } |
| 135 | 146 |
| 136 | 147 |
| 137 // Detect pattern when one value is zero and another is a power of 2. | 148 // Detect pattern when one value is zero and another is a power of 2. |
| 138 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 149 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 139 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 150 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| (...skipping 12 matching lines...) Expand all Loading... |
| 152 const Register result = locs()->out(0).reg(); | 163 const Register result = locs()->out(0).reg(); |
| 153 | 164 |
| 154 Location left = locs()->in(0); | 165 Location left = locs()->in(0); |
| 155 Location right = locs()->in(1); | 166 Location right = locs()->in(1); |
| 156 ASSERT(!left.IsConstant() || !right.IsConstant()); | 167 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 157 | 168 |
| 158 // Clear out register. | 169 // Clear out register. |
| 159 __ eor(result, result, Operand(result)); | 170 __ eor(result, result, Operand(result)); |
| 160 | 171 |
| 161 // Emit comparison code. This must not overwrite the result register. | 172 // Emit comparison code. This must not overwrite the result register. |
| 162 BranchLabels labels = { NULL, NULL, NULL }; | 173 BranchLabels labels = {NULL, NULL, NULL}; |
| 163 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 174 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
| 164 | 175 |
| 165 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 176 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
| 166 | 177 |
| 167 intptr_t true_value = if_true_; | 178 intptr_t true_value = if_true_; |
| 168 intptr_t false_value = if_false_; | 179 intptr_t false_value = if_false_; |
| 169 | 180 |
| 170 if (is_power_of_two_kind) { | 181 if (is_power_of_two_kind) { |
| 171 if (true_value == 0) { | 182 if (true_value == 0) { |
| 172 // We need to have zero in result on true_condition. | 183 // We need to have zero in result on true_condition. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 184 } | 195 } |
| 185 | 196 |
| 186 __ mov(result, Operand(1), true_condition); | 197 __ mov(result, Operand(1), true_condition); |
| 187 | 198 |
| 188 if (is_power_of_two_kind) { | 199 if (is_power_of_two_kind) { |
| 189 const intptr_t shift = | 200 const intptr_t shift = |
| 190 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); | 201 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
| 191 __ Lsl(result, result, Operand(shift + kSmiTagSize)); | 202 __ Lsl(result, result, Operand(shift + kSmiTagSize)); |
| 192 } else { | 203 } else { |
| 193 __ sub(result, result, Operand(1)); | 204 __ sub(result, result, Operand(1)); |
| 194 const int32_t val = | 205 const int32_t val = Smi::RawValue(true_value) - Smi::RawValue(false_value); |
| 195 Smi::RawValue(true_value) - Smi::RawValue(false_value); | |
| 196 __ AndImmediate(result, result, val); | 206 __ AndImmediate(result, result, val); |
| 197 if (false_value != 0) { | 207 if (false_value != 0) { |
| 198 __ AddImmediate(result, Smi::RawValue(false_value)); | 208 __ AddImmediate(result, Smi::RawValue(false_value)); |
| 199 } | 209 } |
| 200 } | 210 } |
| 201 } | 211 } |
| 202 | 212 |
| 203 | 213 |
| 204 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 214 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |
| 205 bool opt) const { | 215 bool opt) const { |
| 206 const intptr_t kNumInputs = 1; | 216 const intptr_t kNumInputs = 1; |
| 207 const intptr_t kNumTemps = 0; | 217 const intptr_t kNumTemps = 0; |
| 208 LocationSummary* summary = new(zone) LocationSummary( | 218 LocationSummary* summary = new (zone) |
| 209 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 219 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 210 summary->set_in(0, Location::RegisterLocation(R0)); // Function. | 220 summary->set_in(0, Location::RegisterLocation(R0)); // Function. |
| 211 summary->set_out(0, Location::RegisterLocation(R0)); | 221 summary->set_out(0, Location::RegisterLocation(R0)); |
| 212 return summary; | 222 return summary; |
| 213 } | 223 } |
| 214 | 224 |
| 215 | 225 |
| 216 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 226 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 217 // Load arguments descriptor in R4. | 227 // Load arguments descriptor in R4. |
| 218 int argument_count = ArgumentCount(); | 228 int argument_count = ArgumentCount(); |
| 219 const Array& arguments_descriptor = | 229 const Array& arguments_descriptor = Array::ZoneHandle( |
| 220 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 230 ArgumentsDescriptor::New(argument_count, argument_names())); |
| 221 argument_names())); | |
| 222 __ LoadObject(R4, arguments_descriptor); | 231 __ LoadObject(R4, arguments_descriptor); |
| 223 | 232 |
| 224 // R4: Arguments descriptor. | 233 // R4: Arguments descriptor. |
| 225 // R0: Function. | 234 // R0: Function. |
| 226 ASSERT(locs()->in(0).reg() == R0); | 235 ASSERT(locs()->in(0).reg() == R0); |
| 227 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 236 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
| 228 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); | 237 __ ldr(R2, FieldAddress(R0, Function::entry_point_offset())); |
| 229 | 238 |
| 230 // R2: instructions entry point. | 239 // R2: instructions entry point. |
| 231 // R9: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). | 240 // R9: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). |
| 232 __ LoadImmediate(R9, 0); | 241 __ LoadImmediate(R9, 0); |
| 233 __ blx(R2); | 242 __ blx(R2); |
| 234 compiler->RecordSafepoint(locs()); | 243 compiler->RecordSafepoint(locs()); |
| 235 // Marks either the continuation point in unoptimized code or the | 244 // Marks either the continuation point in unoptimized code or the |
| 236 // deoptimization point in optimized code, after call. | 245 // deoptimization point in optimized code, after call. |
| 237 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); | 246 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); |
| 238 if (compiler->is_optimizing()) { | 247 if (compiler->is_optimizing()) { |
| 239 compiler->AddDeoptIndexAtCall(deopt_id_after); | 248 compiler->AddDeoptIndexAtCall(deopt_id_after); |
| 240 } | 249 } |
| 241 // Add deoptimization continuation point after the call and before the | 250 // Add deoptimization continuation point after the call and before the |
| 242 // arguments are removed. | 251 // arguments are removed. |
| 243 // In optimized code this descriptor is needed for exception handling. | 252 // In optimized code this descriptor is needed for exception handling. |
| 244 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 253 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, |
| 245 deopt_id_after, | |
| 246 token_pos()); | 254 token_pos()); |
| 247 __ Drop(argument_count); | 255 __ Drop(argument_count); |
| 248 } | 256 } |
| 249 | 257 |
| 250 | 258 |
| 251 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 259 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
| 252 bool opt) const { | 260 bool opt) const { |
| 253 return LocationSummary::Make(zone, | 261 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), |
| 254 0, | |
| 255 Location::RequiresRegister(), | |
| 256 LocationSummary::kNoCall); | 262 LocationSummary::kNoCall); |
| 257 } | 263 } |
| 258 | 264 |
| 259 | 265 |
| 260 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 266 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 261 const Register result = locs()->out(0).reg(); | 267 const Register result = locs()->out(0).reg(); |
| 262 __ LoadFromOffset(kWord, result, FP, local().index() * kWordSize); | 268 __ LoadFromOffset(kWord, result, FP, local().index() * kWordSize); |
| 263 } | 269 } |
| 264 | 270 |
| 265 | 271 |
| 266 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 272 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |
| 267 bool opt) const { | 273 bool opt) const { |
| 268 return LocationSummary::Make(zone, | 274 return LocationSummary::Make(zone, 1, Location::SameAsFirstInput(), |
| 269 1, | |
| 270 Location::SameAsFirstInput(), | |
| 271 LocationSummary::kNoCall); | 275 LocationSummary::kNoCall); |
| 272 } | 276 } |
| 273 | 277 |
| 274 | 278 |
| 275 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 279 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 276 const Register value = locs()->in(0).reg(); | 280 const Register value = locs()->in(0).reg(); |
| 277 const Register result = locs()->out(0).reg(); | 281 const Register result = locs()->out(0).reg(); |
| 278 ASSERT(result == value); // Assert that register assignment is correct. | 282 ASSERT(result == value); // Assert that register assignment is correct. |
| 279 __ StoreToOffset(kWord, value, FP, local().index() * kWordSize); | 283 __ StoreToOffset(kWord, value, FP, local().index() * kWordSize); |
| 280 } | 284 } |
| 281 | 285 |
| 282 | 286 |
| 283 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 287 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |
| 284 bool opt) const { | 288 bool opt) const { |
| 285 return LocationSummary::Make(zone, | 289 return LocationSummary::Make(zone, 0, Location::RequiresRegister(), |
| 286 0, | |
| 287 Location::RequiresRegister(), | |
| 288 LocationSummary::kNoCall); | 290 LocationSummary::kNoCall); |
| 289 } | 291 } |
| 290 | 292 |
| 291 | 293 |
| 292 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 294 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 293 // The register allocator drops constant definitions that have no uses. | 295 // The register allocator drops constant definitions that have no uses. |
| 294 if (!locs()->out(0).IsInvalid()) { | 296 if (!locs()->out(0).IsInvalid()) { |
| 295 const Register result = locs()->out(0).reg(); | 297 const Register result = locs()->out(0).reg(); |
| 296 __ LoadObject(result, value()); | 298 __ LoadObject(result, value()); |
| 297 } | 299 } |
| 298 } | 300 } |
| 299 | 301 |
| 300 | 302 |
| 301 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 303 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
| 302 bool opt) const { | 304 bool opt) const { |
| 303 const intptr_t kNumInputs = 0; | 305 const intptr_t kNumInputs = 0; |
| 304 const intptr_t kNumTemps = (representation_ == kUnboxedInt32) ? 0 : 1; | 306 const intptr_t kNumTemps = (representation_ == kUnboxedInt32) ? 0 : 1; |
| 305 LocationSummary* locs = new(zone) LocationSummary( | 307 LocationSummary* locs = new (zone) |
| 306 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 308 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 307 if (representation_ == kUnboxedInt32) { | 309 if (representation_ == kUnboxedInt32) { |
| 308 locs->set_out(0, Location::RequiresRegister()); | 310 locs->set_out(0, Location::RequiresRegister()); |
| 309 } else { | 311 } else { |
| 310 ASSERT(representation_ == kUnboxedDouble); | 312 ASSERT(representation_ == kUnboxedDouble); |
| 311 locs->set_out(0, Location::RequiresFpuRegister()); | 313 locs->set_out(0, Location::RequiresFpuRegister()); |
| 312 } | 314 } |
| 313 if (kNumTemps > 0) { | 315 if (kNumTemps > 0) { |
| 314 locs->set_temp(0, Location::RequiresRegister()); | 316 locs->set_temp(0, Location::RequiresRegister()); |
| 315 } | 317 } |
| 316 return locs; | 318 return locs; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 340 break; | 342 break; |
| 341 } | 343 } |
| 342 } | 344 } |
| 343 } | 345 } |
| 344 | 346 |
| 345 | 347 |
| 346 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 348 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
| 347 bool opt) const { | 349 bool opt) const { |
| 348 const intptr_t kNumInputs = 2; | 350 const intptr_t kNumInputs = 2; |
| 349 const intptr_t kNumTemps = 0; | 351 const intptr_t kNumTemps = 0; |
| 350 LocationSummary* summary = new(zone) LocationSummary( | 352 LocationSummary* summary = new (zone) |
| 351 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 353 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 352 summary->set_in(0, Location::RegisterLocation(R0)); // Value. | 354 summary->set_in(0, Location::RegisterLocation(R0)); // Value. |
| 353 summary->set_in(1, Location::RegisterLocation(R1)); // Type arguments. | 355 summary->set_in(1, Location::RegisterLocation(R1)); // Type arguments. |
| 354 summary->set_out(0, Location::RegisterLocation(R0)); | 356 summary->set_out(0, Location::RegisterLocation(R0)); |
| 355 return summary; | 357 return summary; |
| 356 } | 358 } |
| 357 | 359 |
| 358 | 360 |
| 359 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 361 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
| 360 bool opt) const { | 362 bool opt) const { |
| 361 const intptr_t kNumInputs = 1; | 363 const intptr_t kNumInputs = 1; |
| 362 const intptr_t kNumTemps = 0; | 364 const intptr_t kNumTemps = 0; |
| 363 LocationSummary* locs = new(zone) LocationSummary( | 365 LocationSummary* locs = new (zone) |
| 364 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 366 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 365 locs->set_in(0, Location::RegisterLocation(R0)); | 367 locs->set_in(0, Location::RegisterLocation(R0)); |
| 366 locs->set_out(0, Location::RegisterLocation(R0)); | 368 locs->set_out(0, Location::RegisterLocation(R0)); |
| 367 return locs; | 369 return locs; |
| 368 } | 370 } |
| 369 | 371 |
| 370 | 372 |
| 371 static void EmitAssertBoolean(Register reg, | 373 static void EmitAssertBoolean(Register reg, |
| 372 TokenPosition token_pos, | 374 TokenPosition token_pos, |
| 373 intptr_t deopt_id, | 375 intptr_t deopt_id, |
| 374 LocationSummary* locs, | 376 LocationSummary* locs, |
| 375 FlowGraphCompiler* compiler) { | 377 FlowGraphCompiler* compiler) { |
| 376 // Check that the type of the value is allowed in conditional context. | 378 // Check that the type of the value is allowed in conditional context. |
| 377 // Call the runtime if the object is not bool::true or bool::false. | 379 // Call the runtime if the object is not bool::true or bool::false. |
| 378 ASSERT(locs->always_calls()); | 380 ASSERT(locs->always_calls()); |
| 379 Label done; | 381 Label done; |
| 380 | 382 |
| 381 if (Isolate::Current()->type_checks()) { | 383 if (Isolate::Current()->type_checks()) { |
| 382 __ CompareObject(reg, Bool::True()); | 384 __ CompareObject(reg, Bool::True()); |
| 383 __ b(&done, EQ); | 385 __ b(&done, EQ); |
| 384 __ CompareObject(reg, Bool::False()); | 386 __ CompareObject(reg, Bool::False()); |
| 385 __ b(&done, EQ); | 387 __ b(&done, EQ); |
| 386 } else { | 388 } else { |
| 387 ASSERT(Isolate::Current()->asserts()); | 389 ASSERT(Isolate::Current()->asserts()); |
| 388 __ CompareObject(reg, Object::null_instance()); | 390 __ CompareObject(reg, Object::null_instance()); |
| 389 __ b(&done, NE); | 391 __ b(&done, NE); |
| 390 } | 392 } |
| 391 | 393 |
| 392 __ Push(reg); // Push the source object. | 394 __ Push(reg); // Push the source object. |
| 393 compiler->GenerateRuntimeCall(token_pos, | 395 compiler->GenerateRuntimeCall(token_pos, deopt_id, |
| 394 deopt_id, | 396 kNonBoolTypeErrorRuntimeEntry, 1, locs); |
| 395 kNonBoolTypeErrorRuntimeEntry, | |
| 396 1, | |
| 397 locs); | |
| 398 // We should never return here. | 397 // We should never return here. |
| 399 __ bkpt(0); | 398 __ bkpt(0); |
| 400 __ Bind(&done); | 399 __ Bind(&done); |
| 401 } | 400 } |
| 402 | 401 |
| 403 | 402 |
| 404 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 403 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 405 const Register obj = locs()->in(0).reg(); | 404 const Register obj = locs()->in(0).reg(); |
| 406 const Register result = locs()->out(0).reg(); | 405 const Register result = locs()->out(0).reg(); |
| 407 | 406 |
| 408 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 407 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 409 ASSERT(obj == result); | 408 ASSERT(obj == result); |
| 410 } | 409 } |
| 411 | 410 |
| 412 | 411 |
| 413 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 412 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
| 414 switch (kind) { | 413 switch (kind) { |
| 415 case Token::kEQ: return EQ; | 414 case Token::kEQ: |
| 416 case Token::kNE: return NE; | 415 return EQ; |
| 417 case Token::kLT: return LT; | 416 case Token::kNE: |
| 418 case Token::kGT: return GT; | 417 return NE; |
| 419 case Token::kLTE: return LE; | 418 case Token::kLT: |
| 420 case Token::kGTE: return GE; | 419 return LT; |
| 420 case Token::kGT: |
| 421 return GT; |
| 422 case Token::kLTE: |
| 423 return LE; |
| 424 case Token::kGTE: |
| 425 return GE; |
| 421 default: | 426 default: |
| 422 UNREACHABLE(); | 427 UNREACHABLE(); |
| 423 return VS; | 428 return VS; |
| 424 } | 429 } |
| 425 } | 430 } |
| 426 | 431 |
| 427 | 432 |
| 428 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 433 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |
| 429 bool opt) const { | 434 bool opt) const { |
| 430 const intptr_t kNumInputs = 2; | 435 const intptr_t kNumInputs = 2; |
| 431 if (operation_cid() == kMintCid) { | 436 if (operation_cid() == kMintCid) { |
| 432 const intptr_t kNumTemps = 0; | 437 const intptr_t kNumTemps = 0; |
| 433 LocationSummary* locs = new(zone) LocationSummary( | 438 LocationSummary* locs = new (zone) |
| 434 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 439 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 435 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 440 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 436 Location::RequiresRegister())); | 441 Location::RequiresRegister())); |
| 437 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 442 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 438 Location::RequiresRegister())); | 443 Location::RequiresRegister())); |
| 439 locs->set_out(0, Location::RequiresRegister()); | 444 locs->set_out(0, Location::RequiresRegister()); |
| 440 return locs; | 445 return locs; |
| 441 } | 446 } |
| 442 if (operation_cid() == kDoubleCid) { | 447 if (operation_cid() == kDoubleCid) { |
| 443 const intptr_t kNumTemps = 0; | 448 const intptr_t kNumTemps = 0; |
| 444 LocationSummary* locs = new(zone) LocationSummary( | 449 LocationSummary* locs = new (zone) |
| 445 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 450 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 446 locs->set_in(0, Location::RequiresFpuRegister()); | 451 locs->set_in(0, Location::RequiresFpuRegister()); |
| 447 locs->set_in(1, Location::RequiresFpuRegister()); | 452 locs->set_in(1, Location::RequiresFpuRegister()); |
| 448 locs->set_out(0, Location::RequiresRegister()); | 453 locs->set_out(0, Location::RequiresRegister()); |
| 449 return locs; | 454 return locs; |
| 450 } | 455 } |
| 451 if (operation_cid() == kSmiCid) { | 456 if (operation_cid() == kSmiCid) { |
| 452 const intptr_t kNumTemps = 0; | 457 const intptr_t kNumTemps = 0; |
| 453 LocationSummary* locs = new(zone) LocationSummary( | 458 LocationSummary* locs = new (zone) |
| 454 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 459 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 455 locs->set_in(0, Location::RegisterOrConstant(left())); | 460 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 456 // Only one input can be a constant operand. The case of two constant | 461 // Only one input can be a constant operand. The case of two constant |
| 457 // operands should be handled by constant propagation. | 462 // operands should be handled by constant propagation. |
| 458 locs->set_in(1, locs->in(0).IsConstant() | 463 locs->set_in(1, locs->in(0).IsConstant() |
| 459 ? Location::RequiresRegister() | 464 ? Location::RequiresRegister() |
| 460 : Location::RegisterOrConstant(right())); | 465 : Location::RegisterOrConstant(right())); |
| 461 locs->set_out(0, Location::RequiresRegister()); | 466 locs->set_out(0, Location::RequiresRegister()); |
| 462 return locs; | 467 return locs; |
| 463 } | 468 } |
| 464 UNREACHABLE(); | 469 UNREACHABLE(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 478 __ LoadClassId(value_cid_reg, value_reg, NE); | 483 __ LoadClassId(value_cid_reg, value_reg, NE); |
| 479 } else { | 484 } else { |
| 480 __ b(value_is_smi, EQ); | 485 __ b(value_is_smi, EQ); |
| 481 __ LoadClassId(value_cid_reg, value_reg); | 486 __ LoadClassId(value_cid_reg, value_reg); |
| 482 } | 487 } |
| 483 } | 488 } |
| 484 | 489 |
| 485 | 490 |
| 486 static Condition FlipCondition(Condition condition) { | 491 static Condition FlipCondition(Condition condition) { |
| 487 switch (condition) { | 492 switch (condition) { |
| 488 case EQ: return EQ; | 493 case EQ: |
| 489 case NE: return NE; | 494 return EQ; |
| 490 case LT: return GT; | 495 case NE: |
| 491 case LE: return GE; | 496 return NE; |
| 492 case GT: return LT; | 497 case LT: |
| 493 case GE: return LE; | 498 return GT; |
| 494 case CC: return HI; | 499 case LE: |
| 495 case LS: return CS; | 500 return GE; |
| 496 case HI: return CC; | 501 case GT: |
| 497 case CS: return LS; | 502 return LT; |
| 503 case GE: |
| 504 return LE; |
| 505 case CC: |
| 506 return HI; |
| 507 case LS: |
| 508 return CS; |
| 509 case HI: |
| 510 return CC; |
| 511 case CS: |
| 512 return LS; |
| 498 default: | 513 default: |
| 499 UNREACHABLE(); | 514 UNREACHABLE(); |
| 500 return EQ; | 515 return EQ; |
| 501 } | 516 } |
| 502 } | 517 } |
| 503 | 518 |
| 504 | 519 |
| 505 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 520 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 506 Condition true_condition, | 521 Condition true_condition, |
| 507 BranchLabels labels) { | 522 BranchLabels labels) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 537 __ CompareObject(left.reg(), right.constant()); | 552 __ CompareObject(left.reg(), right.constant()); |
| 538 } else { | 553 } else { |
| 539 __ cmp(left.reg(), Operand(right.reg())); | 554 __ cmp(left.reg(), Operand(right.reg())); |
| 540 } | 555 } |
| 541 return true_condition; | 556 return true_condition; |
| 542 } | 557 } |
| 543 | 558 |
| 544 | 559 |
| 545 static Condition TokenKindToMintCondition(Token::Kind kind) { | 560 static Condition TokenKindToMintCondition(Token::Kind kind) { |
| 546 switch (kind) { | 561 switch (kind) { |
| 547 case Token::kEQ: return EQ; | 562 case Token::kEQ: |
| 548 case Token::kNE: return NE; | 563 return EQ; |
| 549 case Token::kLT: return LT; | 564 case Token::kNE: |
| 550 case Token::kGT: return GT; | 565 return NE; |
| 551 case Token::kLTE: return LE; | 566 case Token::kLT: |
| 552 case Token::kGTE: return GE; | 567 return LT; |
| 568 case Token::kGT: |
| 569 return GT; |
| 570 case Token::kLTE: |
| 571 return LE; |
| 572 case Token::kGTE: |
| 573 return GE; |
| 553 default: | 574 default: |
| 554 UNREACHABLE(); | 575 UNREACHABLE(); |
| 555 return VS; | 576 return VS; |
| 556 } | 577 } |
| 557 } | 578 } |
| 558 | 579 |
| 559 | 580 |
| 560 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, | 581 static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler, |
| 561 LocationSummary* locs, | 582 LocationSummary* locs, |
| 562 Token::Kind kind) { | 583 Token::Kind kind) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 616 __ b(labels.false_label, FlipCondition(hi_cond)); | 637 __ b(labels.false_label, FlipCondition(hi_cond)); |
| 617 | 638 |
| 618 // If higher words are equal, compare lower words. | 639 // If higher words are equal, compare lower words. |
| 619 __ cmp(left_lo, Operand(right_lo)); | 640 __ cmp(left_lo, Operand(right_lo)); |
| 620 return lo_cond; | 641 return lo_cond; |
| 621 } | 642 } |
| 622 | 643 |
| 623 | 644 |
| 624 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 645 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 625 switch (kind) { | 646 switch (kind) { |
| 626 case Token::kEQ: return EQ; | 647 case Token::kEQ: |
| 627 case Token::kNE: return NE; | 648 return EQ; |
| 628 case Token::kLT: return LT; | 649 case Token::kNE: |
| 629 case Token::kGT: return GT; | 650 return NE; |
| 630 case Token::kLTE: return LE; | 651 case Token::kLT: |
| 631 case Token::kGTE: return GE; | 652 return LT; |
| 653 case Token::kGT: |
| 654 return GT; |
| 655 case Token::kLTE: |
| 656 return LE; |
| 657 case Token::kGTE: |
| 658 return GE; |
| 632 default: | 659 default: |
| 633 UNREACHABLE(); | 660 UNREACHABLE(); |
| 634 return VS; | 661 return VS; |
| 635 } | 662 } |
| 636 } | 663 } |
| 637 | 664 |
| 638 | 665 |
| 639 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 666 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 640 LocationSummary* locs, | 667 LocationSummary* locs, |
| 641 Token::Kind kind) { | 668 Token::Kind kind) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 660 ASSERT(operation_cid() == kDoubleCid); | 687 ASSERT(operation_cid() == kDoubleCid); |
| 661 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 688 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
| 662 } | 689 } |
| 663 } | 690 } |
| 664 | 691 |
| 665 | 692 |
| 666 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 693 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 667 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 694 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 668 | 695 |
| 669 // The ARM code does not use true- and false-labels here. | 696 // The ARM code does not use true- and false-labels here. |
| 670 BranchLabels labels = { NULL, NULL, NULL }; | 697 BranchLabels labels = {NULL, NULL, NULL}; |
| 671 Condition true_condition = EmitComparisonCode(compiler, labels); | 698 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 672 | 699 |
| 673 const Register result = locs()->out(0).reg(); | 700 const Register result = locs()->out(0).reg(); |
| 674 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { | 701 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
| 675 __ LoadObject(result, Bool::True(), true_condition); | 702 __ LoadObject(result, Bool::True(), true_condition); |
| 676 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 703 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 677 } else { | 704 } else { |
| 678 ASSERT(operation_cid() == kDoubleCid); | 705 ASSERT(operation_cid() == kDoubleCid); |
| 679 Label done; | 706 Label done; |
| 680 __ LoadObject(result, Bool::False()); | 707 __ LoadObject(result, Bool::False()); |
| 681 if (true_condition != NE) { | 708 if (true_condition != NE) { |
| 682 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. | 709 __ b(&done, VS); // x == NaN -> false, x != NaN -> true. |
| 683 } | 710 } |
| 684 __ LoadObject(result, Bool::True(), true_condition); | 711 __ LoadObject(result, Bool::True(), true_condition); |
| 685 __ Bind(&done); | 712 __ Bind(&done); |
| 686 } | 713 } |
| 687 } | 714 } |
| 688 | 715 |
| 689 | 716 |
| 690 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 717 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 691 BranchInstr* branch) { | 718 BranchInstr* branch) { |
| 692 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 719 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 693 | 720 |
| 694 BranchLabels labels = compiler->CreateBranchLabels(branch); | 721 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 695 Condition true_condition = EmitComparisonCode(compiler, labels); | 722 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 696 | 723 |
| 697 if (operation_cid() == kDoubleCid) { | 724 if (operation_cid() == kDoubleCid) { |
| 698 Label* nan_result = (true_condition == NE) ? | 725 Label* nan_result = |
| 699 labels.true_label : labels.false_label; | 726 (true_condition == NE) ? labels.true_label : labels.false_label; |
| 700 __ b(nan_result, VS); | 727 __ b(nan_result, VS); |
| 701 } | 728 } |
| 702 EmitBranchOnCondition(compiler, true_condition, labels); | 729 EmitBranchOnCondition(compiler, true_condition, labels); |
| 703 } | 730 } |
| 704 | 731 |
| 705 | 732 |
| 706 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, | 733 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 707 bool opt) const { | |
| 708 const intptr_t kNumInputs = 2; | 734 const intptr_t kNumInputs = 2; |
| 709 const intptr_t kNumTemps = 0; | 735 const intptr_t kNumTemps = 0; |
| 710 LocationSummary* locs = new(zone) LocationSummary( | 736 LocationSummary* locs = new (zone) |
| 711 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 737 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 712 locs->set_in(0, Location::RequiresRegister()); | 738 locs->set_in(0, Location::RequiresRegister()); |
| 713 // Only one input can be a constant operand. The case of two constant | 739 // Only one input can be a constant operand. The case of two constant |
| 714 // operands should be handled by constant propagation. | 740 // operands should be handled by constant propagation. |
| 715 locs->set_in(1, Location::RegisterOrConstant(right())); | 741 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 716 return locs; | 742 return locs; |
| 717 } | 743 } |
| 718 | 744 |
| 719 | 745 |
| 720 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 746 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 721 BranchLabels labels) { | 747 BranchLabels labels) { |
| 722 const Register left = locs()->in(0).reg(); | 748 const Register left = locs()->in(0).reg(); |
| 723 Location right = locs()->in(1); | 749 Location right = locs()->in(1); |
| 724 if (right.IsConstant()) { | 750 if (right.IsConstant()) { |
| 725 ASSERT(right.constant().IsSmi()); | 751 ASSERT(right.constant().IsSmi()); |
| 726 const int32_t imm = | 752 const int32_t imm = reinterpret_cast<int32_t>(right.constant().raw()); |
| 727 reinterpret_cast<int32_t>(right.constant().raw()); | |
| 728 __ TestImmediate(left, imm); | 753 __ TestImmediate(left, imm); |
| 729 } else { | 754 } else { |
| 730 __ tst(left, Operand(right.reg())); | 755 __ tst(left, Operand(right.reg())); |
| 731 } | 756 } |
| 732 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; | 757 Condition true_condition = (kind() == Token::kNE) ? NE : EQ; |
| 733 return true_condition; | 758 return true_condition; |
| 734 } | 759 } |
| 735 | 760 |
| 736 | 761 |
| 737 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 762 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 738 // Never emitted outside of the BranchInstr. | 763 // Never emitted outside of the BranchInstr. |
| 739 UNREACHABLE(); | 764 UNREACHABLE(); |
| 740 } | 765 } |
| 741 | 766 |
| 742 | 767 |
| 743 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 768 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 744 BranchInstr* branch) { | 769 BranchInstr* branch) { |
| 745 BranchLabels labels = compiler->CreateBranchLabels(branch); | 770 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 746 Condition true_condition = EmitComparisonCode(compiler, labels); | 771 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 747 EmitBranchOnCondition(compiler, true_condition, labels); | 772 EmitBranchOnCondition(compiler, true_condition, labels); |
| 748 } | 773 } |
| 749 | 774 |
| 750 | 775 |
| 751 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 776 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
| 752 bool opt) const { | 777 bool opt) const { |
| 753 const intptr_t kNumInputs = 1; | 778 const intptr_t kNumInputs = 1; |
| 754 const intptr_t kNumTemps = 1; | 779 const intptr_t kNumTemps = 1; |
| 755 LocationSummary* locs = new(zone) LocationSummary( | 780 LocationSummary* locs = new (zone) |
| 756 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 781 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 757 locs->set_in(0, Location::RequiresRegister()); | 782 locs->set_in(0, Location::RequiresRegister()); |
| 758 locs->set_temp(0, Location::RequiresRegister()); | 783 locs->set_temp(0, Location::RequiresRegister()); |
| 759 locs->set_out(0, Location::RequiresRegister()); | 784 locs->set_out(0, Location::RequiresRegister()); |
| 760 return locs; | 785 return locs; |
| 761 } | 786 } |
| 762 | 787 |
| 763 | 788 |
| 764 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 789 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 765 BranchLabels labels) { | 790 BranchLabels labels) { |
| 766 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 791 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
| 767 const Register val_reg = locs()->in(0).reg(); | 792 const Register val_reg = locs()->in(0).reg(); |
| 768 const Register cid_reg = locs()->temp(0).reg(); | 793 const Register cid_reg = locs()->temp(0).reg(); |
| 769 | 794 |
| 770 Label* deopt = CanDeoptimize() | 795 Label* deopt = |
| 771 ? compiler->AddDeoptStub(deopt_id(), | 796 CanDeoptimize() |
| 772 ICData::kDeoptTestCids, | 797 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, |
| 773 licm_hoisted_ ? ICData::kHoisted : 0) | 798 licm_hoisted_ ? ICData::kHoisted : 0) |
| 774 : NULL; | 799 : NULL; |
| 775 | 800 |
| 776 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 801 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
| 777 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 802 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
| 778 ASSERT(data[0] == kSmiCid); | 803 ASSERT(data[0] == kSmiCid); |
| 779 bool result = data[1] == true_result; | 804 bool result = data[1] == true_result; |
| 780 __ tst(val_reg, Operand(kSmiTagMask)); | 805 __ tst(val_reg, Operand(kSmiTagMask)); |
| 781 __ b(result ? labels.true_label : labels.false_label, EQ); | 806 __ b(result ? labels.true_label : labels.false_label, EQ); |
| 782 __ LoadClassId(cid_reg, val_reg); | 807 __ LoadClassId(cid_reg, val_reg); |
| 783 | 808 |
| 784 for (intptr_t i = 2; i < data.length(); i += 2) { | 809 for (intptr_t i = 2; i < data.length(); i += 2) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 806 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 831 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 807 BranchInstr* branch) { | 832 BranchInstr* branch) { |
| 808 BranchLabels labels = compiler->CreateBranchLabels(branch); | 833 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 809 EmitComparisonCode(compiler, labels); | 834 EmitComparisonCode(compiler, labels); |
| 810 } | 835 } |
| 811 | 836 |
| 812 | 837 |
| 813 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 838 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 814 const Register result_reg = locs()->out(0).reg(); | 839 const Register result_reg = locs()->out(0).reg(); |
| 815 Label is_true, is_false, done; | 840 Label is_true, is_false, done; |
| 816 BranchLabels labels = { &is_true, &is_false, &is_false }; | 841 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 817 EmitComparisonCode(compiler, labels); | 842 EmitComparisonCode(compiler, labels); |
| 818 __ Bind(&is_false); | 843 __ Bind(&is_false); |
| 819 __ LoadObject(result_reg, Bool::False()); | 844 __ LoadObject(result_reg, Bool::False()); |
| 820 __ b(&done); | 845 __ b(&done); |
| 821 __ Bind(&is_true); | 846 __ Bind(&is_true); |
| 822 __ LoadObject(result_reg, Bool::True()); | 847 __ LoadObject(result_reg, Bool::True()); |
| 823 __ Bind(&done); | 848 __ Bind(&done); |
| 824 } | 849 } |
| 825 | 850 |
| 826 | 851 |
| 827 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 852 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
| 828 bool opt) const { | 853 bool opt) const { |
| 829 const intptr_t kNumInputs = 2; | 854 const intptr_t kNumInputs = 2; |
| 830 const intptr_t kNumTemps = 0; | 855 const intptr_t kNumTemps = 0; |
| 831 if (operation_cid() == kMintCid) { | 856 if (operation_cid() == kMintCid) { |
| 832 const intptr_t kNumTemps = 0; | 857 const intptr_t kNumTemps = 0; |
| 833 LocationSummary* locs = new(zone) LocationSummary( | 858 LocationSummary* locs = new (zone) |
| 834 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 859 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 835 locs->set_in(0, Location::Pair(Location::RequiresRegister(), | 860 locs->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 836 Location::RequiresRegister())); | 861 Location::RequiresRegister())); |
| 837 locs->set_in(1, Location::Pair(Location::RequiresRegister(), | 862 locs->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 838 Location::RequiresRegister())); | 863 Location::RequiresRegister())); |
| 839 locs->set_out(0, Location::RequiresRegister()); | 864 locs->set_out(0, Location::RequiresRegister()); |
| 840 return locs; | 865 return locs; |
| 841 } | 866 } |
| 842 if (operation_cid() == kDoubleCid) { | 867 if (operation_cid() == kDoubleCid) { |
| 843 LocationSummary* summary = new(zone) LocationSummary( | 868 LocationSummary* summary = new (zone) |
| 844 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 869 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 845 summary->set_in(0, Location::RequiresFpuRegister()); | 870 summary->set_in(0, Location::RequiresFpuRegister()); |
| 846 summary->set_in(1, Location::RequiresFpuRegister()); | 871 summary->set_in(1, Location::RequiresFpuRegister()); |
| 847 summary->set_out(0, Location::RequiresRegister()); | 872 summary->set_out(0, Location::RequiresRegister()); |
| 848 return summary; | 873 return summary; |
| 849 } | 874 } |
| 850 ASSERT(operation_cid() == kSmiCid); | 875 ASSERT(operation_cid() == kSmiCid); |
| 851 LocationSummary* summary = new(zone) LocationSummary( | 876 LocationSummary* summary = new (zone) |
| 852 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 877 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 853 summary->set_in(0, Location::RegisterOrConstant(left())); | 878 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 854 // Only one input can be a constant operand. The case of two constant | 879 // Only one input can be a constant operand. The case of two constant |
| 855 // operands should be handled by constant propagation. | 880 // operands should be handled by constant propagation. |
| 856 summary->set_in(1, summary->in(0).IsConstant() | 881 summary->set_in(1, summary->in(0).IsConstant() |
| 857 ? Location::RequiresRegister() | 882 ? Location::RequiresRegister() |
| 858 : Location::RegisterOrConstant(right())); | 883 : Location::RegisterOrConstant(right())); |
| 859 summary->set_out(0, Location::RequiresRegister()); | 884 summary->set_out(0, Location::RequiresRegister()); |
| 860 return summary; | 885 return summary; |
| 861 } | 886 } |
| 862 | 887 |
| 863 | 888 |
| 864 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 889 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 865 BranchLabels labels) { | 890 BranchLabels labels) { |
| 866 if (operation_cid() == kSmiCid) { | 891 if (operation_cid() == kSmiCid) { |
| 867 return EmitSmiComparisonOp(compiler, locs(), kind()); | 892 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 868 } else if (operation_cid() == kMintCid) { | 893 } else if (operation_cid() == kMintCid) { |
| 869 return EmitUnboxedMintComparisonOp(compiler, locs(), kind(), labels); | 894 return EmitUnboxedMintComparisonOp(compiler, locs(), kind(), labels); |
| 870 } else { | 895 } else { |
| 871 ASSERT(operation_cid() == kDoubleCid); | 896 ASSERT(operation_cid() == kDoubleCid); |
| 872 return EmitDoubleComparisonOp(compiler, locs(), kind()); | 897 return EmitDoubleComparisonOp(compiler, locs(), kind()); |
| 873 } | 898 } |
| 874 } | 899 } |
| 875 | 900 |
| 876 | 901 |
| 877 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 902 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 878 Label is_true, is_false; | 903 Label is_true, is_false; |
| 879 BranchLabels labels = { &is_true, &is_false, &is_false }; | 904 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 880 Condition true_condition = EmitComparisonCode(compiler, labels); | 905 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 881 | 906 |
| 882 const Register result = locs()->out(0).reg(); | 907 const Register result = locs()->out(0).reg(); |
| 883 if (operation_cid() == kSmiCid) { | 908 if (operation_cid() == kSmiCid) { |
| 884 __ LoadObject(result, Bool::True(), true_condition); | 909 __ LoadObject(result, Bool::True(), true_condition); |
| 885 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 910 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 886 } else if (operation_cid() == kMintCid) { | 911 } else if (operation_cid() == kMintCid) { |
| 887 EmitBranchOnCondition(compiler, true_condition, labels); | 912 EmitBranchOnCondition(compiler, true_condition, labels); |
| 888 Label done; | 913 Label done; |
| 889 __ Bind(&is_false); | 914 __ Bind(&is_false); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 906 | 931 |
| 907 | 932 |
| 908 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 933 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 909 BranchInstr* branch) { | 934 BranchInstr* branch) { |
| 910 BranchLabels labels = compiler->CreateBranchLabels(branch); | 935 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 911 Condition true_condition = EmitComparisonCode(compiler, labels); | 936 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 912 | 937 |
| 913 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { | 938 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
| 914 EmitBranchOnCondition(compiler, true_condition, labels); | 939 EmitBranchOnCondition(compiler, true_condition, labels); |
| 915 } else if (operation_cid() == kDoubleCid) { | 940 } else if (operation_cid() == kDoubleCid) { |
| 916 Label* nan_result = (true_condition == NE) ? | 941 Label* nan_result = |
| 917 labels.true_label : labels.false_label; | 942 (true_condition == NE) ? labels.true_label : labels.false_label; |
| 918 __ b(nan_result, VS); | 943 __ b(nan_result, VS); |
| 919 EmitBranchOnCondition(compiler, true_condition, labels); | 944 EmitBranchOnCondition(compiler, true_condition, labels); |
| 920 } | 945 } |
| 921 } | 946 } |
| 922 | 947 |
| 923 | 948 |
| 924 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, | 949 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, |
| 925 bool opt) const { | 950 bool opt) const { |
| 926 return MakeCallSummary(zone); | 951 return MakeCallSummary(zone); |
| 927 } | 952 } |
| 928 | 953 |
| 929 | 954 |
| 930 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 955 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 931 SetupNative(); | 956 SetupNative(); |
| 932 const Register result = locs()->out(0).reg(); | 957 const Register result = locs()->out(0).reg(); |
| 933 | 958 |
| 934 // Push the result place holder initialized to NULL. | 959 // Push the result place holder initialized to NULL. |
| 935 __ PushObject(Object::null_object()); | 960 __ PushObject(Object::null_object()); |
| 936 // Pass a pointer to the first argument in R2. | 961 // Pass a pointer to the first argument in R2. |
| 937 if (!function().HasOptionalParameters()) { | 962 if (!function().HasOptionalParameters()) { |
| 938 __ AddImmediate(R2, FP, (kParamEndSlotFromFp + | 963 __ AddImmediate( |
| 939 function().NumParameters()) * kWordSize); | 964 R2, FP, (kParamEndSlotFromFp + function().NumParameters()) * kWordSize); |
| 940 } else { | 965 } else { |
| 941 __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize); | 966 __ AddImmediate(R2, FP, kFirstLocalSlotFromFp * kWordSize); |
| 942 } | 967 } |
| 943 // Compute the effective address. When running under the simulator, | 968 // Compute the effective address. When running under the simulator, |
| 944 // this is a redirection address that forces the simulator to call | 969 // this is a redirection address that forces the simulator to call |
| 945 // into the runtime system. | 970 // into the runtime system. |
| 946 uword entry; | 971 uword entry; |
| 947 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 972 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
| 948 const StubEntry* stub_entry; | 973 const StubEntry* stub_entry; |
| 949 if (link_lazily()) { | 974 if (link_lazily()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 960 } else { | 985 } else { |
| 961 // In the case of non bootstrap native methods the CallNativeCFunction | 986 // In the case of non bootstrap native methods the CallNativeCFunction |
| 962 // stub generates the redirection address when running under the simulator | 987 // stub generates the redirection address when running under the simulator |
| 963 // and hence we do not change 'entry' here. | 988 // and hence we do not change 'entry' here. |
| 964 stub_entry = StubCode::CallNativeCFunction_entry(); | 989 stub_entry = StubCode::CallNativeCFunction_entry(); |
| 965 } | 990 } |
| 966 } | 991 } |
| 967 __ LoadImmediate(R1, argc_tag); | 992 __ LoadImmediate(R1, argc_tag); |
| 968 ExternalLabel label(entry); | 993 ExternalLabel label(entry); |
| 969 __ LoadNativeEntry(R9, &label, link_lazily() ? kPatchable : kNotPatchable); | 994 __ LoadNativeEntry(R9, &label, link_lazily() ? kPatchable : kNotPatchable); |
| 970 compiler->GenerateCall(token_pos(), | 995 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, |
| 971 *stub_entry, | |
| 972 RawPcDescriptors::kOther, | |
| 973 locs()); | 996 locs()); |
| 974 __ Pop(result); | 997 __ Pop(result); |
| 975 } | 998 } |
| 976 | 999 |
| 977 | 1000 |
| 978 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 1001 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |
| 979 Zone* zone, bool opt) const { | 1002 Zone* zone, |
| 1003 bool opt) const { |
| 980 const intptr_t kNumInputs = 1; | 1004 const intptr_t kNumInputs = 1; |
| 981 // TODO(fschneider): Allow immediate operands for the char code. | 1005 // TODO(fschneider): Allow immediate operands for the char code. |
| 982 return LocationSummary::Make(zone, | 1006 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 983 kNumInputs, | |
| 984 Location::RequiresRegister(), | |
| 985 LocationSummary::kNoCall); | 1007 LocationSummary::kNoCall); |
| 986 } | 1008 } |
| 987 | 1009 |
| 988 | 1010 |
| 989 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 1011 void OneByteStringFromCharCodeInstr::EmitNativeCode( |
| 990 FlowGraphCompiler* compiler) { | 1012 FlowGraphCompiler* compiler) { |
| 991 ASSERT(compiler->is_optimizing()); | 1013 ASSERT(compiler->is_optimizing()); |
| 992 const Register char_code = locs()->in(0).reg(); | 1014 const Register char_code = locs()->in(0).reg(); |
| 993 const Register result = locs()->out(0).reg(); | 1015 const Register result = locs()->out(0).reg(); |
| 994 | 1016 |
| 995 __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset())); | 1017 __ ldr(result, Address(THR, Thread::predefined_symbols_address_offset())); |
| 996 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); | 1018 __ AddImmediate(result, Symbols::kNullCharCodeSymbolOffset * kWordSize); |
| 997 __ ldr(result, Address(result, char_code, LSL, 1)); // Char code is a smi. | 1019 __ ldr(result, Address(result, char_code, LSL, 1)); // Char code is a smi. |
| 998 } | 1020 } |
| 999 | 1021 |
| 1000 | 1022 |
| 1001 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 1023 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
| 1002 bool opt) const { | 1024 bool opt) const { |
| 1003 const intptr_t kNumInputs = 1; | 1025 const intptr_t kNumInputs = 1; |
| 1004 return LocationSummary::Make(zone, | 1026 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 1005 kNumInputs, | |
| 1006 Location::RequiresRegister(), | |
| 1007 LocationSummary::kNoCall); | 1027 LocationSummary::kNoCall); |
| 1008 } | 1028 } |
| 1009 | 1029 |
| 1010 | 1030 |
| 1011 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1031 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1012 ASSERT(cid_ == kOneByteStringCid); | 1032 ASSERT(cid_ == kOneByteStringCid); |
| 1013 const Register str = locs()->in(0).reg(); | 1033 const Register str = locs()->in(0).reg(); |
| 1014 const Register result = locs()->out(0).reg(); | 1034 const Register result = locs()->out(0).reg(); |
| 1015 __ ldr(result, FieldAddress(str, String::length_offset())); | 1035 __ ldr(result, FieldAddress(str, String::length_offset())); |
| 1016 __ cmp(result, Operand(Smi::RawValue(1))); | 1036 __ cmp(result, Operand(Smi::RawValue(1))); |
| 1017 __ LoadImmediate(result, -1, NE); | 1037 __ LoadImmediate(result, -1, NE); |
| 1018 __ ldrb(result, FieldAddress(str, OneByteString::data_offset()), EQ); | 1038 __ ldrb(result, FieldAddress(str, OneByteString::data_offset()), EQ); |
| 1019 __ SmiTag(result); | 1039 __ SmiTag(result); |
| 1020 } | 1040 } |
| 1021 | 1041 |
| 1022 | 1042 |
| 1023 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 1043 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |
| 1024 bool opt) const { | 1044 bool opt) const { |
| 1025 const intptr_t kNumInputs = 1; | 1045 const intptr_t kNumInputs = 1; |
| 1026 const intptr_t kNumTemps = 0; | 1046 const intptr_t kNumTemps = 0; |
| 1027 LocationSummary* summary = new(zone) LocationSummary( | 1047 LocationSummary* summary = new (zone) |
| 1028 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 1048 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1029 summary->set_in(0, Location::RegisterLocation(R0)); | 1049 summary->set_in(0, Location::RegisterLocation(R0)); |
| 1030 summary->set_out(0, Location::RegisterLocation(R0)); | 1050 summary->set_out(0, Location::RegisterLocation(R0)); |
| 1031 return summary; | 1051 return summary; |
| 1032 } | 1052 } |
| 1033 | 1053 |
| 1034 | 1054 |
| 1035 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1055 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1036 const Register array = locs()->in(0).reg(); | 1056 const Register array = locs()->in(0).reg(); |
| 1037 __ Push(array); | 1057 __ Push(array); |
| 1038 const int kNumberOfArguments = 1; | 1058 const int kNumberOfArguments = 1; |
| 1039 const Array& kNoArgumentNames = Object::null_array(); | 1059 const Array& kNoArgumentNames = Object::null_array(); |
| 1040 compiler->GenerateStaticCall(deopt_id(), | 1060 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), |
| 1041 token_pos(), | 1061 kNumberOfArguments, kNoArgumentNames, locs(), |
| 1042 CallFunction(), | |
| 1043 kNumberOfArguments, | |
| 1044 kNoArgumentNames, | |
| 1045 locs(), | |
| 1046 ICData::Handle()); | 1062 ICData::Handle()); |
| 1047 ASSERT(locs()->out(0).reg() == R0); | 1063 ASSERT(locs()->out(0).reg() == R0); |
| 1048 } | 1064 } |
| 1049 | 1065 |
| 1050 | 1066 |
| 1051 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 1067 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |
| 1052 bool opt) const { | 1068 bool opt) const { |
| 1053 const intptr_t kNumInputs = 1; | 1069 const intptr_t kNumInputs = 1; |
| 1054 return LocationSummary::Make(zone, | 1070 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 1055 kNumInputs, | |
| 1056 Location::RequiresRegister(), | |
| 1057 LocationSummary::kNoCall); | 1071 LocationSummary::kNoCall); |
| 1058 } | 1072 } |
| 1059 | 1073 |
| 1060 | 1074 |
| 1061 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1075 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1062 const Register obj = locs()->in(0).reg(); | 1076 const Register obj = locs()->in(0).reg(); |
| 1063 const Register result = locs()->out(0).reg(); | 1077 const Register result = locs()->out(0).reg(); |
| 1064 if (object()->definition()->representation() == kUntagged) { | 1078 if (object()->definition()->representation() == kUntagged) { |
| 1065 __ LoadFromOffset(kWord, result, obj, offset()); | 1079 __ LoadFromOffset(kWord, result, obj, offset()); |
| 1066 } else { | 1080 } else { |
| 1067 ASSERT(object()->definition()->representation() == kTagged); | 1081 ASSERT(object()->definition()->representation() == kTagged); |
| 1068 __ LoadFieldFromOffset(kWord, result, obj, offset()); | 1082 __ LoadFieldFromOffset(kWord, result, obj, offset()); |
| 1069 } | 1083 } |
| 1070 } | 1084 } |
| 1071 | 1085 |
| 1072 | 1086 |
| 1073 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 1087 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |
| 1074 bool opt) const { | 1088 bool opt) const { |
| 1075 const intptr_t kNumInputs = 1; | 1089 const intptr_t kNumInputs = 1; |
| 1076 return LocationSummary::Make(zone, | 1090 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 1077 kNumInputs, | |
| 1078 Location::RequiresRegister(), | |
| 1079 LocationSummary::kNoCall); | 1091 LocationSummary::kNoCall); |
| 1080 } | 1092 } |
| 1081 | 1093 |
| 1082 | 1094 |
| 1083 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1095 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1084 const Register object = locs()->in(0).reg(); | 1096 const Register object = locs()->in(0).reg(); |
| 1085 const Register result = locs()->out(0).reg(); | 1097 const Register result = locs()->out(0).reg(); |
| 1086 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 1098 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |
| 1087 if (CompileType::Smi().IsAssignableTo(value_type) || | 1099 if (CompileType::Smi().IsAssignableTo(value_type) || |
| 1088 value_type.IsTypeParameter()) { | 1100 value_type.IsTypeParameter()) { |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1205 } | 1217 } |
| 1206 | 1218 |
| 1207 return false; | 1219 return false; |
| 1208 } | 1220 } |
| 1209 | 1221 |
| 1210 | 1222 |
| 1211 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 1223 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1212 bool opt) const { | 1224 bool opt) const { |
| 1213 const intptr_t kNumInputs = 2; | 1225 const intptr_t kNumInputs = 2; |
| 1214 const intptr_t kNumTemps = aligned() ? 0 : 1; | 1226 const intptr_t kNumTemps = aligned() ? 0 : 1; |
| 1215 LocationSummary* locs = new(zone) LocationSummary( | 1227 LocationSummary* locs = new (zone) |
| 1216 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1228 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1217 locs->set_in(0, Location::RequiresRegister()); | 1229 locs->set_in(0, Location::RequiresRegister()); |
| 1218 bool needs_base = false; | 1230 bool needs_base = false; |
| 1219 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), | 1231 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), |
| 1220 true, // Load. | 1232 true, // Load. |
| 1221 &needs_base)) { | 1233 &needs_base)) { |
| 1222 // CanBeImmediateIndex must return false for unsafe smis. | 1234 // CanBeImmediateIndex must return false for unsafe smis. |
| 1223 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1235 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
| 1224 } else { | 1236 } else { |
| 1225 locs->set_in(1, Location::RequiresRegister()); | 1237 locs->set_in(1, Location::RequiresRegister()); |
| 1226 } | 1238 } |
| 1227 if ((representation() == kUnboxedDouble) || | 1239 if ((representation() == kUnboxedDouble) || |
| 1228 (representation() == kUnboxedFloat32x4) || | 1240 (representation() == kUnboxedFloat32x4) || |
| 1229 (representation() == kUnboxedInt32x4) || | 1241 (representation() == kUnboxedInt32x4) || |
| 1230 (representation() == kUnboxedFloat64x2)) { | 1242 (representation() == kUnboxedFloat64x2)) { |
| 1231 if (class_id() == kTypedDataFloat32ArrayCid) { | 1243 if (class_id() == kTypedDataFloat32ArrayCid) { |
| 1232 // Need register <= Q7 for float operations. | 1244 // Need register <= Q7 for float operations. |
| 1233 // TODO(fschneider): Add a register policy to specify a subset of | 1245 // TODO(fschneider): Add a register policy to specify a subset of |
| 1234 // registers. | 1246 // registers. |
| 1235 locs->set_out(0, Location::FpuRegisterLocation(Q7)); | 1247 locs->set_out(0, Location::FpuRegisterLocation(Q7)); |
| 1236 } else { | 1248 } else { |
| 1237 locs->set_out(0, Location::RequiresFpuRegister()); | 1249 locs->set_out(0, Location::RequiresFpuRegister()); |
| 1238 } | 1250 } |
| 1239 } else if (representation() == kUnboxedUint32) { | 1251 } else if (representation() == kUnboxedUint32) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1255 | 1267 |
| 1256 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1268 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1257 // The array register points to the backing store for external arrays. | 1269 // The array register points to the backing store for external arrays. |
| 1258 const Register array = locs()->in(0).reg(); | 1270 const Register array = locs()->in(0).reg(); |
| 1259 const Location index = locs()->in(1); | 1271 const Location index = locs()->in(1); |
| 1260 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); | 1272 const Register address = aligned() ? kNoRegister : locs()->temp(0).reg(); |
| 1261 | 1273 |
| 1262 Address element_address(kNoRegister); | 1274 Address element_address(kNoRegister); |
| 1263 if (aligned()) { | 1275 if (aligned()) { |
| 1264 element_address = index.IsRegister() | 1276 element_address = index.IsRegister() |
| 1265 ? __ ElementAddressForRegIndex(true, // Load. | 1277 ? __ ElementAddressForRegIndex( |
| 1266 IsExternal(), class_id(), index_scale(), | 1278 true, // Load. |
| 1267 array, | 1279 IsExternal(), class_id(), index_scale(), array, |
| 1268 index.reg()) | 1280 index.reg()) |
| 1269 : __ ElementAddressForIntIndex(true, // Load. | 1281 : __ ElementAddressForIntIndex( |
| 1270 IsExternal(), class_id(), index_scale(), | 1282 true, // Load. |
| 1271 array, Smi::Cast(index.constant()).Value(), | 1283 IsExternal(), class_id(), index_scale(), array, |
| 1272 IP); // Temp register. | 1284 Smi::Cast(index.constant()).Value(), |
| 1285 IP); // Temp register. |
| 1273 // Warning: element_address may use register IP as base. | 1286 // Warning: element_address may use register IP as base. |
| 1274 } else { | 1287 } else { |
| 1275 if (index.IsRegister()) { | 1288 if (index.IsRegister()) { |
| 1276 __ LoadElementAddressForRegIndex(address, | 1289 __ LoadElementAddressForRegIndex(address, |
| 1277 true, // Load. | 1290 true, // Load. |
| 1278 IsExternal(), class_id(), index_scale(), | 1291 IsExternal(), class_id(), index_scale(), |
| 1279 array, | 1292 array, index.reg()); |
| 1280 index.reg()); | |
| 1281 } else { | 1293 } else { |
| 1282 __ LoadElementAddressForIntIndex(address, | 1294 __ LoadElementAddressForIntIndex(address, |
| 1283 true, // Load. | 1295 true, // Load. |
| 1284 IsExternal(), class_id(), index_scale(), | 1296 IsExternal(), class_id(), index_scale(), |
| 1285 array, | 1297 array, |
| 1286 Smi::Cast(index.constant()).Value()); | 1298 Smi::Cast(index.constant()).Value()); |
| 1287 } | 1299 } |
| 1288 } | 1300 } |
| 1289 | 1301 |
| 1290 if ((representation() == kUnboxedDouble) || | 1302 if ((representation() == kUnboxedDouble) || |
| 1291 (representation() == kUnboxedFloat32x4) || | 1303 (representation() == kUnboxedFloat32x4) || |
| 1292 (representation() == kUnboxedInt32x4) || | 1304 (representation() == kUnboxedInt32x4) || |
| 1293 (representation() == kUnboxedFloat64x2)) { | 1305 (representation() == kUnboxedFloat64x2)) { |
| 1294 const QRegister result = locs()->out(0).fpu_reg(); | 1306 const QRegister result = locs()->out(0).fpu_reg(); |
| 1295 const DRegister dresult0 = EvenDRegisterOf(result); | 1307 const DRegister dresult0 = EvenDRegisterOf(result); |
| 1296 switch (class_id()) { | 1308 switch (class_id()) { |
| 1297 case kTypedDataFloat32ArrayCid: | 1309 case kTypedDataFloat32ArrayCid: |
| 1298 // Load single precision float. | 1310 // Load single precision float. |
| 1299 // vldrs does not support indexed addressing. | 1311 // vldrs does not support indexed addressing. |
| 1300 __ vldrs(EvenSRegisterOf(dresult0), element_address); | 1312 __ vldrs(EvenSRegisterOf(dresult0), element_address); |
| 1301 break; | 1313 break; |
| 1302 case kTypedDataFloat64ArrayCid: | 1314 case kTypedDataFloat64ArrayCid: |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1319 (representation() == kUnboxedInt32)) { | 1331 (representation() == kUnboxedInt32)) { |
| 1320 Register result = locs()->out(0).reg(); | 1332 Register result = locs()->out(0).reg(); |
| 1321 switch (class_id()) { | 1333 switch (class_id()) { |
| 1322 case kTypedDataInt32ArrayCid: | 1334 case kTypedDataInt32ArrayCid: |
| 1323 ASSERT(representation() == kUnboxedInt32); | 1335 ASSERT(representation() == kUnboxedInt32); |
| 1324 if (aligned()) { | 1336 if (aligned()) { |
| 1325 __ ldr(result, element_address); | 1337 __ ldr(result, element_address); |
| 1326 } else { | 1338 } else { |
| 1327 __ LoadWordUnaligned(result, address, TMP); | 1339 __ LoadWordUnaligned(result, address, TMP); |
| 1328 } | 1340 } |
| 1329 break; | 1341 break; |
| 1330 case kTypedDataUint32ArrayCid: | 1342 case kTypedDataUint32ArrayCid: |
| 1331 ASSERT(representation() == kUnboxedUint32); | 1343 ASSERT(representation() == kUnboxedUint32); |
| 1332 if (aligned()) { | 1344 if (aligned()) { |
| 1333 __ ldr(result, element_address); | 1345 __ ldr(result, element_address); |
| 1334 } else { | 1346 } else { |
| 1335 __ LoadWordUnaligned(result, address, TMP); | 1347 __ LoadWordUnaligned(result, address, TMP); |
| 1336 } | 1348 } |
| 1337 break; | 1349 break; |
| 1338 default: | 1350 default: |
| 1339 UNREACHABLE(); | 1351 UNREACHABLE(); |
| 1340 } | 1352 } |
| 1341 return; | 1353 return; |
| 1342 } | 1354 } |
| 1343 | 1355 |
| 1344 ASSERT(representation() == kTagged); | 1356 ASSERT(representation() == kTagged); |
| 1345 | 1357 |
| 1346 const Register result = locs()->out(0).reg(); | 1358 const Register result = locs()->out(0).reg(); |
| 1347 switch (class_id()) { | 1359 switch (class_id()) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1384 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1396 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1385 __ ldr(result, element_address); | 1397 __ ldr(result, element_address); |
| 1386 break; | 1398 break; |
| 1387 } | 1399 } |
| 1388 } | 1400 } |
| 1389 | 1401 |
| 1390 | 1402 |
| 1391 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1403 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 1392 intptr_t idx) const { | 1404 intptr_t idx) const { |
| 1393 // Array can be a Dart object or a pointer to external data. | 1405 // Array can be a Dart object or a pointer to external data. |
| 1394 if (idx == 0) return kNoRepresentation; // Flexible input representation. | 1406 if (idx == 0) return kNoRepresentation; // Flexible input representation. |
| 1395 if (idx == 1) return kTagged; // Index is a smi. | 1407 if (idx == 1) return kTagged; // Index is a smi. |
| 1396 ASSERT(idx == 2); | 1408 ASSERT(idx == 2); |
| 1397 switch (class_id_) { | 1409 switch (class_id_) { |
| 1398 case kArrayCid: | 1410 case kArrayCid: |
| 1399 case kOneByteStringCid: | 1411 case kOneByteStringCid: |
| 1400 case kTypedDataInt8ArrayCid: | 1412 case kTypedDataInt8ArrayCid: |
| 1401 case kTypedDataUint8ArrayCid: | 1413 case kTypedDataUint8ArrayCid: |
| 1402 case kExternalTypedDataUint8ArrayCid: | 1414 case kExternalTypedDataUint8ArrayCid: |
| 1403 case kTypedDataUint8ClampedArrayCid: | 1415 case kTypedDataUint8ClampedArrayCid: |
| 1404 case kExternalTypedDataUint8ClampedArrayCid: | 1416 case kExternalTypedDataUint8ClampedArrayCid: |
| 1405 case kTypedDataInt16ArrayCid: | 1417 case kTypedDataInt16ArrayCid: |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1428 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1440 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1429 bool opt) const { | 1441 bool opt) const { |
| 1430 const intptr_t kNumInputs = 3; | 1442 const intptr_t kNumInputs = 3; |
| 1431 LocationSummary* locs; | 1443 LocationSummary* locs; |
| 1432 | 1444 |
| 1433 bool needs_base = false; | 1445 bool needs_base = false; |
| 1434 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), | 1446 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), |
| 1435 false, // Store. | 1447 false, // Store. |
| 1436 &needs_base)) { | 1448 &needs_base)) { |
| 1437 const intptr_t kNumTemps = aligned() ? (needs_base ? 1 : 0) : 2; | 1449 const intptr_t kNumTemps = aligned() ? (needs_base ? 1 : 0) : 2; |
| 1438 locs = new(zone) LocationSummary( | 1450 locs = new (zone) |
| 1439 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1451 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1440 | 1452 |
| 1441 // CanBeImmediateIndex must return false for unsafe smis. | 1453 // CanBeImmediateIndex must return false for unsafe smis. |
| 1442 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); | 1454 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
| 1443 if (needs_base) { | 1455 if (needs_base) { |
| 1444 locs->set_temp(0, Location::RequiresRegister()); | 1456 locs->set_temp(0, Location::RequiresRegister()); |
| 1445 } | 1457 } |
| 1446 if (!aligned()) { | 1458 if (!aligned()) { |
| 1447 locs->set_temp(0, Location::RequiresRegister()); | 1459 locs->set_temp(0, Location::RequiresRegister()); |
| 1448 locs->set_temp(1, Location::RequiresRegister()); | 1460 locs->set_temp(1, Location::RequiresRegister()); |
| 1449 } | 1461 } |
| 1450 } else { | 1462 } else { |
| 1451 const intptr_t kNumTemps = aligned() ? 0 : 2; | 1463 const intptr_t kNumTemps = aligned() ? 0 : 2; |
| 1452 locs = new(zone) LocationSummary( | 1464 locs = new (zone) |
| 1453 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1465 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1454 | 1466 |
| 1455 locs->set_in(1, Location::WritableRegister()); | 1467 locs->set_in(1, Location::WritableRegister()); |
| 1456 if (!aligned()) { | 1468 if (!aligned()) { |
| 1457 locs->set_temp(0, Location::RequiresRegister()); | 1469 locs->set_temp(0, Location::RequiresRegister()); |
| 1458 locs->set_temp(1, Location::RequiresRegister()); | 1470 locs->set_temp(1, Location::RequiresRegister()); |
| 1459 } | 1471 } |
| 1460 } | 1472 } |
| 1461 locs->set_in(0, Location::RequiresRegister()); | 1473 locs->set_in(0, Location::RequiresRegister()); |
| 1462 | 1474 |
| 1463 switch (class_id()) { | 1475 switch (class_id()) { |
| 1464 case kArrayCid: | 1476 case kArrayCid: |
| 1465 locs->set_in(2, ShouldEmitStoreBarrier() | 1477 locs->set_in(2, ShouldEmitStoreBarrier() |
| 1466 ? Location::WritableRegister() | 1478 ? Location::WritableRegister() |
| 1467 : Location::RegisterOrConstant(value())); | 1479 : Location::RegisterOrConstant(value())); |
| 1468 break; | 1480 break; |
| 1469 case kExternalTypedDataUint8ArrayCid: | 1481 case kExternalTypedDataUint8ArrayCid: |
| 1470 case kExternalTypedDataUint8ClampedArrayCid: | 1482 case kExternalTypedDataUint8ClampedArrayCid: |
| 1471 case kTypedDataInt8ArrayCid: | 1483 case kTypedDataInt8ArrayCid: |
| 1472 case kTypedDataUint8ArrayCid: | 1484 case kTypedDataUint8ArrayCid: |
| 1473 case kTypedDataUint8ClampedArrayCid: | 1485 case kTypedDataUint8ClampedArrayCid: |
| 1474 case kOneByteStringCid: | 1486 case kOneByteStringCid: |
| 1475 case kTypedDataInt16ArrayCid: | 1487 case kTypedDataInt16ArrayCid: |
| 1476 case kTypedDataUint16ArrayCid: | 1488 case kTypedDataUint16ArrayCid: |
| 1477 case kTypedDataInt32ArrayCid: | 1489 case kTypedDataInt32ArrayCid: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1501 const Register array = locs()->in(0).reg(); | 1513 const Register array = locs()->in(0).reg(); |
| 1502 const Location index = locs()->in(1); | 1514 const Location index = locs()->in(1); |
| 1503 const Register temp = | 1515 const Register temp = |
| 1504 (locs()->temp_count() > 0) ? locs()->temp(0).reg() : kNoRegister; | 1516 (locs()->temp_count() > 0) ? locs()->temp(0).reg() : kNoRegister; |
| 1505 const Register temp2 = | 1517 const Register temp2 = |
| 1506 (locs()->temp_count() > 1) ? locs()->temp(1).reg() : kNoRegister; | 1518 (locs()->temp_count() > 1) ? locs()->temp(1).reg() : kNoRegister; |
| 1507 | 1519 |
| 1508 Address element_address(kNoRegister); | 1520 Address element_address(kNoRegister); |
| 1509 if (aligned()) { | 1521 if (aligned()) { |
| 1510 element_address = index.IsRegister() | 1522 element_address = index.IsRegister() |
| 1511 ? __ ElementAddressForRegIndex(false, // Store. | 1523 ? __ ElementAddressForRegIndex( |
| 1512 IsExternal(), class_id(), index_scale(), | 1524 false, // Store. |
| 1513 array, | 1525 IsExternal(), class_id(), index_scale(), array, |
| 1514 index.reg()) | 1526 index.reg()) |
| 1515 : __ ElementAddressForIntIndex(false, // Store. | 1527 : __ ElementAddressForIntIndex( |
| 1516 IsExternal(), class_id(), index_scale(), | 1528 false, // Store. |
| 1517 array, Smi::Cast(index.constant()).Value(), | 1529 IsExternal(), class_id(), index_scale(), array, |
| 1518 temp); | 1530 Smi::Cast(index.constant()).Value(), temp); |
| 1519 } else { | 1531 } else { |
| 1520 if (index.IsRegister()) { | 1532 if (index.IsRegister()) { |
| 1521 __ LoadElementAddressForRegIndex(temp, | 1533 __ LoadElementAddressForRegIndex(temp, |
| 1522 false, // Store. | 1534 false, // Store. |
| 1523 IsExternal(), class_id(), index_scale(), | 1535 IsExternal(), class_id(), index_scale(), |
| 1524 array, | 1536 array, index.reg()); |
| 1525 index.reg()); | |
| 1526 } else { | 1537 } else { |
| 1527 __ LoadElementAddressForIntIndex(temp, | 1538 __ LoadElementAddressForIntIndex(temp, |
| 1528 false, // Store. | 1539 false, // Store. |
| 1529 IsExternal(), class_id(), index_scale(), | 1540 IsExternal(), class_id(), index_scale(), |
| 1530 array, | 1541 array, |
| 1531 Smi::Cast(index.constant()).Value()); | 1542 Smi::Cast(index.constant()).Value()); |
| 1532 } | 1543 } |
| 1533 } | 1544 } |
| 1534 | 1545 |
| 1535 switch (class_id()) { | 1546 switch (class_id()) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1569 if (value > 0xFF) { | 1580 if (value > 0xFF) { |
| 1570 value = 0xFF; | 1581 value = 0xFF; |
| 1571 } else if (value < 0) { | 1582 } else if (value < 0) { |
| 1572 value = 0; | 1583 value = 0; |
| 1573 } | 1584 } |
| 1574 __ LoadImmediate(IP, static_cast<int8_t>(value)); | 1585 __ LoadImmediate(IP, static_cast<int8_t>(value)); |
| 1575 __ strb(IP, element_address); | 1586 __ strb(IP, element_address); |
| 1576 } else { | 1587 } else { |
| 1577 const Register value = locs()->in(2).reg(); | 1588 const Register value = locs()->in(2).reg(); |
| 1578 __ LoadImmediate(IP, 0x1FE); // Smi 0xFF. | 1589 __ LoadImmediate(IP, 0x1FE); // Smi 0xFF. |
| 1579 __ cmp(value, Operand(IP)); // Compare Smi value and smi 0xFF. | 1590 __ cmp(value, Operand(IP)); // Compare Smi value and smi 0xFF. |
| 1580 // Clamp to 0x00 or 0xFF respectively. | 1591 // Clamp to 0x00 or 0xFF respectively. |
| 1581 __ mov(IP, Operand(0), LE); // IP = value <= 0x1FE ? 0 : 0x1FE. | 1592 __ mov(IP, Operand(0), LE); // IP = value <= 0x1FE ? 0 : 0x1FE. |
| 1582 __ mov(IP, Operand(value), LS); // IP = value in range ? value : IP. | 1593 __ mov(IP, Operand(value), LS); // IP = value in range ? value : IP. |
| 1583 __ SmiUntag(IP); | 1594 __ SmiUntag(IP); |
| 1584 __ strb(IP, element_address); | 1595 __ strb(IP, element_address); |
| 1585 } | 1596 } |
| 1586 break; | 1597 break; |
| 1587 } | 1598 } |
| 1588 case kTypedDataInt16ArrayCid: | 1599 case kTypedDataInt16ArrayCid: |
| 1589 case kTypedDataUint16ArrayCid: { | 1600 case kTypedDataUint16ArrayCid: { |
| 1590 const Register value = locs()->in(2).reg(); | 1601 const Register value = locs()->in(2).reg(); |
| 1591 __ SmiUntag(IP, value); | 1602 __ SmiUntag(IP, value); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1631 } | 1642 } |
| 1632 | 1643 |
| 1633 | 1644 |
| 1634 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 1645 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |
| 1635 bool opt) const { | 1646 bool opt) const { |
| 1636 const intptr_t kNumInputs = 1; | 1647 const intptr_t kNumInputs = 1; |
| 1637 | 1648 |
| 1638 const intptr_t value_cid = value()->Type()->ToCid(); | 1649 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1639 const intptr_t field_cid = field().guarded_cid(); | 1650 const intptr_t field_cid = field().guarded_cid(); |
| 1640 | 1651 |
| 1641 const bool emit_full_guard = | 1652 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); |
| 1642 !opt || (field_cid == kIllegalCid); | |
| 1643 | 1653 |
| 1644 const bool needs_value_cid_temp_reg = emit_full_guard || | 1654 const bool needs_value_cid_temp_reg = |
| 1645 ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); | 1655 emit_full_guard || ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); |
| 1646 | 1656 |
| 1647 const bool needs_field_temp_reg = emit_full_guard; | 1657 const bool needs_field_temp_reg = emit_full_guard; |
| 1648 | 1658 |
| 1649 intptr_t num_temps = 0; | 1659 intptr_t num_temps = 0; |
| 1650 if (needs_value_cid_temp_reg) { | 1660 if (needs_value_cid_temp_reg) { |
| 1651 num_temps++; | 1661 num_temps++; |
| 1652 } | 1662 } |
| 1653 if (needs_field_temp_reg) { | 1663 if (needs_field_temp_reg) { |
| 1654 num_temps++; | 1664 num_temps++; |
| 1655 } | 1665 } |
| 1656 | 1666 |
| 1657 LocationSummary* summary = new(zone) LocationSummary( | 1667 LocationSummary* summary = new (zone) |
| 1658 zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 1668 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
| 1659 summary->set_in(0, Location::RequiresRegister()); | 1669 summary->set_in(0, Location::RequiresRegister()); |
| 1660 | 1670 |
| 1661 for (intptr_t i = 0; i < num_temps; i++) { | 1671 for (intptr_t i = 0; i < num_temps; i++) { |
| 1662 summary->set_temp(i, Location::RequiresRegister()); | 1672 summary->set_temp(i, Location::RequiresRegister()); |
| 1663 } | 1673 } |
| 1664 | 1674 |
| 1665 return summary; | 1675 return summary; |
| 1666 } | 1676 } |
| 1667 | 1677 |
| 1668 | 1678 |
| 1669 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1679 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1670 ASSERT(sizeof(classid_t) == kInt16Size); | 1680 ASSERT(sizeof(classid_t) == kInt16Size); |
| 1671 | 1681 |
| 1672 const intptr_t value_cid = value()->Type()->ToCid(); | 1682 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1673 const intptr_t field_cid = field().guarded_cid(); | 1683 const intptr_t field_cid = field().guarded_cid(); |
| 1674 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1684 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
| 1675 | 1685 |
| 1676 if (field_cid == kDynamicCid) { | 1686 if (field_cid == kDynamicCid) { |
| 1677 if (Compiler::IsBackgroundCompilation()) { | 1687 if (Compiler::IsBackgroundCompilation()) { |
| 1678 // Field state changed while compiling. | 1688 // Field state changed while compiling. |
| 1679 Compiler::AbortBackgroundCompilation(deopt_id(), | 1689 Compiler::AbortBackgroundCompilation( |
| 1690 deopt_id(), |
| 1680 "GuardFieldClassInstr: field state changed while compiling"); | 1691 "GuardFieldClassInstr: field state changed while compiling"); |
| 1681 } | 1692 } |
| 1682 ASSERT(!compiler->is_optimizing()); | 1693 ASSERT(!compiler->is_optimizing()); |
| 1683 return; // Nothing to emit. | 1694 return; // Nothing to emit. |
| 1684 } | 1695 } |
| 1685 | 1696 |
| 1686 const bool emit_full_guard = | 1697 const bool emit_full_guard = |
| 1687 !compiler->is_optimizing() || (field_cid == kIllegalCid); | 1698 !compiler->is_optimizing() || (field_cid == kIllegalCid); |
| 1688 | 1699 |
| 1689 const bool needs_value_cid_temp_reg = emit_full_guard || | 1700 const bool needs_value_cid_temp_reg = |
| 1690 ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); | 1701 emit_full_guard || ((value_cid == kDynamicCid) && (field_cid != kSmiCid)); |
| 1691 | 1702 |
| 1692 const bool needs_field_temp_reg = emit_full_guard; | 1703 const bool needs_field_temp_reg = emit_full_guard; |
| 1693 | 1704 |
| 1694 const Register value_reg = locs()->in(0).reg(); | 1705 const Register value_reg = locs()->in(0).reg(); |
| 1695 | 1706 |
| 1696 const Register value_cid_reg = needs_value_cid_temp_reg ? | 1707 const Register value_cid_reg = |
| 1697 locs()->temp(0).reg() : kNoRegister; | 1708 needs_value_cid_temp_reg ? locs()->temp(0).reg() : kNoRegister; |
| 1698 | 1709 |
| 1699 const Register field_reg = needs_field_temp_reg ? | 1710 const Register field_reg = needs_field_temp_reg |
| 1700 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; | 1711 ? locs()->temp(locs()->temp_count() - 1).reg() |
| 1712 : kNoRegister; |
| 1701 | 1713 |
| 1702 Label ok, fail_label; | 1714 Label ok, fail_label; |
| 1703 | 1715 |
| 1704 Label* deopt = compiler->is_optimizing() ? | 1716 Label* deopt = |
| 1705 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1717 compiler->is_optimizing() |
| 1718 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1719 : NULL; |
| 1706 | 1720 |
| 1707 Label* fail = (deopt != NULL) ? deopt : &fail_label; | 1721 Label* fail = (deopt != NULL) ? deopt : &fail_label; |
| 1708 | 1722 |
| 1709 if (emit_full_guard) { | 1723 if (emit_full_guard) { |
| 1710 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1724 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
| 1711 | 1725 |
| 1712 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); | 1726 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); |
| 1713 FieldAddress field_nullability_operand( | 1727 FieldAddress field_nullability_operand(field_reg, |
| 1714 field_reg, Field::is_nullable_offset()); | 1728 Field::is_nullable_offset()); |
| 1715 | 1729 |
| 1716 if (value_cid == kDynamicCid) { | 1730 if (value_cid == kDynamicCid) { |
| 1717 LoadValueCid(compiler, value_cid_reg, value_reg); | 1731 LoadValueCid(compiler, value_cid_reg, value_reg); |
| 1718 __ ldrh(IP, field_cid_operand); | 1732 __ ldrh(IP, field_cid_operand); |
| 1719 __ cmp(value_cid_reg, Operand(IP)); | 1733 __ cmp(value_cid_reg, Operand(IP)); |
| 1720 __ b(&ok, EQ); | 1734 __ b(&ok, EQ); |
| 1721 __ ldrh(IP, field_nullability_operand); | 1735 __ ldrh(IP, field_nullability_operand); |
| 1722 __ cmp(value_cid_reg, Operand(IP)); | 1736 __ cmp(value_cid_reg, Operand(IP)); |
| 1723 } else if (value_cid == kNullCid) { | 1737 } else if (value_cid == kNullCid) { |
| 1724 __ ldrh(value_cid_reg, field_nullability_operand); | 1738 __ ldrh(value_cid_reg, field_nullability_operand); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1802 } | 1816 } |
| 1803 __ Bind(&ok); | 1817 __ Bind(&ok); |
| 1804 } | 1818 } |
| 1805 | 1819 |
| 1806 | 1820 |
| 1807 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 1821 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |
| 1808 bool opt) const { | 1822 bool opt) const { |
| 1809 const intptr_t kNumInputs = 1; | 1823 const intptr_t kNumInputs = 1; |
| 1810 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1824 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
| 1811 const intptr_t kNumTemps = 3; | 1825 const intptr_t kNumTemps = 3; |
| 1812 LocationSummary* summary = new(zone) LocationSummary( | 1826 LocationSummary* summary = new (zone) |
| 1813 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1827 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1814 summary->set_in(0, Location::RequiresRegister()); | 1828 summary->set_in(0, Location::RequiresRegister()); |
| 1815 // We need temporaries for field object, length offset and expected length. | 1829 // We need temporaries for field object, length offset and expected length. |
| 1816 summary->set_temp(0, Location::RequiresRegister()); | 1830 summary->set_temp(0, Location::RequiresRegister()); |
| 1817 summary->set_temp(1, Location::RequiresRegister()); | 1831 summary->set_temp(1, Location::RequiresRegister()); |
| 1818 summary->set_temp(2, Location::RequiresRegister()); | 1832 summary->set_temp(2, Location::RequiresRegister()); |
| 1819 return summary; | 1833 return summary; |
| 1820 } else { | 1834 } else { |
| 1821 // TODO(vegorov): can use TMP when length is small enough to fit into | 1835 // TODO(vegorov): can use TMP when length is small enough to fit into |
| 1822 // immediate. | 1836 // immediate. |
| 1823 const intptr_t kNumTemps = 1; | 1837 const intptr_t kNumTemps = 1; |
| 1824 LocationSummary* summary = new(zone) LocationSummary( | 1838 LocationSummary* summary = new (zone) |
| 1825 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1839 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1826 summary->set_in(0, Location::RequiresRegister()); | 1840 summary->set_in(0, Location::RequiresRegister()); |
| 1827 summary->set_temp(0, Location::RequiresRegister()); | 1841 summary->set_temp(0, Location::RequiresRegister()); |
| 1828 return summary; | 1842 return summary; |
| 1829 } | 1843 } |
| 1830 UNREACHABLE(); | 1844 UNREACHABLE(); |
| 1831 } | 1845 } |
| 1832 | 1846 |
| 1833 | 1847 |
| 1834 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1848 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1835 if (field().guarded_list_length() == Field::kNoFixedLength) { | 1849 if (field().guarded_list_length() == Field::kNoFixedLength) { |
| 1836 if (Compiler::IsBackgroundCompilation()) { | 1850 if (Compiler::IsBackgroundCompilation()) { |
| 1837 // Field state changed while compiling. | 1851 // Field state changed while compiling. |
| 1838 Compiler::AbortBackgroundCompilation(deopt_id(), | 1852 Compiler::AbortBackgroundCompilation( |
| 1853 deopt_id(), |
| 1839 "GuardFieldLengthInstr: field state changed while compiling"); | 1854 "GuardFieldLengthInstr: field state changed while compiling"); |
| 1840 } | 1855 } |
| 1841 ASSERT(!compiler->is_optimizing()); | 1856 ASSERT(!compiler->is_optimizing()); |
| 1842 return; // Nothing to emit. | 1857 return; // Nothing to emit. |
| 1843 } | 1858 } |
| 1844 | 1859 |
| 1845 Label* deopt = compiler->is_optimizing() ? | 1860 Label* deopt = |
| 1846 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1861 compiler->is_optimizing() |
| 1862 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1863 : NULL; |
| 1847 | 1864 |
| 1848 const Register value_reg = locs()->in(0).reg(); | 1865 const Register value_reg = locs()->in(0).reg(); |
| 1849 | 1866 |
| 1850 if (!compiler->is_optimizing() || | 1867 if (!compiler->is_optimizing() || |
| 1851 (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1868 (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
| 1852 const Register field_reg = locs()->temp(0).reg(); | 1869 const Register field_reg = locs()->temp(0).reg(); |
| 1853 const Register offset_reg = locs()->temp(1).reg(); | 1870 const Register offset_reg = locs()->temp(1).reg(); |
| 1854 const Register length_reg = locs()->temp(2).reg(); | 1871 const Register length_reg = locs()->temp(2).reg(); |
| 1855 | 1872 |
| 1856 Label ok; | 1873 Label ok; |
| 1857 | 1874 |
| 1858 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1875 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
| 1859 | 1876 |
| 1860 __ ldrsb(offset_reg, FieldAddress(field_reg, | 1877 __ ldrsb( |
| 1861 Field::guarded_list_length_in_object_offset_offset())); | 1878 offset_reg, |
| 1862 __ ldr(length_reg, FieldAddress(field_reg, | 1879 FieldAddress(field_reg, |
| 1863 Field::guarded_list_length_offset())); | 1880 Field::guarded_list_length_in_object_offset_offset())); |
| 1881 __ ldr(length_reg, |
| 1882 FieldAddress(field_reg, Field::guarded_list_length_offset())); |
| 1864 | 1883 |
| 1865 __ tst(offset_reg, Operand(offset_reg)); | 1884 __ tst(offset_reg, Operand(offset_reg)); |
| 1866 __ b(&ok, MI); | 1885 __ b(&ok, MI); |
| 1867 | 1886 |
| 1868 // Load the length from the value. GuardFieldClass already verified that | 1887 // Load the length from the value. GuardFieldClass already verified that |
| 1869 // value's class matches guarded class id of the field. | 1888 // value's class matches guarded class id of the field. |
| 1870 // offset_reg contains offset already corrected by -kHeapObjectTag that is | 1889 // offset_reg contains offset already corrected by -kHeapObjectTag that is |
| 1871 // why we use Address instead of FieldAddress. | 1890 // why we use Address instead of FieldAddress. |
| 1872 __ ldr(IP, Address(value_reg, offset_reg)); | 1891 __ ldr(IP, Address(value_reg, offset_reg)); |
| 1873 __ cmp(length_reg, Operand(IP)); | 1892 __ cmp(length_reg, Operand(IP)); |
| 1874 | 1893 |
| 1875 if (deopt == NULL) { | 1894 if (deopt == NULL) { |
| 1876 __ b(&ok, EQ); | 1895 __ b(&ok, EQ); |
| 1877 | 1896 |
| 1878 __ Push(field_reg); | 1897 __ Push(field_reg); |
| 1879 __ Push(value_reg); | 1898 __ Push(value_reg); |
| 1880 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); | 1899 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); |
| 1881 __ Drop(2); // Drop the field and the value. | 1900 __ Drop(2); // Drop the field and the value. |
| 1882 } else { | 1901 } else { |
| 1883 __ b(deopt, NE); | 1902 __ b(deopt, NE); |
| 1884 } | 1903 } |
| 1885 | 1904 |
| 1886 __ Bind(&ok); | 1905 __ Bind(&ok); |
| 1887 } else { | 1906 } else { |
| 1888 ASSERT(compiler->is_optimizing()); | 1907 ASSERT(compiler->is_optimizing()); |
| 1889 ASSERT(field().guarded_list_length() >= 0); | 1908 ASSERT(field().guarded_list_length() >= 0); |
| 1890 ASSERT(field().guarded_list_length_in_object_offset() != | 1909 ASSERT(field().guarded_list_length_in_object_offset() != |
| 1891 Field::kUnknownLengthOffset); | 1910 Field::kUnknownLengthOffset); |
| 1892 | 1911 |
| 1893 const Register length_reg = locs()->temp(0).reg(); | 1912 const Register length_reg = locs()->temp(0).reg(); |
| 1894 | 1913 |
| 1895 __ ldr(length_reg, | 1914 __ ldr(length_reg, |
| 1896 FieldAddress(value_reg, | 1915 FieldAddress(value_reg, |
| 1897 field().guarded_list_length_in_object_offset())); | 1916 field().guarded_list_length_in_object_offset())); |
| 1898 __ CompareImmediate(length_reg, | 1917 __ CompareImmediate(length_reg, |
| 1899 Smi::RawValue(field().guarded_list_length())); | 1918 Smi::RawValue(field().guarded_list_length())); |
| 1900 __ b(deopt, NE); | 1919 __ b(deopt, NE); |
| 1901 } | 1920 } |
| 1902 } | 1921 } |
| 1903 | 1922 |
| 1904 | 1923 |
| 1905 class BoxAllocationSlowPath : public SlowPathCode { | 1924 class BoxAllocationSlowPath : public SlowPathCode { |
| 1906 public: | 1925 public: |
| 1907 BoxAllocationSlowPath(Instruction* instruction, | 1926 BoxAllocationSlowPath(Instruction* instruction, |
| 1908 const Class& cls, | 1927 const Class& cls, |
| 1909 Register result) | 1928 Register result) |
| 1910 : instruction_(instruction), | 1929 : instruction_(instruction), cls_(cls), result_(result) {} |
| 1911 cls_(cls), | |
| 1912 result_(result) { } | |
| 1913 | 1930 |
| 1914 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1931 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1915 if (Assembler::EmittingComments()) { | 1932 if (Assembler::EmittingComments()) { |
| 1916 __ Comment("%s slow path allocation of %s", | 1933 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), |
| 1917 instruction_->DebugName(), | |
| 1918 String::Handle(cls_.ScrubbedName()).ToCString()); | 1934 String::Handle(cls_.ScrubbedName()).ToCString()); |
| 1919 } | 1935 } |
| 1920 __ Bind(entry_label()); | 1936 __ Bind(entry_label()); |
| 1921 const Code& stub = Code::ZoneHandle( | 1937 const Code& stub = Code::ZoneHandle( |
| 1922 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); | 1938 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); |
| 1923 const StubEntry stub_entry(stub); | 1939 const StubEntry stub_entry(stub); |
| 1924 | 1940 |
| 1925 LocationSummary* locs = instruction_->locs(); | 1941 LocationSummary* locs = instruction_->locs(); |
| 1926 | 1942 |
| 1927 locs->live_registers()->Remove(Location::RegisterLocation(result_)); | 1943 locs->live_registers()->Remove(Location::RegisterLocation(result_)); |
| 1928 | 1944 |
| 1929 compiler->SaveLiveRegisters(locs); | 1945 compiler->SaveLiveRegisters(locs); |
| 1930 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. | 1946 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. |
| 1931 stub_entry, | 1947 stub_entry, RawPcDescriptors::kOther, locs); |
| 1932 RawPcDescriptors::kOther, | |
| 1933 locs); | |
| 1934 compiler->AddStubCallTarget(stub); | 1948 compiler->AddStubCallTarget(stub); |
| 1935 __ MoveRegister(result_, R0); | 1949 __ MoveRegister(result_, R0); |
| 1936 compiler->RestoreLiveRegisters(locs); | 1950 compiler->RestoreLiveRegisters(locs); |
| 1937 __ b(exit_label()); | 1951 __ b(exit_label()); |
| 1938 } | 1952 } |
| 1939 | 1953 |
| 1940 static void Allocate(FlowGraphCompiler* compiler, | 1954 static void Allocate(FlowGraphCompiler* compiler, |
| 1941 Instruction* instruction, | 1955 Instruction* instruction, |
| 1942 const Class& cls, | 1956 const Class& cls, |
| 1943 Register result, | 1957 Register result, |
| 1944 Register temp) { | 1958 Register temp) { |
| 1945 if (compiler->intrinsic_mode()) { | 1959 if (compiler->intrinsic_mode()) { |
| 1946 __ TryAllocate(cls, | 1960 __ TryAllocate(cls, compiler->intrinsic_slow_path_label(), result, temp); |
| 1947 compiler->intrinsic_slow_path_label(), | |
| 1948 result, | |
| 1949 temp); | |
| 1950 } else { | 1961 } else { |
| 1951 BoxAllocationSlowPath* slow_path = | 1962 BoxAllocationSlowPath* slow_path = |
| 1952 new BoxAllocationSlowPath(instruction, cls, result); | 1963 new BoxAllocationSlowPath(instruction, cls, result); |
| 1953 compiler->AddSlowPathCode(slow_path); | 1964 compiler->AddSlowPathCode(slow_path); |
| 1954 | 1965 |
| 1955 __ TryAllocate(cls, | 1966 __ TryAllocate(cls, slow_path->entry_label(), result, temp); |
| 1956 slow_path->entry_label(), | |
| 1957 result, | |
| 1958 temp); | |
| 1959 __ Bind(slow_path->exit_label()); | 1967 __ Bind(slow_path->exit_label()); |
| 1960 } | 1968 } |
| 1961 } | 1969 } |
| 1962 | 1970 |
| 1963 private: | 1971 private: |
| 1964 Instruction* instruction_; | 1972 Instruction* instruction_; |
| 1965 const Class& cls_; | 1973 const Class& cls_; |
| 1966 const Register result_; | 1974 const Register result_; |
| 1967 }; | 1975 }; |
| 1968 | 1976 |
| 1969 | 1977 |
| 1970 | |
| 1971 | |
| 1972 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 1978 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |
| 1973 bool opt) const { | 1979 bool opt) const { |
| 1974 const bool might_box = (representation() == kTagged) && !can_pack_into_smi(); | 1980 const bool might_box = (representation() == kTagged) && !can_pack_into_smi(); |
| 1975 const intptr_t kNumInputs = 2; | 1981 const intptr_t kNumInputs = 2; |
| 1976 const intptr_t kNumTemps = might_box ? 1 : 0; | 1982 const intptr_t kNumTemps = might_box ? 1 : 0; |
| 1977 LocationSummary* summary = new(zone) LocationSummary( | 1983 LocationSummary* summary = new (zone) LocationSummary( |
| 1978 zone, kNumInputs, kNumTemps, | 1984 zone, kNumInputs, kNumTemps, |
| 1979 might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall); | 1985 might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall); |
| 1980 summary->set_in(0, Location::RequiresRegister()); | 1986 summary->set_in(0, Location::RequiresRegister()); |
| 1981 summary->set_in(1, Location::RequiresRegister()); | 1987 summary->set_in(1, Location::RequiresRegister()); |
| 1982 | 1988 |
| 1983 if (might_box) { | 1989 if (might_box) { |
| 1984 summary->set_temp(0, Location::RequiresRegister()); | 1990 summary->set_temp(0, Location::RequiresRegister()); |
| 1985 } | 1991 } |
| 1986 | 1992 |
| 1987 if (representation() == kUnboxedMint) { | 1993 if (representation() == kUnboxedMint) { |
| 1988 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 1994 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 1989 Location::RequiresRegister())); | 1995 Location::RequiresRegister())); |
| 1990 } else { | 1996 } else { |
| 1991 ASSERT(representation() == kTagged); | 1997 ASSERT(representation() == kTagged); |
| 1992 summary->set_out(0, Location::RequiresRegister()); | 1998 summary->set_out(0, Location::RequiresRegister()); |
| 1993 } | 1999 } |
| 1994 | 2000 |
| 1995 return summary; | 2001 return summary; |
| 1996 } | 2002 } |
| 1997 | 2003 |
| 1998 | 2004 |
| 1999 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2005 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2000 // The string register points to the backing store for external strings. | 2006 // The string register points to the backing store for external strings. |
| 2001 const Register str = locs()->in(0).reg(); | 2007 const Register str = locs()->in(0).reg(); |
| 2002 const Location index = locs()->in(1); | 2008 const Location index = locs()->in(1); |
| 2003 | 2009 |
| 2004 Address element_address = __ ElementAddressForRegIndex( | 2010 Address element_address = __ ElementAddressForRegIndex( |
| 2005 true, IsExternal(), class_id(), index_scale(), str, index.reg()); | 2011 true, IsExternal(), class_id(), index_scale(), str, index.reg()); |
| 2006 // Warning: element_address may use register IP as base. | 2012 // Warning: element_address may use register IP as base. |
| 2007 | 2013 |
| 2008 if (representation() == kUnboxedMint) { | 2014 if (representation() == kUnboxedMint) { |
| 2009 ASSERT(compiler->is_optimizing()); | 2015 ASSERT(compiler->is_optimizing()); |
| 2010 ASSERT(locs()->out(0).IsPairLocation()); | 2016 ASSERT(locs()->out(0).IsPairLocation()); |
| 2011 PairLocation* result_pair = locs()->out(0).AsPairLocation(); | 2017 PairLocation* result_pair = locs()->out(0).AsPairLocation(); |
| 2012 Register result1 = result_pair->At(0).reg(); | 2018 Register result1 = result_pair->At(0).reg(); |
| 2013 Register result2 = result_pair->At(1).reg(); | 2019 Register result2 = result_pair->At(1).reg(); |
| 2014 switch (class_id()) { | 2020 switch (class_id()) { |
| 2015 case kOneByteStringCid: | 2021 case kOneByteStringCid: |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2027 default: | 2033 default: |
| 2028 UNREACHABLE(); | 2034 UNREACHABLE(); |
| 2029 } | 2035 } |
| 2030 } else { | 2036 } else { |
| 2031 ASSERT(representation() == kTagged); | 2037 ASSERT(representation() == kTagged); |
| 2032 Register result = locs()->out(0).reg(); | 2038 Register result = locs()->out(0).reg(); |
| 2033 switch (class_id()) { | 2039 switch (class_id()) { |
| 2034 case kOneByteStringCid: | 2040 case kOneByteStringCid: |
| 2035 case kExternalOneByteStringCid: | 2041 case kExternalOneByteStringCid: |
| 2036 switch (element_count()) { | 2042 switch (element_count()) { |
| 2037 case 1: __ ldrb(result, element_address); break; | 2043 case 1: |
| 2038 case 2: __ ldrh(result, element_address); break; | 2044 __ ldrb(result, element_address); |
| 2039 case 4: __ ldr(result, element_address); break; | 2045 break; |
| 2040 default: UNREACHABLE(); | 2046 case 2: |
| 2047 __ ldrh(result, element_address); |
| 2048 break; |
| 2049 case 4: |
| 2050 __ ldr(result, element_address); |
| 2051 break; |
| 2052 default: |
| 2053 UNREACHABLE(); |
| 2041 } | 2054 } |
| 2042 break; | 2055 break; |
| 2043 case kTwoByteStringCid: | 2056 case kTwoByteStringCid: |
| 2044 case kExternalTwoByteStringCid: | 2057 case kExternalTwoByteStringCid: |
| 2045 switch (element_count()) { | 2058 switch (element_count()) { |
| 2046 case 1: __ ldrh(result, element_address); break; | 2059 case 1: |
| 2047 case 2: __ ldr(result, element_address); break; | 2060 __ ldrh(result, element_address); |
| 2048 default: UNREACHABLE(); | 2061 break; |
| 2062 case 2: |
| 2063 __ ldr(result, element_address); |
| 2064 break; |
| 2065 default: |
| 2066 UNREACHABLE(); |
| 2049 } | 2067 } |
| 2050 break; | 2068 break; |
| 2051 default: | 2069 default: |
| 2052 UNREACHABLE(); | 2070 UNREACHABLE(); |
| 2053 break; | 2071 break; |
| 2054 } | 2072 } |
| 2055 if (can_pack_into_smi()) { | 2073 if (can_pack_into_smi()) { |
| 2056 __ SmiTag(result); | 2074 __ SmiTag(result); |
| 2057 } else { | 2075 } else { |
| 2058 // If the value cannot fit in a smi then allocate a mint box for it. | 2076 // If the value cannot fit in a smi then allocate a mint box for it. |
| 2059 Register value = locs()->temp(0).reg(); | 2077 Register value = locs()->temp(0).reg(); |
| 2060 Register temp = locs()->temp(1).reg(); | 2078 Register temp = locs()->temp(1).reg(); |
| 2061 // Value register needs to be manually preserved on allocation slow-path. | 2079 // Value register needs to be manually preserved on allocation slow-path. |
| 2062 locs()->live_registers()->Add(locs()->temp(0), kUnboxedInt32); | 2080 locs()->live_registers()->Add(locs()->temp(0), kUnboxedInt32); |
| 2063 | 2081 |
| 2064 ASSERT(result != value); | 2082 ASSERT(result != value); |
| 2065 __ MoveRegister(value, result); | 2083 __ MoveRegister(value, result); |
| 2066 __ SmiTag(result); | 2084 __ SmiTag(result); |
| 2067 | 2085 |
| 2068 Label done; | 2086 Label done; |
| 2069 __ TestImmediate(value, 0xC0000000); | 2087 __ TestImmediate(value, 0xC0000000); |
| 2070 __ b(&done, EQ); | 2088 __ b(&done, EQ); |
| 2071 BoxAllocationSlowPath::Allocate( | 2089 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), |
| 2072 compiler, this, compiler->mint_class(), result, temp); | 2090 result, temp); |
| 2073 __ eor(temp, temp, Operand(temp)); | 2091 __ eor(temp, temp, Operand(temp)); |
| 2074 __ StoreToOffset(kWord, value, result, | 2092 __ StoreToOffset(kWord, value, result, |
| 2075 Mint::value_offset() - kHeapObjectTag); | 2093 Mint::value_offset() - kHeapObjectTag); |
| 2076 __ StoreToOffset(kWord, temp, result, | 2094 __ StoreToOffset(kWord, temp, result, |
| 2077 Mint::value_offset() - kHeapObjectTag + kWordSize); | 2095 Mint::value_offset() - kHeapObjectTag + kWordSize); |
| 2078 __ Bind(&done); | 2096 __ Bind(&done); |
| 2079 } | 2097 } |
| 2080 } | 2098 } |
| 2081 } | 2099 } |
| 2082 | 2100 |
| 2083 | 2101 |
| 2084 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 2102 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |
| 2085 bool opt) const { | 2103 bool opt) const { |
| 2086 const intptr_t kNumInputs = 2; | 2104 const intptr_t kNumInputs = 2; |
| 2087 const intptr_t kNumTemps = | 2105 const intptr_t kNumTemps = |
| 2088 (IsUnboxedStore() && opt) ? 2 : | 2106 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); |
| 2089 ((IsPotentialUnboxedStore()) ? 3 : 0); | 2107 LocationSummary* summary = new (zone) |
| 2090 LocationSummary* summary = new(zone) LocationSummary( | 2108 LocationSummary(zone, kNumInputs, kNumTemps, |
| 2091 zone, kNumInputs, kNumTemps, | 2109 ((IsUnboxedStore() && opt && is_initialization()) || |
| 2092 ((IsUnboxedStore() && opt && is_initialization()) || | 2110 IsPotentialUnboxedStore()) |
| 2093 IsPotentialUnboxedStore()) | 2111 ? LocationSummary::kCallOnSlowPath |
| 2094 ? LocationSummary::kCallOnSlowPath | 2112 : LocationSummary::kNoCall); |
| 2095 : LocationSummary::kNoCall); | |
| 2096 | 2113 |
| 2097 summary->set_in(0, Location::RequiresRegister()); | 2114 summary->set_in(0, Location::RequiresRegister()); |
| 2098 if (IsUnboxedStore() && opt) { | 2115 if (IsUnboxedStore() && opt) { |
| 2099 summary->set_in(1, Location::RequiresFpuRegister()); | 2116 summary->set_in(1, Location::RequiresFpuRegister()); |
| 2100 summary->set_temp(0, Location::RequiresRegister()); | 2117 summary->set_temp(0, Location::RequiresRegister()); |
| 2101 summary->set_temp(1, Location::RequiresRegister()); | 2118 summary->set_temp(1, Location::RequiresRegister()); |
| 2102 } else if (IsPotentialUnboxedStore()) { | 2119 } else if (IsPotentialUnboxedStore()) { |
| 2103 summary->set_in(1, ShouldEmitStoreBarrier() | 2120 summary->set_in(1, ShouldEmitStoreBarrier() ? Location::WritableRegister() |
| 2104 ? Location::WritableRegister() | 2121 : Location::RequiresRegister()); |
| 2105 : Location::RequiresRegister()); | |
| 2106 summary->set_temp(0, Location::RequiresRegister()); | 2122 summary->set_temp(0, Location::RequiresRegister()); |
| 2107 summary->set_temp(1, Location::RequiresRegister()); | 2123 summary->set_temp(1, Location::RequiresRegister()); |
| 2108 summary->set_temp(2, opt ? Location::RequiresFpuRegister() | 2124 summary->set_temp(2, opt ? Location::RequiresFpuRegister() |
| 2109 : Location::FpuRegisterLocation(Q1)); | 2125 : Location::FpuRegisterLocation(Q1)); |
| 2110 } else { | 2126 } else { |
| 2111 summary->set_in(1, ShouldEmitStoreBarrier() | 2127 summary->set_in(1, ShouldEmitStoreBarrier() |
| 2112 ? Location::WritableRegister() | 2128 ? Location::WritableRegister() |
| 2113 : Location::RegisterOrConstant(value())); | 2129 : Location::RegisterOrConstant(value())); |
| 2114 } | 2130 } |
| 2115 return summary; | 2131 return summary; |
| 2116 } | 2132 } |
| 2117 | 2133 |
| 2118 | 2134 |
| 2119 static void EnsureMutableBox(FlowGraphCompiler* compiler, | 2135 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
| 2120 StoreInstanceFieldInstr* instruction, | 2136 StoreInstanceFieldInstr* instruction, |
| 2121 Register box_reg, | 2137 Register box_reg, |
| 2122 const Class& cls, | 2138 const Class& cls, |
| 2123 Register instance_reg, | 2139 Register instance_reg, |
| 2124 intptr_t offset, | 2140 intptr_t offset, |
| 2125 Register temp) { | 2141 Register temp) { |
| 2126 Label done; | 2142 Label done; |
| 2127 __ ldr(box_reg, FieldAddress(instance_reg, offset)); | 2143 __ ldr(box_reg, FieldAddress(instance_reg, offset)); |
| 2128 __ CompareObject(box_reg, Object::null_object()); | 2144 __ CompareObject(box_reg, Object::null_object()); |
| 2129 __ b(&done, NE); | 2145 __ b(&done, NE); |
| 2130 | 2146 |
| 2131 BoxAllocationSlowPath::Allocate( | 2147 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); |
| 2132 compiler, instruction, cls, box_reg, temp); | |
| 2133 | 2148 |
| 2134 __ MoveRegister(temp, box_reg); | 2149 __ MoveRegister(temp, box_reg); |
| 2135 __ StoreIntoObjectOffset(instance_reg, offset, temp); | 2150 __ StoreIntoObjectOffset(instance_reg, offset, temp); |
| 2136 __ Bind(&done); | 2151 __ Bind(&done); |
| 2137 } | 2152 } |
| 2138 | 2153 |
| 2139 | 2154 |
| 2140 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2155 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2141 ASSERT(sizeof(classid_t) == kInt16Size); | 2156 ASSERT(sizeof(classid_t) == kInt16Size); |
| 2142 | 2157 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2159 case kFloat32x4Cid: | 2174 case kFloat32x4Cid: |
| 2160 cls = &compiler->float32x4_class(); | 2175 cls = &compiler->float32x4_class(); |
| 2161 break; | 2176 break; |
| 2162 case kFloat64x2Cid: | 2177 case kFloat64x2Cid: |
| 2163 cls = &compiler->float64x2_class(); | 2178 cls = &compiler->float64x2_class(); |
| 2164 break; | 2179 break; |
| 2165 default: | 2180 default: |
| 2166 UNREACHABLE(); | 2181 UNREACHABLE(); |
| 2167 } | 2182 } |
| 2168 | 2183 |
| 2169 BoxAllocationSlowPath::Allocate( | 2184 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2); |
| 2170 compiler, this, *cls, temp, temp2); | |
| 2171 __ MoveRegister(temp2, temp); | 2185 __ MoveRegister(temp2, temp); |
| 2172 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2); | 2186 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, temp2); |
| 2173 } else { | 2187 } else { |
| 2174 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes_)); | 2188 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes_)); |
| 2175 } | 2189 } |
| 2176 switch (cid) { | 2190 switch (cid) { |
| 2177 case kDoubleCid: | 2191 case kDoubleCid: |
| 2178 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); | 2192 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); |
| 2179 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); | 2193 __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
| 2180 break; | 2194 break; |
| 2181 case kFloat32x4Cid: | 2195 case kFloat32x4Cid: |
| 2182 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr"); | 2196 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr"); |
| 2183 __ StoreMultipleDToOffset(value, 2, temp, | 2197 __ StoreMultipleDToOffset(value, 2, temp, |
| 2184 Float32x4::value_offset() - kHeapObjectTag); | 2198 Float32x4::value_offset() - kHeapObjectTag); |
| 2185 break; | 2199 break; |
| 2186 case kFloat64x2Cid: | 2200 case kFloat64x2Cid: |
| 2187 __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr"); | 2201 __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr"); |
| 2188 __ StoreMultipleDToOffset(value, 2, temp, | 2202 __ StoreMultipleDToOffset(value, 2, temp, |
| 2189 Float64x2::value_offset() - kHeapObjectTag); | 2203 Float64x2::value_offset() - kHeapObjectTag); |
| 2190 break; | 2204 break; |
| 2191 default: | 2205 default: |
| 2192 UNREACHABLE(); | 2206 UNREACHABLE(); |
| 2193 } | 2207 } |
| 2194 | 2208 |
| 2195 return; | 2209 return; |
| 2196 } | 2210 } |
| 2197 | 2211 |
| 2198 if (IsPotentialUnboxedStore()) { | 2212 if (IsPotentialUnboxedStore()) { |
| 2199 const Register value_reg = locs()->in(1).reg(); | 2213 const Register value_reg = locs()->in(1).reg(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2231 __ b(&store_float32x4, EQ); | 2245 __ b(&store_float32x4, EQ); |
| 2232 | 2246 |
| 2233 __ ldrh(temp2, FieldAddress(temp, Field::guarded_cid_offset())); | 2247 __ ldrh(temp2, FieldAddress(temp, Field::guarded_cid_offset())); |
| 2234 __ CompareImmediate(temp2, kFloat64x2Cid); | 2248 __ CompareImmediate(temp2, kFloat64x2Cid); |
| 2235 __ b(&store_float64x2, EQ); | 2249 __ b(&store_float64x2, EQ); |
| 2236 | 2250 |
| 2237 // Fall through. | 2251 // Fall through. |
| 2238 __ b(&store_pointer); | 2252 __ b(&store_pointer); |
| 2239 | 2253 |
| 2240 if (!compiler->is_optimizing()) { | 2254 if (!compiler->is_optimizing()) { |
| 2241 locs()->live_registers()->Add(locs()->in(0)); | 2255 locs()->live_registers()->Add(locs()->in(0)); |
| 2242 locs()->live_registers()->Add(locs()->in(1)); | 2256 locs()->live_registers()->Add(locs()->in(1)); |
| 2243 } | 2257 } |
| 2244 | 2258 |
| 2245 { | 2259 { |
| 2246 __ Bind(&store_double); | 2260 __ Bind(&store_double); |
| 2247 EnsureMutableBox(compiler, | 2261 EnsureMutableBox(compiler, this, temp, compiler->double_class(), |
| 2248 this, | 2262 instance_reg, offset_in_bytes_, temp2); |
| 2249 temp, | |
| 2250 compiler->double_class(), | |
| 2251 instance_reg, | |
| 2252 offset_in_bytes_, | |
| 2253 temp2); | |
| 2254 __ CopyDoubleField(temp, value_reg, TMP, temp2, fpu_temp); | 2263 __ CopyDoubleField(temp, value_reg, TMP, temp2, fpu_temp); |
| 2255 __ b(&skip_store); | 2264 __ b(&skip_store); |
| 2256 } | 2265 } |
| 2257 | 2266 |
| 2258 { | 2267 { |
| 2259 __ Bind(&store_float32x4); | 2268 __ Bind(&store_float32x4); |
| 2260 EnsureMutableBox(compiler, | 2269 EnsureMutableBox(compiler, this, temp, compiler->float32x4_class(), |
| 2261 this, | 2270 instance_reg, offset_in_bytes_, temp2); |
| 2262 temp, | |
| 2263 compiler->float32x4_class(), | |
| 2264 instance_reg, | |
| 2265 offset_in_bytes_, | |
| 2266 temp2); | |
| 2267 __ CopyFloat32x4Field(temp, value_reg, TMP, temp2, fpu_temp); | 2271 __ CopyFloat32x4Field(temp, value_reg, TMP, temp2, fpu_temp); |
| 2268 __ b(&skip_store); | 2272 __ b(&skip_store); |
| 2269 } | 2273 } |
| 2270 | 2274 |
| 2271 { | 2275 { |
| 2272 __ Bind(&store_float64x2); | 2276 __ Bind(&store_float64x2); |
| 2273 EnsureMutableBox(compiler, | 2277 EnsureMutableBox(compiler, this, temp, compiler->float64x2_class(), |
| 2274 this, | 2278 instance_reg, offset_in_bytes_, temp2); |
| 2275 temp, | |
| 2276 compiler->float64x2_class(), | |
| 2277 instance_reg, | |
| 2278 offset_in_bytes_, | |
| 2279 temp2); | |
| 2280 __ CopyFloat64x2Field(temp, value_reg, TMP, temp2, fpu_temp); | 2279 __ CopyFloat64x2Field(temp, value_reg, TMP, temp2, fpu_temp); |
| 2281 __ b(&skip_store); | 2280 __ b(&skip_store); |
| 2282 } | 2281 } |
| 2283 | 2282 |
| 2284 __ Bind(&store_pointer); | 2283 __ Bind(&store_pointer); |
| 2285 } | 2284 } |
| 2286 | 2285 |
| 2287 if (ShouldEmitStoreBarrier()) { | 2286 if (ShouldEmitStoreBarrier()) { |
| 2288 const Register value_reg = locs()->in(1).reg(); | 2287 const Register value_reg = locs()->in(1).reg(); |
| 2289 __ StoreIntoObjectOffset(instance_reg, | 2288 __ StoreIntoObjectOffset(instance_reg, offset_in_bytes_, value_reg, |
| 2290 offset_in_bytes_, | |
| 2291 value_reg, | |
| 2292 CanValueBeSmi()); | 2289 CanValueBeSmi()); |
| 2293 } else { | 2290 } else { |
| 2294 if (locs()->in(1).IsConstant()) { | 2291 if (locs()->in(1).IsConstant()) { |
| 2295 __ StoreIntoObjectNoBarrierOffset(instance_reg, | 2292 __ StoreIntoObjectNoBarrierOffset(instance_reg, offset_in_bytes_, |
| 2296 offset_in_bytes_, | |
| 2297 locs()->in(1).constant()); | 2293 locs()->in(1).constant()); |
| 2298 } else { | 2294 } else { |
| 2299 const Register value_reg = locs()->in(1).reg(); | 2295 const Register value_reg = locs()->in(1).reg(); |
| 2300 __ StoreIntoObjectNoBarrierOffset(instance_reg, | 2296 __ StoreIntoObjectNoBarrierOffset(instance_reg, offset_in_bytes_, |
| 2301 offset_in_bytes_, | |
| 2302 value_reg); | 2297 value_reg); |
| 2303 } | 2298 } |
| 2304 } | 2299 } |
| 2305 __ Bind(&skip_store); | 2300 __ Bind(&skip_store); |
| 2306 } | 2301 } |
| 2307 | 2302 |
| 2308 | 2303 |
| 2309 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2304 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2310 bool opt) const { | 2305 bool opt) const { |
| 2311 const intptr_t kNumInputs = 1; | 2306 const intptr_t kNumInputs = 1; |
| 2312 const intptr_t kNumTemps = 0; | 2307 const intptr_t kNumTemps = 0; |
| 2313 LocationSummary* summary = new(zone) LocationSummary( | 2308 LocationSummary* summary = new (zone) |
| 2314 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2309 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2315 summary->set_in(0, Location::RequiresRegister()); | 2310 summary->set_in(0, Location::RequiresRegister()); |
| 2316 summary->set_out(0, Location::RequiresRegister()); | 2311 summary->set_out(0, Location::RequiresRegister()); |
| 2317 return summary; | 2312 return summary; |
| 2318 } | 2313 } |
| 2319 | 2314 |
| 2320 | 2315 |
| 2321 // When the parser is building an implicit static getter for optimization, | 2316 // When the parser is building an implicit static getter for optimization, |
| 2322 // it can generate a function body where deoptimization ids do not line up | 2317 // it can generate a function body where deoptimization ids do not line up |
| 2323 // with the unoptimized code. | 2318 // with the unoptimized code. |
| 2324 // | 2319 // |
| 2325 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 2320 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
| 2326 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2321 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2327 const Register field = locs()->in(0).reg(); | 2322 const Register field = locs()->in(0).reg(); |
| 2328 const Register result = locs()->out(0).reg(); | 2323 const Register result = locs()->out(0).reg(); |
| 2329 __ LoadFieldFromOffset(kWord, result, field, Field::static_value_offset()); | 2324 __ LoadFieldFromOffset(kWord, result, field, Field::static_value_offset()); |
| 2330 } | 2325 } |
| 2331 | 2326 |
| 2332 | 2327 |
| 2333 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2328 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2334 bool opt) const { | 2329 bool opt) const { |
| 2335 LocationSummary* locs = new(zone) LocationSummary( | 2330 LocationSummary* locs = |
| 2336 zone, 1, 1, LocationSummary::kNoCall); | 2331 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); |
| 2337 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 2332 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 2338 : Location::RequiresRegister()); | 2333 : Location::RequiresRegister()); |
| 2339 locs->set_temp(0, Location::RequiresRegister()); | 2334 locs->set_temp(0, Location::RequiresRegister()); |
| 2340 return locs; | 2335 return locs; |
| 2341 } | 2336 } |
| 2342 | 2337 |
| 2343 | 2338 |
| 2344 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2339 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2345 const Register value = locs()->in(0).reg(); | 2340 const Register value = locs()->in(0).reg(); |
| 2346 const Register temp = locs()->temp(0).reg(); | 2341 const Register temp = locs()->temp(0).reg(); |
| 2347 | 2342 |
| 2348 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 2343 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
| 2349 if (this->value()->NeedsStoreBuffer()) { | 2344 if (this->value()->NeedsStoreBuffer()) { |
| 2350 __ StoreIntoObject(temp, | 2345 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), |
| 2351 FieldAddress(temp, Field::static_value_offset()), | 2346 value, CanValueBeSmi()); |
| 2352 value, | |
| 2353 CanValueBeSmi()); | |
| 2354 } else { | 2347 } else { |
| 2355 __ StoreIntoObjectNoBarrier( | 2348 __ StoreIntoObjectNoBarrier( |
| 2356 temp, FieldAddress(temp, Field::static_value_offset()), value); | 2349 temp, FieldAddress(temp, Field::static_value_offset()), value); |
| 2357 } | 2350 } |
| 2358 } | 2351 } |
| 2359 | 2352 |
| 2360 | 2353 |
| 2361 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 2354 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
| 2362 bool opt) const { | 2355 bool opt) const { |
| 2363 const intptr_t kNumInputs = 2; | 2356 const intptr_t kNumInputs = 2; |
| 2364 const intptr_t kNumTemps = 0; | 2357 const intptr_t kNumTemps = 0; |
| 2365 LocationSummary* summary = new(zone) LocationSummary( | 2358 LocationSummary* summary = new (zone) |
| 2366 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2359 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2367 summary->set_in(0, Location::RegisterLocation(R0)); | 2360 summary->set_in(0, Location::RegisterLocation(R0)); |
| 2368 summary->set_in(1, Location::RegisterLocation(R1)); | 2361 summary->set_in(1, Location::RegisterLocation(R1)); |
| 2369 summary->set_out(0, Location::RegisterLocation(R0)); | 2362 summary->set_out(0, Location::RegisterLocation(R0)); |
| 2370 return summary; | 2363 return summary; |
| 2371 } | 2364 } |
| 2372 | 2365 |
| 2373 | 2366 |
| 2374 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2367 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2375 ASSERT(locs()->in(0).reg() == R0); // Value. | 2368 ASSERT(locs()->in(0).reg() == R0); // Value. |
| 2376 ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments. | 2369 ASSERT(locs()->in(1).reg() == R1); // Instantiator type arguments. |
| 2377 | 2370 |
| 2378 compiler->GenerateInstanceOf(token_pos(), | 2371 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), negate_result(), |
| 2379 deopt_id(), | |
| 2380 type(), | |
| 2381 negate_result(), | |
| 2382 locs()); | 2372 locs()); |
| 2383 ASSERT(locs()->out(0).reg() == R0); | 2373 ASSERT(locs()->out(0).reg() == R0); |
| 2384 } | 2374 } |
| 2385 | 2375 |
| 2386 | 2376 |
| 2387 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 2377 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
| 2388 bool opt) const { | 2378 bool opt) const { |
| 2389 const intptr_t kNumInputs = 2; | 2379 const intptr_t kNumInputs = 2; |
| 2390 const intptr_t kNumTemps = 0; | 2380 const intptr_t kNumTemps = 0; |
| 2391 LocationSummary* locs = new(zone) LocationSummary( | 2381 LocationSummary* locs = new (zone) |
| 2392 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2382 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2393 locs->set_in(kElementTypePos, Location::RegisterLocation(R1)); | 2383 locs->set_in(kElementTypePos, Location::RegisterLocation(R1)); |
| 2394 locs->set_in(kLengthPos, Location::RegisterLocation(R2)); | 2384 locs->set_in(kLengthPos, Location::RegisterLocation(R2)); |
| 2395 locs->set_out(0, Location::RegisterLocation(R0)); | 2385 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2396 return locs; | 2386 return locs; |
| 2397 } | 2387 } |
| 2398 | 2388 |
| 2399 | 2389 |
| 2400 // Inlines array allocation for known constant values. | 2390 // Inlines array allocation for known constant values. |
| 2401 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 2391 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
| 2402 intptr_t num_elements, | 2392 intptr_t num_elements, |
| 2403 Label* slow_path, | 2393 Label* slow_path, |
| 2404 Label* done) { | 2394 Label* done) { |
| 2405 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. | 2395 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. |
| 2406 const Register kLengthReg = R2; | 2396 const Register kLengthReg = R2; |
| 2407 const Register kElemTypeReg = R1; | 2397 const Register kElemTypeReg = R1; |
| 2408 const intptr_t instance_size = Array::InstanceSize(num_elements); | 2398 const intptr_t instance_size = Array::InstanceSize(num_elements); |
| 2409 | 2399 |
| 2410 __ TryAllocateArray(kArrayCid, instance_size, slow_path, | 2400 __ TryAllocateArray(kArrayCid, instance_size, slow_path, |
| 2411 R0, // instance | 2401 R0, // instance |
| 2412 R3, // end address | 2402 R3, // end address |
| 2413 R8, | 2403 R8, R6); |
| 2414 R6); | |
| 2415 // R0: new object start as a tagged pointer. | 2404 // R0: new object start as a tagged pointer. |
| 2416 // R3: new object end address. | 2405 // R3: new object end address. |
| 2417 | 2406 |
| 2418 // Store the type argument field. | 2407 // Store the type argument field. |
| 2419 __ StoreIntoObjectNoBarrier(R0, | 2408 __ StoreIntoObjectNoBarrier( |
| 2420 FieldAddress(R0, Array::type_arguments_offset()), | 2409 R0, FieldAddress(R0, Array::type_arguments_offset()), kElemTypeReg); |
| 2421 kElemTypeReg); | |
| 2422 | 2410 |
| 2423 // Set the length field. | 2411 // Set the length field. |
| 2424 __ StoreIntoObjectNoBarrier(R0, | 2412 __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, Array::length_offset()), |
| 2425 FieldAddress(R0, Array::length_offset()), | |
| 2426 kLengthReg); | 2413 kLengthReg); |
| 2427 | 2414 |
| 2428 // Initialize all array elements to raw_null. | 2415 // Initialize all array elements to raw_null. |
| 2429 // R0: new object start as a tagged pointer. | 2416 // R0: new object start as a tagged pointer. |
| 2430 // R3: new object end address. | 2417 // R3: new object end address. |
| 2431 // R6: iterator which initially points to the start of the variable | 2418 // R6: iterator which initially points to the start of the variable |
| 2432 // data area to be initialized. | 2419 // data area to be initialized. |
| 2433 // R8: null | 2420 // R8: null |
| 2434 if (num_elements > 0) { | 2421 if (num_elements > 0) { |
| 2435 const intptr_t array_size = instance_size - sizeof(RawArray); | 2422 const intptr_t array_size = instance_size - sizeof(RawArray); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2455 | 2442 |
| 2456 | 2443 |
| 2457 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2444 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2458 const Register kLengthReg = R2; | 2445 const Register kLengthReg = R2; |
| 2459 const Register kElemTypeReg = R1; | 2446 const Register kElemTypeReg = R1; |
| 2460 const Register kResultReg = R0; | 2447 const Register kResultReg = R0; |
| 2461 | 2448 |
| 2462 ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg); | 2449 ASSERT(locs()->in(kElementTypePos).reg() == kElemTypeReg); |
| 2463 ASSERT(locs()->in(kLengthPos).reg() == kLengthReg); | 2450 ASSERT(locs()->in(kLengthPos).reg() == kLengthReg); |
| 2464 | 2451 |
| 2465 if (compiler->is_optimizing() && | 2452 if (compiler->is_optimizing() && !FLAG_precompiled_mode && |
| 2466 !FLAG_precompiled_mode && | |
| 2467 num_elements()->BindsToConstant() && | 2453 num_elements()->BindsToConstant() && |
| 2468 num_elements()->BoundConstant().IsSmi()) { | 2454 num_elements()->BoundConstant().IsSmi()) { |
| 2469 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); | 2455 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); |
| 2470 if ((length >= 0) && (length <= Array::kMaxElements)) { | 2456 if ((length >= 0) && (length <= Array::kMaxElements)) { |
| 2471 Label slow_path, done; | 2457 Label slow_path, done; |
| 2472 InlineArrayAllocation(compiler, length, &slow_path, &done); | 2458 InlineArrayAllocation(compiler, length, &slow_path, &done); |
| 2473 __ Bind(&slow_path); | 2459 __ Bind(&slow_path); |
| 2474 __ PushObject(Object::null_object()); // Make room for the result. | 2460 __ PushObject(Object::null_object()); // Make room for the result. |
| 2475 __ Push(kLengthReg); // length. | 2461 __ Push(kLengthReg); // length. |
| 2476 __ Push(kElemTypeReg); | 2462 __ Push(kElemTypeReg); |
| 2477 compiler->GenerateRuntimeCall(token_pos(), | 2463 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2478 deopt_id(), | 2464 kAllocateArrayRuntimeEntry, 2, locs()); |
| 2479 kAllocateArrayRuntimeEntry, | |
| 2480 2, | |
| 2481 locs()); | |
| 2482 __ Drop(2); | 2465 __ Drop(2); |
| 2483 __ Pop(kResultReg); | 2466 __ Pop(kResultReg); |
| 2484 __ Bind(&done); | 2467 __ Bind(&done); |
| 2485 return; | 2468 return; |
| 2486 } | 2469 } |
| 2487 } | 2470 } |
| 2488 const Code& stub = Code::ZoneHandle(compiler->zone(), | 2471 const Code& stub = Code::ZoneHandle(compiler->zone(), |
| 2489 StubCode::AllocateArray_entry()->code()); | 2472 StubCode::AllocateArray_entry()->code()); |
| 2490 compiler->AddStubCallTarget(stub); | 2473 compiler->AddStubCallTarget(stub); |
| 2491 compiler->GenerateCall(token_pos(), | 2474 compiler->GenerateCall(token_pos(), *StubCode::AllocateArray_entry(), |
| 2492 *StubCode::AllocateArray_entry(), | 2475 RawPcDescriptors::kOther, locs()); |
| 2493 RawPcDescriptors::kOther, | |
| 2494 locs()); | |
| 2495 ASSERT(locs()->out(0).reg() == kResultReg); | 2476 ASSERT(locs()->out(0).reg() == kResultReg); |
| 2496 } | 2477 } |
| 2497 | 2478 |
| 2498 | 2479 |
| 2499 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 2480 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |
| 2500 bool opt) const { | 2481 bool opt) const { |
| 2501 const intptr_t kNumInputs = 1; | 2482 const intptr_t kNumInputs = 1; |
| 2502 const intptr_t kNumTemps = | 2483 const intptr_t kNumTemps = |
| 2503 (IsUnboxedLoad() && opt) ? 1 : | 2484 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 3 : 0); |
| 2504 ((IsPotentialUnboxedLoad()) ? 3 : 0); | |
| 2505 | 2485 |
| 2506 LocationSummary* locs = new(zone) LocationSummary( | 2486 LocationSummary* locs = new (zone) LocationSummary( |
| 2507 zone, kNumInputs, kNumTemps, | 2487 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) |
| 2508 (opt && !IsPotentialUnboxedLoad()) | 2488 ? LocationSummary::kNoCall |
| 2509 ? LocationSummary::kNoCall | 2489 : LocationSummary::kCallOnSlowPath); |
| 2510 : LocationSummary::kCallOnSlowPath); | |
| 2511 | 2490 |
| 2512 locs->set_in(0, Location::RequiresRegister()); | 2491 locs->set_in(0, Location::RequiresRegister()); |
| 2513 | 2492 |
| 2514 if (IsUnboxedLoad() && opt) { | 2493 if (IsUnboxedLoad() && opt) { |
| 2515 locs->set_temp(0, Location::RequiresRegister()); | 2494 locs->set_temp(0, Location::RequiresRegister()); |
| 2516 } else if (IsPotentialUnboxedLoad()) { | 2495 } else if (IsPotentialUnboxedLoad()) { |
| 2517 locs->set_temp(0, opt ? Location::RequiresFpuRegister() | 2496 locs->set_temp(0, opt ? Location::RequiresFpuRegister() |
| 2518 : Location::FpuRegisterLocation(Q1)); | 2497 : Location::FpuRegisterLocation(Q1)); |
| 2519 locs->set_temp(1, Location::RequiresRegister()); | 2498 locs->set_temp(1, Location::RequiresRegister()); |
| 2520 locs->set_temp(2, Location::RequiresRegister()); | 2499 locs->set_temp(2, Location::RequiresRegister()); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2535 const intptr_t cid = field()->UnboxedFieldCid(); | 2514 const intptr_t cid = field()->UnboxedFieldCid(); |
| 2536 switch (cid) { | 2515 switch (cid) { |
| 2537 case kDoubleCid: | 2516 case kDoubleCid: |
| 2538 __ Comment("UnboxedDoubleLoadFieldInstr"); | 2517 __ Comment("UnboxedDoubleLoadFieldInstr"); |
| 2539 __ LoadDFromOffset(result, temp, | 2518 __ LoadDFromOffset(result, temp, |
| 2540 Double::value_offset() - kHeapObjectTag); | 2519 Double::value_offset() - kHeapObjectTag); |
| 2541 break; | 2520 break; |
| 2542 case kFloat32x4Cid: | 2521 case kFloat32x4Cid: |
| 2543 __ Comment("UnboxedFloat32x4LoadFieldInstr"); | 2522 __ Comment("UnboxedFloat32x4LoadFieldInstr"); |
| 2544 __ LoadMultipleDFromOffset(result, 2, temp, | 2523 __ LoadMultipleDFromOffset(result, 2, temp, |
| 2545 Float32x4::value_offset() - kHeapObjectTag); | 2524 Float32x4::value_offset() - kHeapObjectTag); |
| 2546 break; | 2525 break; |
| 2547 case kFloat64x2Cid: | 2526 case kFloat64x2Cid: |
| 2548 __ Comment("UnboxedFloat64x2LoadFieldInstr"); | 2527 __ Comment("UnboxedFloat64x2LoadFieldInstr"); |
| 2549 __ LoadMultipleDFromOffset(result, 2, temp, | 2528 __ LoadMultipleDFromOffset(result, 2, temp, |
| 2550 Float64x2::value_offset() - kHeapObjectTag); | 2529 Float64x2::value_offset() - kHeapObjectTag); |
| 2551 break; | 2530 break; |
| 2552 default: | 2531 default: |
| 2553 UNREACHABLE(); | 2532 UNREACHABLE(); |
| 2554 } | 2533 } |
| 2555 return; | 2534 return; |
| 2556 } | 2535 } |
| 2557 | 2536 |
| 2558 Label done; | 2537 Label done; |
| 2559 const Register result_reg = locs()->out(0).reg(); | 2538 const Register result_reg = locs()->out(0).reg(); |
| 2560 if (IsPotentialUnboxedLoad()) { | 2539 if (IsPotentialUnboxedLoad()) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2591 | 2570 |
| 2592 // Fall through. | 2571 // Fall through. |
| 2593 __ b(&load_pointer); | 2572 __ b(&load_pointer); |
| 2594 | 2573 |
| 2595 if (!compiler->is_optimizing()) { | 2574 if (!compiler->is_optimizing()) { |
| 2596 locs()->live_registers()->Add(locs()->in(0)); | 2575 locs()->live_registers()->Add(locs()->in(0)); |
| 2597 } | 2576 } |
| 2598 | 2577 |
| 2599 { | 2578 { |
| 2600 __ Bind(&load_double); | 2579 __ Bind(&load_double); |
| 2601 BoxAllocationSlowPath::Allocate( | 2580 BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(), |
| 2602 compiler, | 2581 result_reg, temp); |
| 2603 this, | |
| 2604 compiler->double_class(), | |
| 2605 result_reg, | |
| 2606 temp); | |
| 2607 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2582 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 2608 __ CopyDoubleField(result_reg, temp, TMP, temp2, value); | 2583 __ CopyDoubleField(result_reg, temp, TMP, temp2, value); |
| 2609 __ b(&done); | 2584 __ b(&done); |
| 2610 } | 2585 } |
| 2611 | 2586 |
| 2612 { | 2587 { |
| 2613 __ Bind(&load_float32x4); | 2588 __ Bind(&load_float32x4); |
| 2614 BoxAllocationSlowPath::Allocate( | 2589 BoxAllocationSlowPath::Allocate( |
| 2615 compiler, | 2590 compiler, this, compiler->float32x4_class(), result_reg, temp); |
| 2616 this, | |
| 2617 compiler->float32x4_class(), | |
| 2618 result_reg, | |
| 2619 temp); | |
| 2620 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2591 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 2621 __ CopyFloat32x4Field(result_reg, temp, TMP, temp2, value); | 2592 __ CopyFloat32x4Field(result_reg, temp, TMP, temp2, value); |
| 2622 __ b(&done); | 2593 __ b(&done); |
| 2623 } | 2594 } |
| 2624 | 2595 |
| 2625 { | 2596 { |
| 2626 __ Bind(&load_float64x2); | 2597 __ Bind(&load_float64x2); |
| 2627 BoxAllocationSlowPath::Allocate( | 2598 BoxAllocationSlowPath::Allocate( |
| 2628 compiler, | 2599 compiler, this, compiler->float64x2_class(), result_reg, temp); |
| 2629 this, | |
| 2630 compiler->float64x2_class(), | |
| 2631 result_reg, | |
| 2632 temp); | |
| 2633 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2600 __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 2634 __ CopyFloat64x2Field(result_reg, temp, TMP, temp2, value); | 2601 __ CopyFloat64x2Field(result_reg, temp, TMP, temp2, value); |
| 2635 __ b(&done); | 2602 __ b(&done); |
| 2636 } | 2603 } |
| 2637 | 2604 |
| 2638 __ Bind(&load_pointer); | 2605 __ Bind(&load_pointer); |
| 2639 } | 2606 } |
| 2640 __ LoadFieldFromOffset(kWord, result_reg, instance_reg, offset_in_bytes()); | 2607 __ LoadFieldFromOffset(kWord, result_reg, instance_reg, offset_in_bytes()); |
| 2641 __ Bind(&done); | 2608 __ Bind(&done); |
| 2642 } | 2609 } |
| 2643 | 2610 |
| 2644 | 2611 |
| 2645 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2612 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
| 2646 bool opt) const { | 2613 bool opt) const { |
| 2647 const intptr_t kNumInputs = 1; | 2614 const intptr_t kNumInputs = 1; |
| 2648 const intptr_t kNumTemps = 0; | 2615 const intptr_t kNumTemps = 0; |
| 2649 LocationSummary* locs = new(zone) LocationSummary( | 2616 LocationSummary* locs = new (zone) |
| 2650 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2617 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2651 locs->set_in(0, Location::RegisterLocation(R0)); | 2618 locs->set_in(0, Location::RegisterLocation(R0)); |
| 2652 locs->set_out(0, Location::RegisterLocation(R0)); | 2619 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2653 return locs; | 2620 return locs; |
| 2654 } | 2621 } |
| 2655 | 2622 |
| 2656 | 2623 |
| 2657 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2624 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2658 const Register instantiator_reg = locs()->in(0).reg(); | 2625 const Register instantiator_reg = locs()->in(0).reg(); |
| 2659 const Register result_reg = locs()->out(0).reg(); | 2626 const Register result_reg = locs()->out(0).reg(); |
| 2660 | 2627 |
| 2661 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2628 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
| 2662 // A runtime call to instantiate the type is required. | 2629 // A runtime call to instantiate the type is required. |
| 2663 __ PushObject(Object::null_object()); // Make room for the result. | 2630 __ PushObject(Object::null_object()); // Make room for the result. |
| 2664 __ PushObject(type()); | 2631 __ PushObject(type()); |
| 2665 __ Push(instantiator_reg); // Push instantiator type arguments. | 2632 __ Push(instantiator_reg); // Push instantiator type arguments. |
| 2666 compiler->GenerateRuntimeCall(token_pos(), | 2633 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2667 deopt_id(), | 2634 kInstantiateTypeRuntimeEntry, 2, locs()); |
| 2668 kInstantiateTypeRuntimeEntry, | 2635 __ Drop(2); // Drop instantiator and uninstantiated type. |
| 2669 2, | |
| 2670 locs()); | |
| 2671 __ Drop(2); // Drop instantiator and uninstantiated type. | |
| 2672 __ Pop(result_reg); // Pop instantiated type. | 2636 __ Pop(result_reg); // Pop instantiated type. |
| 2673 ASSERT(instantiator_reg == result_reg); | 2637 ASSERT(instantiator_reg == result_reg); |
| 2674 } | 2638 } |
| 2675 | 2639 |
| 2676 | 2640 |
| 2677 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2641 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
| 2678 Zone* zone, bool opt) const { | 2642 Zone* zone, |
| 2643 bool opt) const { |
| 2679 const intptr_t kNumInputs = 1; | 2644 const intptr_t kNumInputs = 1; |
| 2680 const intptr_t kNumTemps = 0; | 2645 const intptr_t kNumTemps = 0; |
| 2681 LocationSummary* locs = new(zone) LocationSummary( | 2646 LocationSummary* locs = new (zone) |
| 2682 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2647 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2683 locs->set_in(0, Location::RegisterLocation(R0)); | 2648 locs->set_in(0, Location::RegisterLocation(R0)); |
| 2684 locs->set_out(0, Location::RegisterLocation(R0)); | 2649 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2685 return locs; | 2650 return locs; |
| 2686 } | 2651 } |
| 2687 | 2652 |
| 2688 | 2653 |
| 2689 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2654 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
| 2690 FlowGraphCompiler* compiler) { | 2655 FlowGraphCompiler* compiler) { |
| 2691 const Register instantiator_reg = locs()->in(0).reg(); | 2656 const Register instantiator_reg = locs()->in(0).reg(); |
| 2692 const Register result_reg = locs()->out(0).reg(); | 2657 const Register result_reg = locs()->out(0).reg(); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2725 __ Bind(&found); | 2690 __ Bind(&found); |
| 2726 __ ldr(R0, Address(R2, 1 * kWordSize)); // Cached instantiated args. | 2691 __ ldr(R0, Address(R2, 1 * kWordSize)); // Cached instantiated args. |
| 2727 __ b(&type_arguments_instantiated); | 2692 __ b(&type_arguments_instantiated); |
| 2728 | 2693 |
| 2729 __ Bind(&slow_case); | 2694 __ Bind(&slow_case); |
| 2730 // Instantiate non-null type arguments. | 2695 // Instantiate non-null type arguments. |
| 2731 // A runtime call to instantiate the type arguments is required. | 2696 // A runtime call to instantiate the type arguments is required. |
| 2732 __ PushObject(Object::null_object()); // Make room for the result. | 2697 __ PushObject(Object::null_object()); // Make room for the result. |
| 2733 __ PushObject(type_arguments()); | 2698 __ PushObject(type_arguments()); |
| 2734 __ Push(instantiator_reg); // Push instantiator type arguments. | 2699 __ Push(instantiator_reg); // Push instantiator type arguments. |
| 2735 compiler->GenerateRuntimeCall(token_pos(), | 2700 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2736 deopt_id(), | 2701 kInstantiateTypeArgumentsRuntimeEntry, 2, |
| 2737 kInstantiateTypeArgumentsRuntimeEntry, | |
| 2738 2, | |
| 2739 locs()); | 2702 locs()); |
| 2740 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 2703 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 2741 __ Pop(result_reg); // Pop instantiated type arguments. | 2704 __ Pop(result_reg); // Pop instantiated type arguments. |
| 2742 __ Bind(&type_arguments_instantiated); | 2705 __ Bind(&type_arguments_instantiated); |
| 2743 } | 2706 } |
| 2744 | 2707 |
| 2745 | 2708 |
| 2746 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2709 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
| 2747 Zone* zone, | 2710 Zone* zone, |
| 2748 bool opt) const { | 2711 bool opt) const { |
| 2749 ASSERT(opt); | 2712 ASSERT(opt); |
| 2750 const intptr_t kNumInputs = 0; | 2713 const intptr_t kNumInputs = 0; |
| 2751 const intptr_t kNumTemps = 3; | 2714 const intptr_t kNumTemps = 3; |
| 2752 LocationSummary* locs = new(zone) LocationSummary( | 2715 LocationSummary* locs = new (zone) LocationSummary( |
| 2753 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2716 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2754 locs->set_temp(0, Location::RegisterLocation(R1)); | 2717 locs->set_temp(0, Location::RegisterLocation(R1)); |
| 2755 locs->set_temp(1, Location::RegisterLocation(R2)); | 2718 locs->set_temp(1, Location::RegisterLocation(R2)); |
| 2756 locs->set_temp(2, Location::RegisterLocation(R3)); | 2719 locs->set_temp(2, Location::RegisterLocation(R3)); |
| 2757 locs->set_out(0, Location::RegisterLocation(R0)); | 2720 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2758 return locs; | 2721 return locs; |
| 2759 } | 2722 } |
| 2760 | 2723 |
| 2761 | 2724 |
| 2762 class AllocateContextSlowPath : public SlowPathCode { | 2725 class AllocateContextSlowPath : public SlowPathCode { |
| 2763 public: | 2726 public: |
| 2764 explicit AllocateContextSlowPath( | 2727 explicit AllocateContextSlowPath( |
| 2765 AllocateUninitializedContextInstr* instruction) | 2728 AllocateUninitializedContextInstr* instruction) |
| 2766 : instruction_(instruction) { } | 2729 : instruction_(instruction) {} |
| 2767 | 2730 |
| 2768 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2731 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2769 __ Comment("AllocateContextSlowPath"); | 2732 __ Comment("AllocateContextSlowPath"); |
| 2770 __ Bind(entry_label()); | 2733 __ Bind(entry_label()); |
| 2771 | 2734 |
| 2772 LocationSummary* locs = instruction_->locs(); | 2735 LocationSummary* locs = instruction_->locs(); |
| 2773 locs->live_registers()->Remove(locs->out(0)); | 2736 locs->live_registers()->Remove(locs->out(0)); |
| 2774 | 2737 |
| 2775 compiler->SaveLiveRegisters(locs); | 2738 compiler->SaveLiveRegisters(locs); |
| 2776 | 2739 |
| 2777 __ LoadImmediate(R1, instruction_->num_context_variables()); | 2740 __ LoadImmediate(R1, instruction_->num_context_variables()); |
| 2778 const Code& stub = Code::ZoneHandle( | 2741 const Code& stub = Code::ZoneHandle( |
| 2779 compiler->zone(), StubCode::AllocateContext_entry()->code()); | 2742 compiler->zone(), StubCode::AllocateContext_entry()->code()); |
| 2780 compiler->AddStubCallTarget(stub); | 2743 compiler->AddStubCallTarget(stub); |
| 2781 compiler->GenerateCall(instruction_->token_pos(), | 2744 compiler->GenerateCall(instruction_->token_pos(), |
| 2782 *StubCode::AllocateContext_entry(), | 2745 *StubCode::AllocateContext_entry(), |
| 2783 RawPcDescriptors::kOther, | 2746 RawPcDescriptors::kOther, locs); |
| 2784 locs); | |
| 2785 ASSERT(instruction_->locs()->out(0).reg() == R0); | 2747 ASSERT(instruction_->locs()->out(0).reg() == R0); |
| 2786 compiler->RestoreLiveRegisters(instruction_->locs()); | 2748 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2787 __ b(exit_label()); | 2749 __ b(exit_label()); |
| 2788 } | 2750 } |
| 2789 | 2751 |
| 2790 private: | 2752 private: |
| 2791 AllocateUninitializedContextInstr* instruction_; | 2753 AllocateUninitializedContextInstr* instruction_; |
| 2792 }; | 2754 }; |
| 2793 | 2755 |
| 2794 | 2756 |
| 2795 void AllocateUninitializedContextInstr::EmitNativeCode( | 2757 void AllocateUninitializedContextInstr::EmitNativeCode( |
| 2796 FlowGraphCompiler* compiler) { | 2758 FlowGraphCompiler* compiler) { |
| 2797 Register temp0 = locs()->temp(0).reg(); | 2759 Register temp0 = locs()->temp(0).reg(); |
| 2798 Register temp1 = locs()->temp(1).reg(); | 2760 Register temp1 = locs()->temp(1).reg(); |
| 2799 Register temp2 = locs()->temp(2).reg(); | 2761 Register temp2 = locs()->temp(2).reg(); |
| 2800 Register result = locs()->out(0).reg(); | 2762 Register result = locs()->out(0).reg(); |
| 2801 // Try allocate the object. | 2763 // Try allocate the object. |
| 2802 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2764 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
| 2803 compiler->AddSlowPathCode(slow_path); | 2765 compiler->AddSlowPathCode(slow_path); |
| 2804 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2766 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
| 2805 | 2767 |
| 2806 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 2768 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
| 2807 result, // instance | 2769 result, // instance |
| 2808 temp0, | 2770 temp0, temp1, temp2); |
| 2809 temp1, | |
| 2810 temp2); | |
| 2811 | 2771 |
| 2812 // Setup up number of context variables field. | 2772 // Setup up number of context variables field. |
| 2813 __ LoadImmediate(temp0, num_context_variables()); | 2773 __ LoadImmediate(temp0, num_context_variables()); |
| 2814 __ str(temp0, FieldAddress(result, Context::num_variables_offset())); | 2774 __ str(temp0, FieldAddress(result, Context::num_variables_offset())); |
| 2815 | 2775 |
| 2816 __ Bind(slow_path->exit_label()); | 2776 __ Bind(slow_path->exit_label()); |
| 2817 } | 2777 } |
| 2818 | 2778 |
| 2819 | 2779 |
| 2820 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 2780 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |
| 2821 bool opt) const { | 2781 bool opt) const { |
| 2822 const intptr_t kNumInputs = 0; | 2782 const intptr_t kNumInputs = 0; |
| 2823 const intptr_t kNumTemps = 1; | 2783 const intptr_t kNumTemps = 1; |
| 2824 LocationSummary* locs = new(zone) LocationSummary( | 2784 LocationSummary* locs = new (zone) |
| 2825 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2785 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2826 locs->set_temp(0, Location::RegisterLocation(R1)); | 2786 locs->set_temp(0, Location::RegisterLocation(R1)); |
| 2827 locs->set_out(0, Location::RegisterLocation(R0)); | 2787 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2828 return locs; | 2788 return locs; |
| 2829 } | 2789 } |
| 2830 | 2790 |
| 2831 | 2791 |
| 2832 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2792 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2833 ASSERT(locs()->temp(0).reg() == R1); | 2793 ASSERT(locs()->temp(0).reg() == R1); |
| 2834 ASSERT(locs()->out(0).reg() == R0); | 2794 ASSERT(locs()->out(0).reg() == R0); |
| 2835 | 2795 |
| 2836 __ LoadImmediate(R1, num_context_variables()); | 2796 __ LoadImmediate(R1, num_context_variables()); |
| 2837 compiler->GenerateCall(token_pos(), | 2797 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), |
| 2838 *StubCode::AllocateContext_entry(), | 2798 RawPcDescriptors::kOther, locs()); |
| 2839 RawPcDescriptors::kOther, | |
| 2840 locs()); | |
| 2841 } | 2799 } |
| 2842 | 2800 |
| 2843 | 2801 |
| 2844 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2802 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2845 bool opt) const { | 2803 bool opt) const { |
| 2846 const intptr_t kNumInputs = 1; | 2804 const intptr_t kNumInputs = 1; |
| 2847 const intptr_t kNumTemps = 1; | 2805 const intptr_t kNumTemps = 1; |
| 2848 LocationSummary* locs = new(zone) LocationSummary( | 2806 LocationSummary* locs = new (zone) |
| 2849 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2807 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2850 locs->set_in(0, Location::RegisterLocation(R0)); | 2808 locs->set_in(0, Location::RegisterLocation(R0)); |
| 2851 locs->set_temp(0, Location::RegisterLocation(R1)); | 2809 locs->set_temp(0, Location::RegisterLocation(R1)); |
| 2852 return locs; | 2810 return locs; |
| 2853 } | 2811 } |
| 2854 | 2812 |
| 2855 | 2813 |
| 2856 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2814 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2857 Register field = locs()->in(0).reg(); | 2815 Register field = locs()->in(0).reg(); |
| 2858 Register temp = locs()->temp(0).reg(); | 2816 Register temp = locs()->temp(0).reg(); |
| 2859 Label call_runtime, no_call; | 2817 Label call_runtime, no_call; |
| 2860 | 2818 |
| 2861 __ ldr(temp, FieldAddress(field, Field::static_value_offset())); | 2819 __ ldr(temp, FieldAddress(field, Field::static_value_offset())); |
| 2862 __ CompareObject(temp, Object::sentinel()); | 2820 __ CompareObject(temp, Object::sentinel()); |
| 2863 __ b(&call_runtime, EQ); | 2821 __ b(&call_runtime, EQ); |
| 2864 | 2822 |
| 2865 __ CompareObject(temp, Object::transition_sentinel()); | 2823 __ CompareObject(temp, Object::transition_sentinel()); |
| 2866 __ b(&no_call, NE); | 2824 __ b(&no_call, NE); |
| 2867 | 2825 |
| 2868 __ Bind(&call_runtime); | 2826 __ Bind(&call_runtime); |
| 2869 __ PushObject(Object::null_object()); // Make room for (unused) result. | 2827 __ PushObject(Object::null_object()); // Make room for (unused) result. |
| 2870 __ Push(field); | 2828 __ Push(field); |
| 2871 compiler->GenerateRuntimeCall(token_pos(), | 2829 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2872 deopt_id(), | 2830 kInitStaticFieldRuntimeEntry, 1, locs()); |
| 2873 kInitStaticFieldRuntimeEntry, | |
| 2874 1, | |
| 2875 locs()); | |
| 2876 __ Drop(2); // Remove argument and result placeholder. | 2831 __ Drop(2); // Remove argument and result placeholder. |
| 2877 __ Bind(&no_call); | 2832 __ Bind(&no_call); |
| 2878 } | 2833 } |
| 2879 | 2834 |
| 2880 | 2835 |
| 2881 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2836 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
| 2882 bool opt) const { | 2837 bool opt) const { |
| 2883 const intptr_t kNumInputs = 1; | 2838 const intptr_t kNumInputs = 1; |
| 2884 const intptr_t kNumTemps = 0; | 2839 const intptr_t kNumTemps = 0; |
| 2885 LocationSummary* locs = new(zone) LocationSummary( | 2840 LocationSummary* locs = new (zone) |
| 2886 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2841 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2887 locs->set_in(0, Location::RegisterLocation(R0)); | 2842 locs->set_in(0, Location::RegisterLocation(R0)); |
| 2888 locs->set_out(0, Location::RegisterLocation(R0)); | 2843 locs->set_out(0, Location::RegisterLocation(R0)); |
| 2889 return locs; | 2844 return locs; |
| 2890 } | 2845 } |
| 2891 | 2846 |
| 2892 | 2847 |
| 2893 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2848 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2894 const Register context_value = locs()->in(0).reg(); | 2849 const Register context_value = locs()->in(0).reg(); |
| 2895 const Register result = locs()->out(0).reg(); | 2850 const Register result = locs()->out(0).reg(); |
| 2896 | 2851 |
| 2897 __ PushObject(Object::null_object()); // Make room for the result. | 2852 __ PushObject(Object::null_object()); // Make room for the result. |
| 2898 __ Push(context_value); | 2853 __ Push(context_value); |
| 2899 compiler->GenerateRuntimeCall(token_pos(), | 2854 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2900 deopt_id(), | 2855 kCloneContextRuntimeEntry, 1, locs()); |
| 2901 kCloneContextRuntimeEntry, | 2856 __ Drop(1); // Remove argument. |
| 2902 1, | |
| 2903 locs()); | |
| 2904 __ Drop(1); // Remove argument. | |
| 2905 __ Pop(result); // Get result (cloned context). | 2857 __ Pop(result); // Get result (cloned context). |
| 2906 } | 2858 } |
| 2907 | 2859 |
| 2908 | 2860 |
| 2909 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2861 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
| 2910 bool opt) const { | 2862 bool opt) const { |
| 2911 UNREACHABLE(); | 2863 UNREACHABLE(); |
| 2912 return NULL; | 2864 return NULL; |
| 2913 } | 2865 } |
| 2914 | 2866 |
| 2915 | 2867 |
| 2916 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2868 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2917 __ Bind(compiler->GetJumpLabel(this)); | 2869 __ Bind(compiler->GetJumpLabel(this)); |
| 2918 compiler->AddExceptionHandler(catch_try_index(), | 2870 compiler->AddExceptionHandler(catch_try_index(), try_index(), |
| 2919 try_index(), | |
| 2920 compiler->assembler()->CodeSize(), | 2871 compiler->assembler()->CodeSize(), |
| 2921 catch_handler_types_, | 2872 catch_handler_types_, needs_stacktrace()); |
| 2922 needs_stacktrace()); | |
| 2923 // On lazy deoptimization we patch the optimized code here to enter the | 2873 // On lazy deoptimization we patch the optimized code here to enter the |
| 2924 // deoptimization stub. | 2874 // deoptimization stub. |
| 2925 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 2875 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |
| 2926 if (compiler->is_optimizing()) { | 2876 if (compiler->is_optimizing()) { |
| 2927 compiler->AddDeoptIndexAtCall(deopt_id); | 2877 compiler->AddDeoptIndexAtCall(deopt_id); |
| 2928 } else { | 2878 } else { |
| 2929 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 2879 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id, |
| 2930 deopt_id, | |
| 2931 TokenPosition::kNoSource); | 2880 TokenPosition::kNoSource); |
| 2932 } | 2881 } |
| 2933 if (HasParallelMove()) { | 2882 if (HasParallelMove()) { |
| 2934 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2883 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 2935 } | 2884 } |
| 2936 | 2885 |
| 2937 // Restore SP from FP as we are coming from a throw and the code for | 2886 // Restore SP from FP as we are coming from a throw and the code for |
| 2938 // popping arguments has not been run. | 2887 // popping arguments has not been run. |
| 2939 const intptr_t fp_sp_dist = | 2888 const intptr_t fp_sp_dist = |
| 2940 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 2889 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2962 // Initialize exception and stack trace variables. | 2911 // Initialize exception and stack trace variables. |
| 2963 if (exception_var().is_captured()) { | 2912 if (exception_var().is_captured()) { |
| 2964 ASSERT(stacktrace_var().is_captured()); | 2913 ASSERT(stacktrace_var().is_captured()); |
| 2965 __ StoreIntoObjectOffset(CTX, | 2914 __ StoreIntoObjectOffset(CTX, |
| 2966 Context::variable_offset(exception_var().index()), | 2915 Context::variable_offset(exception_var().index()), |
| 2967 kExceptionObjectReg); | 2916 kExceptionObjectReg); |
| 2968 __ StoreIntoObjectOffset(CTX, | 2917 __ StoreIntoObjectOffset(CTX, |
| 2969 Context::variable_offset(stacktrace_var().index()), | 2918 Context::variable_offset(stacktrace_var().index()), |
| 2970 kStackTraceObjectReg); | 2919 kStackTraceObjectReg); |
| 2971 } else { | 2920 } else { |
| 2972 __ StoreToOffset(kWord, kExceptionObjectReg, | 2921 __ StoreToOffset(kWord, kExceptionObjectReg, FP, |
| 2973 FP, exception_var().index() * kWordSize); | 2922 exception_var().index() * kWordSize); |
| 2974 __ StoreToOffset(kWord, kStackTraceObjectReg, | 2923 __ StoreToOffset(kWord, kStackTraceObjectReg, FP, |
| 2975 FP, stacktrace_var().index() * kWordSize); | 2924 stacktrace_var().index() * kWordSize); |
| 2976 } | 2925 } |
| 2977 } | 2926 } |
| 2978 | 2927 |
| 2979 | 2928 |
| 2980 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 2929 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |
| 2981 bool opt) const { | 2930 bool opt) const { |
| 2982 const intptr_t kNumInputs = 0; | 2931 const intptr_t kNumInputs = 0; |
| 2983 const intptr_t kNumTemps = 1; | 2932 const intptr_t kNumTemps = 1; |
| 2984 LocationSummary* summary = new(zone) LocationSummary( | 2933 LocationSummary* summary = new (zone) LocationSummary( |
| 2985 zone, kNumInputs, | 2934 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2986 kNumTemps, | |
| 2987 LocationSummary::kCallOnSlowPath); | |
| 2988 summary->set_temp(0, Location::RequiresRegister()); | 2935 summary->set_temp(0, Location::RequiresRegister()); |
| 2989 return summary; | 2936 return summary; |
| 2990 } | 2937 } |
| 2991 | 2938 |
| 2992 | 2939 |
| 2993 class CheckStackOverflowSlowPath : public SlowPathCode { | 2940 class CheckStackOverflowSlowPath : public SlowPathCode { |
| 2994 public: | 2941 public: |
| 2995 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2942 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
| 2996 : instruction_(instruction) { } | 2943 : instruction_(instruction) {} |
| 2997 | 2944 |
| 2998 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2945 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2999 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { | 2946 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { |
| 3000 const Register value = instruction_->locs()->temp(0).reg(); | 2947 const Register value = instruction_->locs()->temp(0).reg(); |
| 3001 __ Comment("CheckStackOverflowSlowPathOsr"); | 2948 __ Comment("CheckStackOverflowSlowPathOsr"); |
| 3002 __ Bind(osr_entry_label()); | 2949 __ Bind(osr_entry_label()); |
| 3003 __ LoadImmediate(value, Thread::kOsrRequest); | 2950 __ LoadImmediate(value, Thread::kOsrRequest); |
| 3004 __ str(value, Address(THR, Thread::stack_overflow_flags_offset())); | 2951 __ str(value, Address(THR, Thread::stack_overflow_flags_offset())); |
| 3005 } | 2952 } |
| 3006 __ Comment("CheckStackOverflowSlowPath"); | 2953 __ Comment("CheckStackOverflowSlowPath"); |
| 3007 __ Bind(entry_label()); | 2954 __ Bind(entry_label()); |
| 3008 compiler->SaveLiveRegisters(instruction_->locs()); | 2955 compiler->SaveLiveRegisters(instruction_->locs()); |
| 3009 // pending_deoptimization_env_ is needed to generate a runtime call that | 2956 // pending_deoptimization_env_ is needed to generate a runtime call that |
| 3010 // may throw an exception. | 2957 // may throw an exception. |
| 3011 ASSERT(compiler->pending_deoptimization_env_ == NULL); | 2958 ASSERT(compiler->pending_deoptimization_env_ == NULL); |
| 3012 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); | 2959 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |
| 3013 compiler->pending_deoptimization_env_ = env; | 2960 compiler->pending_deoptimization_env_ = env; |
| 3014 compiler->GenerateRuntimeCall(instruction_->token_pos(), | 2961 compiler->GenerateRuntimeCall( |
| 3015 instruction_->deopt_id(), | 2962 instruction_->token_pos(), instruction_->deopt_id(), |
| 3016 kStackOverflowRuntimeEntry, | 2963 kStackOverflowRuntimeEntry, 0, instruction_->locs()); |
| 3017 0, | |
| 3018 instruction_->locs()); | |
| 3019 | 2964 |
| 3020 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { | 2965 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { |
| 3021 // In unoptimized code, record loop stack checks as possible OSR entries. | 2966 // In unoptimized code, record loop stack checks as possible OSR entries. |
| 3022 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, | 2967 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, |
| 3023 instruction_->deopt_id(), | 2968 instruction_->deopt_id(), |
| 3024 TokenPosition::kNoSource); | 2969 TokenPosition::kNoSource); |
| 3025 } | 2970 } |
| 3026 compiler->pending_deoptimization_env_ = NULL; | 2971 compiler->pending_deoptimization_env_ = NULL; |
| 3027 compiler->RestoreLiveRegisters(instruction_->locs()); | 2972 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 3028 __ b(exit_label()); | 2973 __ b(exit_label()); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3063 } | 3008 } |
| 3064 __ Bind(slow_path->exit_label()); | 3009 __ Bind(slow_path->exit_label()); |
| 3065 } | 3010 } |
| 3066 | 3011 |
| 3067 | 3012 |
| 3068 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 3013 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
| 3069 BinarySmiOpInstr* shift_left) { | 3014 BinarySmiOpInstr* shift_left) { |
| 3070 const LocationSummary& locs = *shift_left->locs(); | 3015 const LocationSummary& locs = *shift_left->locs(); |
| 3071 const Register left = locs.in(0).reg(); | 3016 const Register left = locs.in(0).reg(); |
| 3072 const Register result = locs.out(0).reg(); | 3017 const Register result = locs.out(0).reg(); |
| 3073 Label* deopt = shift_left->CanDeoptimize() ? | 3018 Label* deopt = shift_left->CanDeoptimize() |
| 3074 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | 3019 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
| 3075 : NULL; | 3020 ICData::kDeoptBinarySmiOp) |
| 3021 : NULL; |
| 3076 if (locs.in(1).IsConstant()) { | 3022 if (locs.in(1).IsConstant()) { |
| 3077 const Object& constant = locs.in(1).constant(); | 3023 const Object& constant = locs.in(1).constant(); |
| 3078 ASSERT(constant.IsSmi()); | 3024 ASSERT(constant.IsSmi()); |
| 3079 // Immediate shift operation takes 5 bits for the count. | 3025 // Immediate shift operation takes 5 bits for the count. |
| 3080 const intptr_t kCountLimit = 0x1F; | 3026 const intptr_t kCountLimit = 0x1F; |
| 3081 const intptr_t value = Smi::Cast(constant).Value(); | 3027 const intptr_t value = Smi::Cast(constant).Value(); |
| 3082 ASSERT((0 < value) && (value < kCountLimit)); | 3028 ASSERT((0 < value) && (value < kCountLimit)); |
| 3083 if (shift_left->can_overflow()) { | 3029 if (shift_left->can_overflow()) { |
| 3084 // Check for overflow (preserve left). | 3030 // Check for overflow (preserve left). |
| 3085 __ Lsl(IP, left, Operand(value)); | 3031 __ Lsl(IP, left, Operand(value)); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3155 __ b(deopt, NE); // Overflow. | 3101 __ b(deopt, NE); // Overflow. |
| 3156 // Shift for result now we know there is no overflow. | 3102 // Shift for result now we know there is no overflow. |
| 3157 __ Lsl(result, left, IP); | 3103 __ Lsl(result, left, IP); |
| 3158 } | 3104 } |
| 3159 } | 3105 } |
| 3160 | 3106 |
| 3161 | 3107 |
| 3162 class CheckedSmiSlowPath : public SlowPathCode { | 3108 class CheckedSmiSlowPath : public SlowPathCode { |
| 3163 public: | 3109 public: |
| 3164 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) | 3110 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) |
| 3165 : instruction_(instruction), try_index_(try_index) { } | 3111 : instruction_(instruction), try_index_(try_index) {} |
| 3166 | 3112 |
| 3167 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 3113 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3168 if (Assembler::EmittingComments()) { | 3114 if (Assembler::EmittingComments()) { |
| 3169 __ Comment("slow path smi operation"); | 3115 __ Comment("slow path smi operation"); |
| 3170 } | 3116 } |
| 3171 __ Bind(entry_label()); | 3117 __ Bind(entry_label()); |
| 3172 LocationSummary* locs = instruction_->locs(); | 3118 LocationSummary* locs = instruction_->locs(); |
| 3173 Register result = locs->out(0).reg(); | 3119 Register result = locs->out(0).reg(); |
| 3174 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 3120 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
| 3175 | 3121 |
| 3176 compiler->SaveLiveRegisters(locs); | 3122 compiler->SaveLiveRegisters(locs); |
| 3177 __ Push(locs->in(0).reg()); | 3123 __ Push(locs->in(0).reg()); |
| 3178 __ Push(locs->in(1).reg()); | 3124 __ Push(locs->in(1).reg()); |
| 3179 compiler->EmitMegamorphicInstanceCall( | 3125 compiler->EmitMegamorphicInstanceCall( |
| 3180 *instruction_->call()->ic_data(), | 3126 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
| 3181 instruction_->call()->ArgumentCount(), | 3127 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
| 3182 instruction_->call()->deopt_id(), | 3128 locs, try_index_, |
| 3183 instruction_->call()->token_pos(), | |
| 3184 locs, | |
| 3185 try_index_, | |
| 3186 /* slow_path_argument_count = */ 2); | 3129 /* slow_path_argument_count = */ 2); |
| 3187 __ mov(result, Operand(R0)); | 3130 __ mov(result, Operand(R0)); |
| 3188 compiler->RestoreLiveRegisters(locs); | 3131 compiler->RestoreLiveRegisters(locs); |
| 3189 __ b(exit_label()); | 3132 __ b(exit_label()); |
| 3190 } | 3133 } |
| 3191 | 3134 |
| 3192 private: | 3135 private: |
| 3193 CheckedSmiOpInstr* instruction_; | 3136 CheckedSmiOpInstr* instruction_; |
| 3194 intptr_t try_index_; | 3137 intptr_t try_index_; |
| 3195 }; | 3138 }; |
| 3196 | 3139 |
| 3197 | 3140 |
| 3198 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 3141 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
| 3199 bool opt) const { | 3142 bool opt) const { |
| 3200 const intptr_t kNumInputs = 2; | 3143 const intptr_t kNumInputs = 2; |
| 3201 const intptr_t kNumTemps = 0; | 3144 const intptr_t kNumTemps = 0; |
| 3202 LocationSummary* summary = new(zone) LocationSummary( | 3145 LocationSummary* summary = new (zone) LocationSummary( |
| 3203 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3146 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3204 summary->set_in(0, Location::RequiresRegister()); | 3147 summary->set_in(0, Location::RequiresRegister()); |
| 3205 summary->set_in(1, Location::RequiresRegister()); | 3148 summary->set_in(1, Location::RequiresRegister()); |
| 3206 summary->set_out(0, Location::RequiresRegister()); | 3149 summary->set_out(0, Location::RequiresRegister()); |
| 3207 return summary; | 3150 return summary; |
| 3208 } | 3151 } |
| 3209 | 3152 |
| 3210 | 3153 |
| 3211 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3154 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3212 CheckedSmiSlowPath* slow_path = | 3155 CheckedSmiSlowPath* slow_path = |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3268 | 3211 |
| 3269 class CheckedSmiComparisonSlowPath : public SlowPathCode { | 3212 class CheckedSmiComparisonSlowPath : public SlowPathCode { |
| 3270 public: | 3213 public: |
| 3271 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, | 3214 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, |
| 3272 intptr_t try_index, | 3215 intptr_t try_index, |
| 3273 BranchLabels labels, | 3216 BranchLabels labels, |
| 3274 bool merged) | 3217 bool merged) |
| 3275 : instruction_(instruction), | 3218 : instruction_(instruction), |
| 3276 try_index_(try_index), | 3219 try_index_(try_index), |
| 3277 labels_(labels), | 3220 labels_(labels), |
| 3278 merged_(merged) { } | 3221 merged_(merged) {} |
| 3279 | 3222 |
| 3280 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 3223 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3281 if (Assembler::EmittingComments()) { | 3224 if (Assembler::EmittingComments()) { |
| 3282 __ Comment("slow path smi operation"); | 3225 __ Comment("slow path smi operation"); |
| 3283 } | 3226 } |
| 3284 __ Bind(entry_label()); | 3227 __ Bind(entry_label()); |
| 3285 LocationSummary* locs = instruction_->locs(); | 3228 LocationSummary* locs = instruction_->locs(); |
| 3286 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); | 3229 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); |
| 3287 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 3230 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
| 3288 | 3231 |
| 3289 compiler->SaveLiveRegisters(locs); | 3232 compiler->SaveLiveRegisters(locs); |
| 3290 __ Push(locs->in(0).reg()); | 3233 __ Push(locs->in(0).reg()); |
| 3291 __ Push(locs->in(1).reg()); | 3234 __ Push(locs->in(1).reg()); |
| 3292 compiler->EmitMegamorphicInstanceCall( | 3235 compiler->EmitMegamorphicInstanceCall( |
| 3293 *instruction_->call()->ic_data(), | 3236 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
| 3294 instruction_->call()->ArgumentCount(), | 3237 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
| 3295 instruction_->call()->deopt_id(), | 3238 locs, try_index_, |
| 3296 instruction_->call()->token_pos(), | |
| 3297 locs, | |
| 3298 try_index_, | |
| 3299 /* slow_path_argument_count = */ 2); | 3239 /* slow_path_argument_count = */ 2); |
| 3300 __ mov(result, Operand(R0)); | 3240 __ mov(result, Operand(R0)); |
| 3301 compiler->RestoreLiveRegisters(locs); | 3241 compiler->RestoreLiveRegisters(locs); |
| 3302 if (merged_) { | 3242 if (merged_) { |
| 3303 __ CompareObject(result, Bool::True()); | 3243 __ CompareObject(result, Bool::True()); |
| 3304 __ b(instruction_->is_negated() | 3244 __ b( |
| 3305 ? labels_.false_label : labels_.true_label, EQ); | 3245 instruction_->is_negated() ? labels_.false_label : labels_.true_label, |
| 3306 __ b(instruction_->is_negated() | 3246 EQ); |
| 3307 ? labels_.true_label : labels_.false_label); | 3247 __ b(instruction_->is_negated() ? labels_.true_label |
| 3248 : labels_.false_label); |
| 3308 } else { | 3249 } else { |
| 3309 __ b(exit_label()); | 3250 __ b(exit_label()); |
| 3310 } | 3251 } |
| 3311 } | 3252 } |
| 3312 | 3253 |
| 3313 private: | 3254 private: |
| 3314 CheckedSmiComparisonInstr* instruction_; | 3255 CheckedSmiComparisonInstr* instruction_; |
| 3315 intptr_t try_index_; | 3256 intptr_t try_index_; |
| 3316 BranchLabels labels_; | 3257 BranchLabels labels_; |
| 3317 bool merged_; | 3258 bool merged_; |
| 3318 }; | 3259 }; |
| 3319 | 3260 |
| 3320 | 3261 |
| 3321 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 3262 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
| 3322 Zone* zone, bool opt) const { | 3263 Zone* zone, |
| 3264 bool opt) const { |
| 3323 const intptr_t kNumInputs = 2; | 3265 const intptr_t kNumInputs = 2; |
| 3324 const intptr_t kNumTemps = 1; | 3266 const intptr_t kNumTemps = 1; |
| 3325 LocationSummary* summary = new(zone) LocationSummary( | 3267 LocationSummary* summary = new (zone) LocationSummary( |
| 3326 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3268 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3327 summary->set_in(0, Location::RequiresRegister()); | 3269 summary->set_in(0, Location::RequiresRegister()); |
| 3328 summary->set_in(1, Location::RequiresRegister()); | 3270 summary->set_in(1, Location::RequiresRegister()); |
| 3329 summary->set_temp(0, Location::RequiresRegister()); | 3271 summary->set_temp(0, Location::RequiresRegister()); |
| 3330 summary->set_out(0, Location::RequiresRegister()); | 3272 summary->set_out(0, Location::RequiresRegister()); |
| 3331 return summary; | 3273 return summary; |
| 3332 } | 3274 } |
| 3333 | 3275 |
| 3334 | 3276 |
| 3335 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 3277 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
| 3336 FlowGraphCompiler* compiler, BranchLabels labels) { | 3278 FlowGraphCompiler* compiler, |
| 3279 BranchLabels labels) { |
| 3337 return EmitSmiComparisonOp(compiler, locs(), kind()); | 3280 return EmitSmiComparisonOp(compiler, locs(), kind()); |
| 3338 } | 3281 } |
| 3339 | 3282 |
| 3340 | 3283 |
| 3341 #define EMIT_SMI_CHECK \ | 3284 #define EMIT_SMI_CHECK \ |
| 3342 Register left = locs()->in(0).reg(); \ | 3285 Register left = locs()->in(0).reg(); \ |
| 3343 Register right = locs()->in(1).reg(); \ | 3286 Register right = locs()->in(1).reg(); \ |
| 3344 Register temp = locs()->temp(0).reg(); \ | 3287 Register temp = locs()->temp(0).reg(); \ |
| 3345 intptr_t left_cid = this->left()->Type()->ToCid(); \ | 3288 intptr_t left_cid = this->left()->Type()->ToCid(); \ |
| 3346 intptr_t right_cid = this->right()->Type()->ToCid(); \ | 3289 intptr_t right_cid = this->right()->Type()->ToCid(); \ |
| 3347 if (this->left()->definition() == this->right()->definition()) { \ | 3290 if (this->left()->definition() == this->right()->definition()) { \ |
| 3348 __ tst(left, Operand(kSmiTagMask)); \ | 3291 __ tst(left, Operand(kSmiTagMask)); \ |
| 3349 } else if (left_cid == kSmiCid) { \ | 3292 } else if (left_cid == kSmiCid) { \ |
| 3350 __ tst(right, Operand(kSmiTagMask)); \ | 3293 __ tst(right, Operand(kSmiTagMask)); \ |
| 3351 } else if (right_cid == kSmiCid) { \ | 3294 } else if (right_cid == kSmiCid) { \ |
| 3352 __ tst(left, Operand(kSmiTagMask)); \ | 3295 __ tst(left, Operand(kSmiTagMask)); \ |
| 3353 } else { \ | 3296 } else { \ |
| 3354 __ orr(temp, left, Operand(right)); \ | 3297 __ orr(temp, left, Operand(right)); \ |
| 3355 __ tst(temp, Operand(kSmiTagMask)); \ | 3298 __ tst(temp, Operand(kSmiTagMask)); \ |
| 3356 } \ | 3299 } \ |
| 3357 __ b(slow_path->entry_label(), NE) | 3300 __ b(slow_path->entry_label(), NE) |
| 3358 | 3301 |
| 3359 | 3302 |
| 3360 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3303 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 3361 BranchInstr* branch) { | 3304 BranchInstr* branch) { |
| 3362 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3305 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 3363 CheckedSmiComparisonSlowPath* slow_path = | 3306 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
| 3364 new CheckedSmiComparisonSlowPath(this, | 3307 this, compiler->CurrentTryIndex(), labels, |
| 3365 compiler->CurrentTryIndex(), | 3308 /* merged = */ true); |
| 3366 labels, | |
| 3367 /* merged = */ true); | |
| 3368 compiler->AddSlowPathCode(slow_path); | 3309 compiler->AddSlowPathCode(slow_path); |
| 3369 EMIT_SMI_CHECK; | 3310 EMIT_SMI_CHECK; |
| 3370 Condition true_condition = EmitComparisonCode(compiler, labels); | 3311 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3371 EmitBranchOnCondition(compiler, true_condition, labels); | 3312 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3372 __ Bind(slow_path->exit_label()); | 3313 __ Bind(slow_path->exit_label()); |
| 3373 } | 3314 } |
| 3374 | 3315 |
| 3375 | 3316 |
| 3376 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3317 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3377 BranchLabels labels = { NULL, NULL, NULL }; | 3318 BranchLabels labels = {NULL, NULL, NULL}; |
| 3378 CheckedSmiComparisonSlowPath* slow_path = | 3319 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
| 3379 new CheckedSmiComparisonSlowPath(this, | 3320 this, compiler->CurrentTryIndex(), labels, |
| 3380 compiler->CurrentTryIndex(), | 3321 /* merged = */ false); |
| 3381 labels, | |
| 3382 /* merged = */ false); | |
| 3383 compiler->AddSlowPathCode(slow_path); | 3322 compiler->AddSlowPathCode(slow_path); |
| 3384 EMIT_SMI_CHECK; | 3323 EMIT_SMI_CHECK; |
| 3385 Condition true_condition = EmitComparisonCode(compiler, labels); | 3324 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3386 Register result = locs()->out(0).reg(); | 3325 Register result = locs()->out(0).reg(); |
| 3387 __ LoadObject(result, Bool::True(), true_condition); | 3326 __ LoadObject(result, Bool::True(), true_condition); |
| 3388 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 3327 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 3389 __ Bind(slow_path->exit_label()); | 3328 __ Bind(slow_path->exit_label()); |
| 3390 } | 3329 } |
| 3391 #undef EMIT_SMI_CHECK | 3330 #undef EMIT_SMI_CHECK |
| 3392 | 3331 |
| 3393 | 3332 |
| 3394 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 3333 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 3395 bool opt) const { | 3334 bool opt) const { |
| 3396 const intptr_t kNumInputs = 2; | 3335 const intptr_t kNumInputs = 2; |
| 3397 // Calculate number of temporaries. | 3336 // Calculate number of temporaries. |
| 3398 intptr_t num_temps = 0; | 3337 intptr_t num_temps = 0; |
| 3399 if (op_kind() == Token::kTRUNCDIV) { | 3338 if (op_kind() == Token::kTRUNCDIV) { |
| 3400 if (RightIsPowerOfTwoConstant()) { | 3339 if (RightIsPowerOfTwoConstant()) { |
| 3401 num_temps = 1; | 3340 num_temps = 1; |
| 3402 } else { | 3341 } else { |
| 3403 num_temps = 2; | 3342 num_temps = 2; |
| 3404 } | 3343 } |
| 3405 } else if (op_kind() == Token::kMOD) { | 3344 } else if (op_kind() == Token::kMOD) { |
| 3406 num_temps = 2; | 3345 num_temps = 2; |
| 3407 } else if (((op_kind() == Token::kSHL) && can_overflow()) || | 3346 } else if (((op_kind() == Token::kSHL) && can_overflow()) || |
| 3408 (op_kind() == Token::kSHR)) { | 3347 (op_kind() == Token::kSHR)) { |
| 3409 num_temps = 1; | 3348 num_temps = 1; |
| 3410 } | 3349 } |
| 3411 LocationSummary* summary = new(zone) LocationSummary( | 3350 LocationSummary* summary = new (zone) |
| 3412 zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 3351 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
| 3413 if (op_kind() == Token::kTRUNCDIV) { | 3352 if (op_kind() == Token::kTRUNCDIV) { |
| 3414 summary->set_in(0, Location::RequiresRegister()); | 3353 summary->set_in(0, Location::RequiresRegister()); |
| 3415 if (RightIsPowerOfTwoConstant()) { | 3354 if (RightIsPowerOfTwoConstant()) { |
| 3416 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 3355 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
| 3417 summary->set_in(1, Location::Constant(right_constant)); | 3356 summary->set_in(1, Location::Constant(right_constant)); |
| 3418 summary->set_temp(0, Location::RequiresRegister()); | 3357 summary->set_temp(0, Location::RequiresRegister()); |
| 3419 } else { | 3358 } else { |
| 3420 summary->set_in(1, Location::RequiresRegister()); | 3359 summary->set_in(1, Location::RequiresRegister()); |
| 3421 summary->set_temp(0, Location::RequiresRegister()); | 3360 summary->set_temp(0, Location::RequiresRegister()); |
| 3422 summary->set_temp(1, Location::RequiresFpuRegister()); | 3361 summary->set_temp(1, Location::RequiresFpuRegister()); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3549 __ LoadImmediate(IP, imm); | 3488 __ LoadImmediate(IP, imm); |
| 3550 __ eor(result, left, Operand(IP)); | 3489 __ eor(result, left, Operand(IP)); |
| 3551 } | 3490 } |
| 3552 break; | 3491 break; |
| 3553 } | 3492 } |
| 3554 case Token::kSHR: { | 3493 case Token::kSHR: { |
| 3555 // sarl operation masks the count to 5 bits. | 3494 // sarl operation masks the count to 5 bits. |
| 3556 const intptr_t kCountLimit = 0x1F; | 3495 const intptr_t kCountLimit = 0x1F; |
| 3557 intptr_t value = Smi::Cast(constant).Value(); | 3496 intptr_t value = Smi::Cast(constant).Value(); |
| 3558 __ Asr(result, left, | 3497 __ Asr(result, left, |
| 3559 Operand(Utils::Minimum(value + kSmiTagSize, kCountLimit))); | 3498 Operand(Utils::Minimum(value + kSmiTagSize, kCountLimit))); |
| 3560 __ SmiTag(result); | 3499 __ SmiTag(result); |
| 3561 break; | 3500 break; |
| 3562 } | 3501 } |
| 3563 | 3502 |
| 3564 default: | 3503 default: |
| 3565 UNREACHABLE(); | 3504 UNREACHABLE(); |
| 3566 break; | 3505 break; |
| 3567 } | 3506 } |
| 3568 return; | 3507 return; |
| 3569 } | 3508 } |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3706 break; | 3645 break; |
| 3707 } | 3646 } |
| 3708 } | 3647 } |
| 3709 | 3648 |
| 3710 | 3649 |
| 3711 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler, | 3650 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler, |
| 3712 BinaryInt32OpInstr* shift_left) { | 3651 BinaryInt32OpInstr* shift_left) { |
| 3713 const LocationSummary& locs = *shift_left->locs(); | 3652 const LocationSummary& locs = *shift_left->locs(); |
| 3714 const Register left = locs.in(0).reg(); | 3653 const Register left = locs.in(0).reg(); |
| 3715 const Register result = locs.out(0).reg(); | 3654 const Register result = locs.out(0).reg(); |
| 3716 Label* deopt = shift_left->CanDeoptimize() ? | 3655 Label* deopt = shift_left->CanDeoptimize() |
| 3717 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | 3656 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
| 3718 : NULL; | 3657 ICData::kDeoptBinarySmiOp) |
| 3658 : NULL; |
| 3719 ASSERT(locs.in(1).IsConstant()); | 3659 ASSERT(locs.in(1).IsConstant()); |
| 3720 const Object& constant = locs.in(1).constant(); | 3660 const Object& constant = locs.in(1).constant(); |
| 3721 ASSERT(constant.IsSmi()); | 3661 ASSERT(constant.IsSmi()); |
| 3722 // Immediate shift operation takes 5 bits for the count. | 3662 // Immediate shift operation takes 5 bits for the count. |
| 3723 const intptr_t kCountLimit = 0x1F; | 3663 const intptr_t kCountLimit = 0x1F; |
| 3724 const intptr_t value = Smi::Cast(constant).Value(); | 3664 const intptr_t value = Smi::Cast(constant).Value(); |
| 3725 ASSERT((0 < value) && (value < kCountLimit)); | 3665 ASSERT((0 < value) && (value < kCountLimit)); |
| 3726 if (shift_left->can_overflow()) { | 3666 if (shift_left->can_overflow()) { |
| 3727 // Check for overflow (preserve left). | 3667 // Check for overflow (preserve left). |
| 3728 __ Lsl(IP, left, Operand(value)); | 3668 __ Lsl(IP, left, Operand(value)); |
| 3729 __ cmp(left, Operand(IP, ASR, value)); | 3669 __ cmp(left, Operand(IP, ASR, value)); |
| 3730 __ b(deopt, NE); // Overflow. | 3670 __ b(deopt, NE); // Overflow. |
| 3731 } | 3671 } |
| 3732 // Shift for result now we know there is no overflow. | 3672 // Shift for result now we know there is no overflow. |
| 3733 __ Lsl(result, left, Operand(value)); | 3673 __ Lsl(result, left, Operand(value)); |
| 3734 } | 3674 } |
| 3735 | 3675 |
| 3736 | 3676 |
| 3737 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone, | 3677 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Zone* zone, |
| 3738 bool opt) const { | 3678 bool opt) const { |
| 3739 const intptr_t kNumInputs = 2; | 3679 const intptr_t kNumInputs = 2; |
| 3740 // Calculate number of temporaries. | 3680 // Calculate number of temporaries. |
| 3741 intptr_t num_temps = 0; | 3681 intptr_t num_temps = 0; |
| 3742 if (((op_kind() == Token::kSHL) && can_overflow()) || | 3682 if (((op_kind() == Token::kSHL) && can_overflow()) || |
| 3743 (op_kind() == Token::kSHR)) { | 3683 (op_kind() == Token::kSHR)) { |
| 3744 num_temps = 1; | 3684 num_temps = 1; |
| 3745 } | 3685 } |
| 3746 LocationSummary* summary = new(zone) LocationSummary( | 3686 LocationSummary* summary = new (zone) |
| 3747 zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 3687 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
| 3748 summary->set_in(0, Location::RequiresRegister()); | 3688 summary->set_in(0, Location::RequiresRegister()); |
| 3749 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 3689 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 3750 if (((op_kind() == Token::kSHL) && can_overflow()) || | 3690 if (((op_kind() == Token::kSHL) && can_overflow()) || |
| 3751 (op_kind() == Token::kSHR)) { | 3691 (op_kind() == Token::kSHR)) { |
| 3752 summary->set_temp(0, Location::RequiresRegister()); | 3692 summary->set_temp(0, Location::RequiresRegister()); |
| 3753 } | 3693 } |
| 3754 // We make use of 3-operand instructions by not requiring result register | 3694 // We make use of 3-operand instructions by not requiring result register |
| 3755 // to be identical to first input register as on Intel. | 3695 // to be identical to first input register as on Intel. |
| 3756 summary->set_out(0, Location::RequiresRegister()); | 3696 summary->set_out(0, Location::RequiresRegister()); |
| 3757 return summary; | 3697 return summary; |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3911 } | 3851 } |
| 3912 | 3852 |
| 3913 | 3853 |
| 3914 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3854 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
| 3915 bool opt) const { | 3855 bool opt) const { |
| 3916 intptr_t left_cid = left()->Type()->ToCid(); | 3856 intptr_t left_cid = left()->Type()->ToCid(); |
| 3917 intptr_t right_cid = right()->Type()->ToCid(); | 3857 intptr_t right_cid = right()->Type()->ToCid(); |
| 3918 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3858 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
| 3919 const intptr_t kNumInputs = 2; | 3859 const intptr_t kNumInputs = 2; |
| 3920 const intptr_t kNumTemps = 0; | 3860 const intptr_t kNumTemps = 0; |
| 3921 LocationSummary* summary = new(zone) LocationSummary( | 3861 LocationSummary* summary = new (zone) |
| 3922 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3862 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3923 summary->set_in(0, Location::RequiresRegister()); | 3863 summary->set_in(0, Location::RequiresRegister()); |
| 3924 summary->set_in(1, Location::RequiresRegister()); | 3864 summary->set_in(1, Location::RequiresRegister()); |
| 3925 return summary; | 3865 return summary; |
| 3926 } | 3866 } |
| 3927 | 3867 |
| 3928 | 3868 |
| 3929 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3869 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3930 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3870 Label* deopt = |
| 3931 ICData::kDeoptBinaryDoubleOp, | 3871 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
| 3932 licm_hoisted_ ? ICData::kHoisted : 0); | 3872 licm_hoisted_ ? ICData::kHoisted : 0); |
| 3933 intptr_t left_cid = left()->Type()->ToCid(); | 3873 intptr_t left_cid = left()->Type()->ToCid(); |
| 3934 intptr_t right_cid = right()->Type()->ToCid(); | 3874 intptr_t right_cid = right()->Type()->ToCid(); |
| 3935 const Register left = locs()->in(0).reg(); | 3875 const Register left = locs()->in(0).reg(); |
| 3936 const Register right = locs()->in(1).reg(); | 3876 const Register right = locs()->in(1).reg(); |
| 3937 if (this->left()->definition() == this->right()->definition()) { | 3877 if (this->left()->definition() == this->right()->definition()) { |
| 3938 __ tst(left, Operand(kSmiTagMask)); | 3878 __ tst(left, Operand(kSmiTagMask)); |
| 3939 } else if (left_cid == kSmiCid) { | 3879 } else if (left_cid == kSmiCid) { |
| 3940 __ tst(right, Operand(kSmiTagMask)); | 3880 __ tst(right, Operand(kSmiTagMask)); |
| 3941 } else if (right_cid == kSmiCid) { | 3881 } else if (right_cid == kSmiCid) { |
| 3942 __ tst(left, Operand(kSmiTagMask)); | 3882 __ tst(left, Operand(kSmiTagMask)); |
| 3943 } else { | 3883 } else { |
| 3944 __ orr(IP, left, Operand(right)); | 3884 __ orr(IP, left, Operand(right)); |
| 3945 __ tst(IP, Operand(kSmiTagMask)); | 3885 __ tst(IP, Operand(kSmiTagMask)); |
| 3946 } | 3886 } |
| 3947 __ b(deopt, EQ); | 3887 __ b(deopt, EQ); |
| 3948 } | 3888 } |
| 3949 | 3889 |
| 3950 | 3890 |
| 3951 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, | 3891 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3952 bool opt) const { | |
| 3953 const intptr_t kNumInputs = 1; | 3892 const intptr_t kNumInputs = 1; |
| 3954 const intptr_t kNumTemps = 1; | 3893 const intptr_t kNumTemps = 1; |
| 3955 LocationSummary* summary = new(zone) LocationSummary( | 3894 LocationSummary* summary = new (zone) LocationSummary( |
| 3956 zone, kNumInputs, | 3895 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3957 kNumTemps, | |
| 3958 LocationSummary::kCallOnSlowPath); | |
| 3959 summary->set_in(0, Location::RequiresFpuRegister()); | 3896 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3960 summary->set_temp(0, Location::RequiresRegister()); | 3897 summary->set_temp(0, Location::RequiresRegister()); |
| 3961 summary->set_out(0, Location::RequiresRegister()); | 3898 summary->set_out(0, Location::RequiresRegister()); |
| 3962 return summary; | 3899 return summary; |
| 3963 } | 3900 } |
| 3964 | 3901 |
| 3965 | 3902 |
| 3966 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3903 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3967 const Register out_reg = locs()->out(0).reg(); | 3904 const Register out_reg = locs()->out(0).reg(); |
| 3968 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 3905 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
| 3969 | 3906 |
| 3970 BoxAllocationSlowPath::Allocate( | 3907 BoxAllocationSlowPath::Allocate(compiler, this, |
| 3971 compiler, | 3908 compiler->BoxClassFor(from_representation()), |
| 3972 this, | 3909 out_reg, locs()->temp(0).reg()); |
| 3973 compiler->BoxClassFor(from_representation()), | |
| 3974 out_reg, | |
| 3975 locs()->temp(0).reg()); | |
| 3976 | 3910 |
| 3977 switch (from_representation()) { | 3911 switch (from_representation()) { |
| 3978 case kUnboxedDouble: | 3912 case kUnboxedDouble: |
| 3979 __ StoreDToOffset( | 3913 __ StoreDToOffset(value, out_reg, ValueOffset() - kHeapObjectTag); |
| 3980 value, out_reg, ValueOffset() - kHeapObjectTag); | |
| 3981 break; | 3914 break; |
| 3982 case kUnboxedFloat32x4: | 3915 case kUnboxedFloat32x4: |
| 3983 case kUnboxedFloat64x2: | 3916 case kUnboxedFloat64x2: |
| 3984 case kUnboxedInt32x4: | 3917 case kUnboxedInt32x4: |
| 3985 __ StoreMultipleDToOffset( | 3918 __ StoreMultipleDToOffset(value, 2, out_reg, |
| 3986 value, 2, out_reg, ValueOffset() - kHeapObjectTag); | 3919 ValueOffset() - kHeapObjectTag); |
| 3987 break; | 3920 break; |
| 3988 default: | 3921 default: |
| 3989 UNREACHABLE(); | 3922 UNREACHABLE(); |
| 3990 break; | 3923 break; |
| 3991 } | 3924 } |
| 3992 } | 3925 } |
| 3993 | 3926 |
| 3994 | 3927 |
| 3995 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, | 3928 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3996 bool opt) const { | |
| 3997 const bool needs_temp = CanDeoptimize(); | 3929 const bool needs_temp = CanDeoptimize(); |
| 3998 const intptr_t kNumInputs = 1; | 3930 const intptr_t kNumInputs = 1; |
| 3999 const intptr_t kNumTemps = needs_temp ? 1 : 0; | 3931 const intptr_t kNumTemps = needs_temp ? 1 : 0; |
| 4000 LocationSummary* summary = new(zone) LocationSummary( | 3932 LocationSummary* summary = new (zone) |
| 4001 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3933 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4002 summary->set_in(0, Location::RequiresRegister()); | 3934 summary->set_in(0, Location::RequiresRegister()); |
| 4003 if (needs_temp) { | 3935 if (needs_temp) { |
| 4004 summary->set_temp(0, Location::RequiresRegister()); | 3936 summary->set_temp(0, Location::RequiresRegister()); |
| 4005 } | 3937 } |
| 4006 if (representation() == kUnboxedMint) { | 3938 if (representation() == kUnboxedMint) { |
| 4007 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 3939 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 4008 Location::RequiresRegister())); | 3940 Location::RequiresRegister())); |
| 4009 } else { | 3941 } else { |
| 4010 summary->set_out(0, Location::RequiresFpuRegister()); | 3942 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4011 } | 3943 } |
| 4012 return summary; | 3944 return summary; |
| 4013 } | 3945 } |
| 4014 | 3946 |
| 4015 | 3947 |
| 4016 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { | 3948 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |
| 4017 const Register box = locs()->in(0).reg(); | 3949 const Register box = locs()->in(0).reg(); |
| 4018 | 3950 |
| 4019 switch (representation()) { | 3951 switch (representation()) { |
| 4020 case kUnboxedMint: { | 3952 case kUnboxedMint: { |
| 4021 PairLocation* result = locs()->out(0).AsPairLocation(); | 3953 PairLocation* result = locs()->out(0).AsPairLocation(); |
| 4022 __ LoadFieldFromOffset(kWord, | 3954 __ LoadFieldFromOffset(kWord, result->At(0).reg(), box, ValueOffset()); |
| 4023 result->At(0).reg(), | 3955 __ LoadFieldFromOffset(kWord, result->At(1).reg(), box, |
| 4024 box, | |
| 4025 ValueOffset()); | |
| 4026 __ LoadFieldFromOffset(kWord, | |
| 4027 result->At(1).reg(), | |
| 4028 box, | |
| 4029 ValueOffset() + kWordSize); | 3956 ValueOffset() + kWordSize); |
| 4030 break; | 3957 break; |
| 4031 } | 3958 } |
| 4032 | 3959 |
| 4033 case kUnboxedDouble: { | 3960 case kUnboxedDouble: { |
| 4034 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 3961 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
| 4035 __ LoadDFromOffset( | 3962 __ LoadDFromOffset(result, box, ValueOffset() - kHeapObjectTag); |
| 4036 result, box, ValueOffset() - kHeapObjectTag); | |
| 4037 break; | 3963 break; |
| 4038 } | 3964 } |
| 4039 | 3965 |
| 4040 case kUnboxedFloat32x4: | 3966 case kUnboxedFloat32x4: |
| 4041 case kUnboxedFloat64x2: | 3967 case kUnboxedFloat64x2: |
| 4042 case kUnboxedInt32x4: { | 3968 case kUnboxedInt32x4: { |
| 4043 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 3969 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
| 4044 __ LoadMultipleDFromOffset( | 3970 __ LoadMultipleDFromOffset(result, 2, box, |
| 4045 result, 2, box, ValueOffset() - kHeapObjectTag); | 3971 ValueOffset() - kHeapObjectTag); |
| 4046 break; | 3972 break; |
| 4047 } | 3973 } |
| 4048 | 3974 |
| 4049 default: | 3975 default: |
| 4050 UNREACHABLE(); | 3976 UNREACHABLE(); |
| 4051 break; | 3977 break; |
| 4052 } | 3978 } |
| 4053 } | 3979 } |
| 4054 | 3980 |
| 4055 | 3981 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 4083 const intptr_t value_cid = value()->Type()->ToCid(); | 4009 const intptr_t value_cid = value()->Type()->ToCid(); |
| 4084 const intptr_t box_cid = BoxCid(); | 4010 const intptr_t box_cid = BoxCid(); |
| 4085 | 4011 |
| 4086 if (value_cid == box_cid) { | 4012 if (value_cid == box_cid) { |
| 4087 EmitLoadFromBox(compiler); | 4013 EmitLoadFromBox(compiler); |
| 4088 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 4014 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
| 4089 EmitSmiConversion(compiler); | 4015 EmitSmiConversion(compiler); |
| 4090 } else { | 4016 } else { |
| 4091 const Register box = locs()->in(0).reg(); | 4017 const Register box = locs()->in(0).reg(); |
| 4092 const Register temp = locs()->temp(0).reg(); | 4018 const Register temp = locs()->temp(0).reg(); |
| 4093 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), | 4019 Label* deopt = |
| 4094 ICData::kDeoptCheckClass); | 4020 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass); |
| 4095 Label is_smi; | 4021 Label is_smi; |
| 4096 | 4022 |
| 4097 if ((value()->Type()->ToNullableCid() == box_cid) && | 4023 if ((value()->Type()->ToNullableCid() == box_cid) && |
| 4098 value()->Type()->is_nullable()) { | 4024 value()->Type()->is_nullable()) { |
| 4099 __ CompareObject(box, Object::null_object()); | 4025 __ CompareObject(box, Object::null_object()); |
| 4100 __ b(deopt, EQ); | 4026 __ b(deopt, EQ); |
| 4101 } else { | 4027 } else { |
| 4102 __ tst(box, Operand(kSmiTagMask)); | 4028 __ tst(box, Operand(kSmiTagMask)); |
| 4103 __ b(CanConvertSmi() ? &is_smi : deopt, EQ); | 4029 __ b(CanConvertSmi() ? &is_smi : deopt, EQ); |
| 4104 __ CompareClassId(box, box_cid, temp); | 4030 __ CompareClassId(box, box_cid, temp); |
| 4105 __ b(deopt, NE); | 4031 __ b(deopt, NE); |
| 4106 } | 4032 } |
| 4107 | 4033 |
| 4108 EmitLoadFromBox(compiler); | 4034 EmitLoadFromBox(compiler); |
| 4109 | 4035 |
| 4110 if (is_smi.IsLinked()) { | 4036 if (is_smi.IsLinked()) { |
| 4111 Label done; | 4037 Label done; |
| 4112 __ b(&done); | 4038 __ b(&done); |
| 4113 __ Bind(&is_smi); | 4039 __ Bind(&is_smi); |
| 4114 EmitSmiConversion(compiler); | 4040 EmitSmiConversion(compiler); |
| 4115 __ Bind(&done); | 4041 __ Bind(&done); |
| 4116 } | 4042 } |
| 4117 } | 4043 } |
| 4118 } | 4044 } |
| 4119 | 4045 |
| 4120 | 4046 |
| 4121 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 4047 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 4122 bool opt) const { | 4048 bool opt) const { |
| 4123 ASSERT((from_representation() == kUnboxedInt32) || | 4049 ASSERT((from_representation() == kUnboxedInt32) || |
| 4124 (from_representation() == kUnboxedUint32)); | 4050 (from_representation() == kUnboxedUint32)); |
| 4125 const intptr_t kNumInputs = 1; | 4051 const intptr_t kNumInputs = 1; |
| 4126 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 4052 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
| 4127 LocationSummary* summary = new(zone) LocationSummary( | 4053 LocationSummary* summary = new (zone) |
| 4128 zone, | 4054 LocationSummary(zone, kNumInputs, kNumTemps, |
| 4129 kNumInputs, | 4055 ValueFitsSmi() ? LocationSummary::kNoCall |
| 4130 kNumTemps, | 4056 : LocationSummary::kCallOnSlowPath); |
| 4131 ValueFitsSmi() ? LocationSummary::kNoCall | |
| 4132 : LocationSummary::kCallOnSlowPath); | |
| 4133 summary->set_in(0, Location::RequiresRegister()); | 4057 summary->set_in(0, Location::RequiresRegister()); |
| 4134 if (!ValueFitsSmi()) { | 4058 if (!ValueFitsSmi()) { |
| 4135 summary->set_temp(0, Location::RequiresRegister()); | 4059 summary->set_temp(0, Location::RequiresRegister()); |
| 4136 } | 4060 } |
| 4137 summary->set_out(0, Location::RequiresRegister()); | 4061 summary->set_out(0, Location::RequiresRegister()); |
| 4138 return summary; | 4062 return summary; |
| 4139 } | 4063 } |
| 4140 | 4064 |
| 4141 | 4065 |
| 4142 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4066 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4143 Register value = locs()->in(0).reg(); | 4067 Register value = locs()->in(0).reg(); |
| 4144 Register out = locs()->out(0).reg(); | 4068 Register out = locs()->out(0).reg(); |
| 4145 ASSERT(value != out); | 4069 ASSERT(value != out); |
| 4146 | 4070 |
| 4147 __ SmiTag(out, value); | 4071 __ SmiTag(out, value); |
| 4148 if (!ValueFitsSmi()) { | 4072 if (!ValueFitsSmi()) { |
| 4149 Register temp = locs()->temp(0).reg(); | 4073 Register temp = locs()->temp(0).reg(); |
| 4150 Label done; | 4074 Label done; |
| 4151 if (from_representation() == kUnboxedInt32) { | 4075 if (from_representation() == kUnboxedInt32) { |
| 4152 __ cmp(value, Operand(out, ASR, 1)); | 4076 __ cmp(value, Operand(out, ASR, 1)); |
| 4153 } else { | 4077 } else { |
| 4154 ASSERT(from_representation() == kUnboxedUint32); | 4078 ASSERT(from_representation() == kUnboxedUint32); |
| 4155 // Note: better to test upper bits instead of comparing with | 4079 // Note: better to test upper bits instead of comparing with |
| 4156 // kSmiMax as kSmiMax does not fit into immediate operand. | 4080 // kSmiMax as kSmiMax does not fit into immediate operand. |
| 4157 __ TestImmediate(value, 0xC0000000); | 4081 __ TestImmediate(value, 0xC0000000); |
| 4158 } | 4082 } |
| 4159 __ b(&done, EQ); | 4083 __ b(&done, EQ); |
| 4160 BoxAllocationSlowPath::Allocate( | 4084 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out, |
| 4161 compiler, | 4085 temp); |
| 4162 this, | |
| 4163 compiler->mint_class(), | |
| 4164 out, | |
| 4165 temp); | |
| 4166 if (from_representation() == kUnboxedInt32) { | 4086 if (from_representation() == kUnboxedInt32) { |
| 4167 __ Asr(temp, value, Operand(kBitsPerWord - 1)); | 4087 __ Asr(temp, value, Operand(kBitsPerWord - 1)); |
| 4168 } else { | 4088 } else { |
| 4169 ASSERT(from_representation() == kUnboxedUint32); | 4089 ASSERT(from_representation() == kUnboxedUint32); |
| 4170 __ eor(temp, temp, Operand(temp)); | 4090 __ eor(temp, temp, Operand(temp)); |
| 4171 } | 4091 } |
| 4172 __ StoreToOffset(kWord, | 4092 __ StoreToOffset(kWord, value, out, Mint::value_offset() - kHeapObjectTag); |
| 4173 value, | 4093 __ StoreToOffset(kWord, temp, out, |
| 4174 out, | |
| 4175 Mint::value_offset() - kHeapObjectTag); | |
| 4176 __ StoreToOffset(kWord, | |
| 4177 temp, | |
| 4178 out, | |
| 4179 Mint::value_offset() - kHeapObjectTag + kWordSize); | 4094 Mint::value_offset() - kHeapObjectTag + kWordSize); |
| 4180 __ Bind(&done); | 4095 __ Bind(&done); |
| 4181 } | 4096 } |
| 4182 } | 4097 } |
| 4183 | 4098 |
| 4184 | 4099 |
| 4185 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, | 4100 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, |
| 4186 bool opt) const { | 4101 bool opt) const { |
| 4187 const intptr_t kNumInputs = 1; | 4102 const intptr_t kNumInputs = 1; |
| 4188 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 4103 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
| 4189 LocationSummary* summary = new(zone) LocationSummary( | 4104 LocationSummary* summary = new (zone) |
| 4190 zone, | 4105 LocationSummary(zone, kNumInputs, kNumTemps, |
| 4191 kNumInputs, | 4106 ValueFitsSmi() ? LocationSummary::kNoCall |
| 4192 kNumTemps, | 4107 : LocationSummary::kCallOnSlowPath); |
| 4193 ValueFitsSmi() ? LocationSummary::kNoCall | |
| 4194 : LocationSummary::kCallOnSlowPath); | |
| 4195 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 4108 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 4196 Location::RequiresRegister())); | 4109 Location::RequiresRegister())); |
| 4197 if (!ValueFitsSmi()) { | 4110 if (!ValueFitsSmi()) { |
| 4198 summary->set_temp(0, Location::RequiresRegister()); | 4111 summary->set_temp(0, Location::RequiresRegister()); |
| 4199 } | 4112 } |
| 4200 summary->set_out(0, Location::RequiresRegister()); | 4113 summary->set_out(0, Location::RequiresRegister()); |
| 4201 return summary; | 4114 return summary; |
| 4202 } | 4115 } |
| 4203 | 4116 |
| 4204 | 4117 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4216 Register value_hi = value_pair->At(1).reg(); | 4129 Register value_hi = value_pair->At(1).reg(); |
| 4217 Register tmp = locs()->temp(0).reg(); | 4130 Register tmp = locs()->temp(0).reg(); |
| 4218 Register out_reg = locs()->out(0).reg(); | 4131 Register out_reg = locs()->out(0).reg(); |
| 4219 | 4132 |
| 4220 Label done; | 4133 Label done; |
| 4221 __ SmiTag(out_reg, value_lo); | 4134 __ SmiTag(out_reg, value_lo); |
| 4222 __ cmp(value_lo, Operand(out_reg, ASR, kSmiTagSize)); | 4135 __ cmp(value_lo, Operand(out_reg, ASR, kSmiTagSize)); |
| 4223 __ cmp(value_hi, Operand(out_reg, ASR, 31), EQ); | 4136 __ cmp(value_hi, Operand(out_reg, ASR, 31), EQ); |
| 4224 __ b(&done, EQ); | 4137 __ b(&done, EQ); |
| 4225 | 4138 |
| 4226 BoxAllocationSlowPath::Allocate( | 4139 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), |
| 4227 compiler, | 4140 out_reg, tmp); |
| 4228 this, | 4141 __ StoreToOffset(kWord, value_lo, out_reg, |
| 4229 compiler->mint_class(), | |
| 4230 out_reg, | |
| 4231 tmp); | |
| 4232 __ StoreToOffset(kWord, | |
| 4233 value_lo, | |
| 4234 out_reg, | |
| 4235 Mint::value_offset() - kHeapObjectTag); | 4142 Mint::value_offset() - kHeapObjectTag); |
| 4236 __ StoreToOffset(kWord, | 4143 __ StoreToOffset(kWord, value_hi, out_reg, |
| 4237 value_hi, | |
| 4238 out_reg, | |
| 4239 Mint::value_offset() - kHeapObjectTag + kWordSize); | 4144 Mint::value_offset() - kHeapObjectTag + kWordSize); |
| 4240 __ Bind(&done); | 4145 __ Bind(&done); |
| 4241 } | 4146 } |
| 4242 | 4147 |
| 4243 | 4148 |
| 4244 static void LoadInt32FromMint(FlowGraphCompiler* compiler, | 4149 static void LoadInt32FromMint(FlowGraphCompiler* compiler, |
| 4245 Register mint, | 4150 Register mint, |
| 4246 Register result, | 4151 Register result, |
| 4247 Register temp, | 4152 Register temp, |
| 4248 Label* deopt) { | 4153 Label* deopt) { |
| 4249 __ LoadFieldFromOffset(kWord, result, mint, Mint::value_offset()); | 4154 __ LoadFieldFromOffset(kWord, result, mint, Mint::value_offset()); |
| 4250 if (deopt != NULL) { | 4155 if (deopt != NULL) { |
| 4251 __ LoadFieldFromOffset(kWord, | 4156 __ LoadFieldFromOffset(kWord, temp, mint, Mint::value_offset() + kWordSize); |
| 4252 temp, | |
| 4253 mint, | |
| 4254 Mint::value_offset() + kWordSize); | |
| 4255 __ cmp(temp, Operand(result, ASR, kBitsPerWord - 1)); | 4157 __ cmp(temp, Operand(result, ASR, kBitsPerWord - 1)); |
| 4256 __ b(deopt, NE); | 4158 __ b(deopt, NE); |
| 4257 } | 4159 } |
| 4258 } | 4160 } |
| 4259 | 4161 |
| 4260 | 4162 |
| 4261 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 4163 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 4262 bool opt) const { | 4164 bool opt) const { |
| 4263 ASSERT((representation() == kUnboxedInt32) || | 4165 ASSERT((representation() == kUnboxedInt32) || |
| 4264 (representation() == kUnboxedUint32)); | 4166 (representation() == kUnboxedUint32)); |
| 4265 ASSERT((representation() != kUnboxedUint32) || is_truncating()); | 4167 ASSERT((representation() != kUnboxedUint32) || is_truncating()); |
| 4266 const intptr_t kNumInputs = 1; | 4168 const intptr_t kNumInputs = 1; |
| 4267 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; | 4169 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0; |
| 4268 LocationSummary* summary = new(zone) LocationSummary( | 4170 LocationSummary* summary = new (zone) |
| 4269 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4171 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4270 summary->set_in(0, Location::RequiresRegister()); | 4172 summary->set_in(0, Location::RequiresRegister()); |
| 4271 if (kNumTemps > 0) { | 4173 if (kNumTemps > 0) { |
| 4272 summary->set_temp(0, Location::RequiresRegister()); | 4174 summary->set_temp(0, Location::RequiresRegister()); |
| 4273 } | 4175 } |
| 4274 summary->set_out(0, Location::RequiresRegister()); | 4176 summary->set_out(0, Location::RequiresRegister()); |
| 4275 return summary; | 4177 return summary; |
| 4276 } | 4178 } |
| 4277 | 4179 |
| 4278 | 4180 |
| 4279 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4181 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4280 const intptr_t value_cid = value()->Type()->ToCid(); | 4182 const intptr_t value_cid = value()->Type()->ToCid(); |
| 4281 const Register value = locs()->in(0).reg(); | 4183 const Register value = locs()->in(0).reg(); |
| 4282 const Register out = locs()->out(0).reg(); | 4184 const Register out = locs()->out(0).reg(); |
| 4283 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; | 4185 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; |
| 4284 Label* deopt = CanDeoptimize() ? | 4186 Label* deopt = |
| 4285 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL; | 4187 CanDeoptimize() |
| 4188 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) |
| 4189 : NULL; |
| 4286 Label* out_of_range = !is_truncating() ? deopt : NULL; | 4190 Label* out_of_range = !is_truncating() ? deopt : NULL; |
| 4287 ASSERT(value != out); | 4191 ASSERT(value != out); |
| 4288 | 4192 |
| 4289 if (value_cid == kSmiCid) { | 4193 if (value_cid == kSmiCid) { |
| 4290 __ SmiUntag(out, value); | 4194 __ SmiUntag(out, value); |
| 4291 } else if (value_cid == kMintCid) { | 4195 } else if (value_cid == kMintCid) { |
| 4292 LoadInt32FromMint(compiler, value, out, temp, out_of_range); | 4196 LoadInt32FromMint(compiler, value, out, temp, out_of_range); |
| 4293 } else if (!CanDeoptimize()) { | 4197 } else if (!CanDeoptimize()) { |
| 4294 Label done; | 4198 Label done; |
| 4295 __ SmiUntag(out, value, &done); | 4199 __ SmiUntag(out, value, &done); |
| 4296 LoadInt32FromMint(compiler, value, out, kNoRegister, NULL); | 4200 LoadInt32FromMint(compiler, value, out, kNoRegister, NULL); |
| 4297 __ Bind(&done); | 4201 __ Bind(&done); |
| 4298 } else { | 4202 } else { |
| 4299 Label done; | 4203 Label done; |
| 4300 __ SmiUntag(out, value, &done); | 4204 __ SmiUntag(out, value, &done); |
| 4301 __ CompareClassId(value, kMintCid, temp); | 4205 __ CompareClassId(value, kMintCid, temp); |
| 4302 __ b(deopt, NE); | 4206 __ b(deopt, NE); |
| 4303 LoadInt32FromMint(compiler, value, out, temp, out_of_range); | 4207 LoadInt32FromMint(compiler, value, out, temp, out_of_range); |
| 4304 __ Bind(&done); | 4208 __ Bind(&done); |
| 4305 } | 4209 } |
| 4306 } | 4210 } |
| 4307 | 4211 |
| 4308 | 4212 |
| 4309 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 4213 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 4310 bool opt) const { | 4214 bool opt) const { |
| 4311 const intptr_t kNumInputs = 2; | 4215 const intptr_t kNumInputs = 2; |
| 4312 const intptr_t kNumTemps = 0; | 4216 const intptr_t kNumTemps = 0; |
| 4313 LocationSummary* summary = new(zone) LocationSummary( | 4217 LocationSummary* summary = new (zone) |
| 4314 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4218 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4315 summary->set_in(0, Location::RequiresFpuRegister()); | 4219 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4316 summary->set_in(1, Location::RequiresFpuRegister()); | 4220 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4317 summary->set_out(0, Location::RequiresFpuRegister()); | 4221 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4318 return summary; | 4222 return summary; |
| 4319 } | 4223 } |
| 4320 | 4224 |
| 4321 | 4225 |
| 4322 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4226 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4323 const DRegister left = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 4227 const DRegister left = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
| 4324 const DRegister right = EvenDRegisterOf(locs()->in(1).fpu_reg()); | 4228 const DRegister right = EvenDRegisterOf(locs()->in(1).fpu_reg()); |
| 4325 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 4229 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
| 4326 switch (op_kind()) { | 4230 switch (op_kind()) { |
| 4327 case Token::kADD: __ vaddd(result, left, right); break; | 4231 case Token::kADD: |
| 4328 case Token::kSUB: __ vsubd(result, left, right); break; | 4232 __ vaddd(result, left, right); |
| 4329 case Token::kMUL: __ vmuld(result, left, right); break; | 4233 break; |
| 4330 case Token::kDIV: __ vdivd(result, left, right); break; | 4234 case Token::kSUB: |
| 4331 default: UNREACHABLE(); | 4235 __ vsubd(result, left, right); |
| 4236 break; |
| 4237 case Token::kMUL: |
| 4238 __ vmuld(result, left, right); |
| 4239 break; |
| 4240 case Token::kDIV: |
| 4241 __ vdivd(result, left, right); |
| 4242 break; |
| 4243 default: |
| 4244 UNREACHABLE(); |
| 4332 } | 4245 } |
| 4333 } | 4246 } |
| 4334 | 4247 |
| 4335 | 4248 |
| 4336 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 4249 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |
| 4337 bool opt) const { | 4250 bool opt) const { |
| 4338 const intptr_t kNumInputs = 1; | 4251 const intptr_t kNumInputs = 1; |
| 4339 const intptr_t kNumTemps = | 4252 const intptr_t kNumTemps = |
| 4340 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; | 4253 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; |
| 4341 LocationSummary* summary = new(zone) LocationSummary( | 4254 LocationSummary* summary = new (zone) |
| 4342 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4255 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4343 summary->set_in(0, Location::RequiresFpuRegister()); | 4256 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4344 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 4257 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
| 4345 summary->set_temp(0, Location::RequiresRegister()); | 4258 summary->set_temp(0, Location::RequiresRegister()); |
| 4346 } | 4259 } |
| 4347 summary->set_out(0, Location::RequiresRegister()); | 4260 summary->set_out(0, Location::RequiresRegister()); |
| 4348 return summary; | 4261 return summary; |
| 4349 } | 4262 } |
| 4350 | 4263 |
| 4351 | 4264 |
| 4352 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 4265 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 4379 ASSERT(compiler->is_optimizing()); | 4292 ASSERT(compiler->is_optimizing()); |
| 4380 BranchLabels labels = compiler->CreateBranchLabels(branch); | 4293 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 4381 Condition true_condition = EmitComparisonCode(compiler, labels); | 4294 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 4382 EmitBranchOnCondition(compiler, true_condition, labels); | 4295 EmitBranchOnCondition(compiler, true_condition, labels); |
| 4383 } | 4296 } |
| 4384 | 4297 |
| 4385 | 4298 |
| 4386 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4299 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4387 ASSERT(compiler->is_optimizing()); | 4300 ASSERT(compiler->is_optimizing()); |
| 4388 Label is_true, is_false; | 4301 Label is_true, is_false; |
| 4389 BranchLabels labels = { &is_true, &is_false, &is_false }; | 4302 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 4390 Condition true_condition = EmitComparisonCode(compiler, labels); | 4303 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 4391 const Register result = locs()->out(0).reg(); | 4304 const Register result = locs()->out(0).reg(); |
| 4392 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { | 4305 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { |
| 4393 __ LoadObject(result, Bool::True(), true_condition); | 4306 __ LoadObject(result, Bool::True(), true_condition); |
| 4394 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 4307 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 4395 } else { | 4308 } else { |
| 4396 ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite); | 4309 ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite); |
| 4397 EmitBranchOnCondition(compiler, true_condition, labels); | 4310 EmitBranchOnCondition(compiler, true_condition, labels); |
| 4398 Label done; | 4311 Label done; |
| 4399 __ Bind(&is_false); | 4312 __ Bind(&is_false); |
| 4400 __ LoadObject(result, Bool::False()); | 4313 __ LoadObject(result, Bool::False()); |
| 4401 __ b(&done); | 4314 __ b(&done); |
| 4402 __ Bind(&is_true); | 4315 __ Bind(&is_true); |
| 4403 __ LoadObject(result, Bool::True()); | 4316 __ LoadObject(result, Bool::True()); |
| 4404 __ Bind(&done); | 4317 __ Bind(&done); |
| 4405 } | 4318 } |
| 4406 } | 4319 } |
| 4407 | 4320 |
| 4408 | 4321 |
| 4409 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 4322 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 4410 bool opt) const { | 4323 bool opt) const { |
| 4411 const intptr_t kNumInputs = 2; | 4324 const intptr_t kNumInputs = 2; |
| 4412 const intptr_t kNumTemps = 0; | 4325 const intptr_t kNumTemps = 0; |
| 4413 LocationSummary* summary = new(zone) LocationSummary( | 4326 LocationSummary* summary = new (zone) |
| 4414 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4327 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4415 summary->set_in(0, Location::RequiresFpuRegister()); | 4328 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4416 summary->set_in(1, Location::RequiresFpuRegister()); | 4329 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4417 summary->set_out(0, Location::RequiresFpuRegister()); | 4330 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4418 return summary; | 4331 return summary; |
| 4419 } | 4332 } |
| 4420 | 4333 |
| 4421 | 4334 |
| 4422 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4335 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4423 const QRegister left = locs()->in(0).fpu_reg(); | 4336 const QRegister left = locs()->in(0).fpu_reg(); |
| 4424 const QRegister right = locs()->in(1).fpu_reg(); | 4337 const QRegister right = locs()->in(1).fpu_reg(); |
| 4425 const QRegister result = locs()->out(0).fpu_reg(); | 4338 const QRegister result = locs()->out(0).fpu_reg(); |
| 4426 | 4339 |
| 4427 switch (op_kind()) { | 4340 switch (op_kind()) { |
| 4428 case Token::kADD: __ vaddqs(result, left, right); break; | 4341 case Token::kADD: |
| 4429 case Token::kSUB: __ vsubqs(result, left, right); break; | 4342 __ vaddqs(result, left, right); |
| 4430 case Token::kMUL: __ vmulqs(result, left, right); break; | 4343 break; |
| 4431 case Token::kDIV: __ Vdivqs(result, left, right); break; | 4344 case Token::kSUB: |
| 4432 default: UNREACHABLE(); | 4345 __ vsubqs(result, left, right); |
| 4346 break; |
| 4347 case Token::kMUL: |
| 4348 __ vmulqs(result, left, right); |
| 4349 break; |
| 4350 case Token::kDIV: |
| 4351 __ Vdivqs(result, left, right); |
| 4352 break; |
| 4353 default: |
| 4354 UNREACHABLE(); |
| 4433 } | 4355 } |
| 4434 } | 4356 } |
| 4435 | 4357 |
| 4436 | 4358 |
| 4437 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, | 4359 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, |
| 4438 bool opt) const { | 4360 bool opt) const { |
| 4439 const intptr_t kNumInputs = 2; | 4361 const intptr_t kNumInputs = 2; |
| 4440 const intptr_t kNumTemps = 0; | 4362 const intptr_t kNumTemps = 0; |
| 4441 LocationSummary* summary = new(zone) LocationSummary( | 4363 LocationSummary* summary = new (zone) |
| 4442 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4364 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4443 summary->set_in(0, Location::RequiresFpuRegister()); | 4365 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4444 summary->set_in(1, Location::RequiresFpuRegister()); | 4366 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4445 summary->set_out(0, Location::RequiresFpuRegister()); | 4367 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4446 return summary; | 4368 return summary; |
| 4447 } | 4369 } |
| 4448 | 4370 |
| 4449 | 4371 |
| 4450 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4372 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4451 const QRegister left = locs()->in(0).fpu_reg(); | 4373 const QRegister left = locs()->in(0).fpu_reg(); |
| 4452 const QRegister right = locs()->in(1).fpu_reg(); | 4374 const QRegister right = locs()->in(1).fpu_reg(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4471 __ vsubd(result1, left1, right1); | 4393 __ vsubd(result1, left1, right1); |
| 4472 break; | 4394 break; |
| 4473 case Token::kMUL: | 4395 case Token::kMUL: |
| 4474 __ vmuld(result0, left0, right0); | 4396 __ vmuld(result0, left0, right0); |
| 4475 __ vmuld(result1, left1, right1); | 4397 __ vmuld(result1, left1, right1); |
| 4476 break; | 4398 break; |
| 4477 case Token::kDIV: | 4399 case Token::kDIV: |
| 4478 __ vdivd(result0, left0, right0); | 4400 __ vdivd(result0, left0, right0); |
| 4479 __ vdivd(result1, left1, right1); | 4401 __ vdivd(result1, left1, right1); |
| 4480 break; | 4402 break; |
| 4481 default: UNREACHABLE(); | 4403 default: |
| 4404 UNREACHABLE(); |
| 4482 } | 4405 } |
| 4483 } | 4406 } |
| 4484 | 4407 |
| 4485 | 4408 |
| 4486 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, | 4409 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 4487 bool opt) const { | 4410 bool opt) const { |
| 4488 const intptr_t kNumInputs = 1; | 4411 const intptr_t kNumInputs = 1; |
| 4489 const intptr_t kNumTemps = 0; | 4412 const intptr_t kNumTemps = 0; |
| 4490 LocationSummary* summary = new(zone) LocationSummary( | 4413 LocationSummary* summary = new (zone) |
| 4491 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4414 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4492 // Low (< Q7) Q registers are needed for the vcvtds and vmovs instructions. | 4415 // Low (< Q7) Q registers are needed for the vcvtds and vmovs instructions. |
| 4493 summary->set_in(0, Location::FpuRegisterLocation(Q5)); | 4416 summary->set_in(0, Location::FpuRegisterLocation(Q5)); |
| 4494 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 4417 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
| 4495 return summary; | 4418 return summary; |
| 4496 } | 4419 } |
| 4497 | 4420 |
| 4498 | 4421 |
| 4499 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4422 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4500 const QRegister value = locs()->in(0).fpu_reg(); | 4423 const QRegister value = locs()->in(0).fpu_reg(); |
| 4501 const QRegister result = locs()->out(0).fpu_reg(); | 4424 const QRegister result = locs()->out(0).fpu_reg(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4533 __ vcvtds(dresult0, svalue3); | 4456 __ vcvtds(dresult0, svalue3); |
| 4534 break; | 4457 break; |
| 4535 case MethodRecognizer::kInt32x4Shuffle: | 4458 case MethodRecognizer::kInt32x4Shuffle: |
| 4536 case MethodRecognizer::kFloat32x4Shuffle: | 4459 case MethodRecognizer::kFloat32x4Shuffle: |
| 4537 if (mask_ == 0x00) { | 4460 if (mask_ == 0x00) { |
| 4538 __ vdup(kWord, result, dvalue0, 0); | 4461 __ vdup(kWord, result, dvalue0, 0); |
| 4539 } else if (mask_ == 0x55) { | 4462 } else if (mask_ == 0x55) { |
| 4540 __ vdup(kWord, result, dvalue0, 1); | 4463 __ vdup(kWord, result, dvalue0, 1); |
| 4541 } else if (mask_ == 0xAA) { | 4464 } else if (mask_ == 0xAA) { |
| 4542 __ vdup(kWord, result, dvalue1, 0); | 4465 __ vdup(kWord, result, dvalue1, 0); |
| 4543 } else if (mask_ == 0xFF) { | 4466 } else if (mask_ == 0xFF) { |
| 4544 __ vdup(kWord, result, dvalue1, 1); | 4467 __ vdup(kWord, result, dvalue1, 1); |
| 4545 } else { | 4468 } else { |
| 4546 // TODO(zra): Investigate better instruction sequences for other | 4469 // TODO(zra): Investigate better instruction sequences for other |
| 4547 // shuffle masks. | 4470 // shuffle masks. |
| 4548 SRegister svalues[4]; | 4471 SRegister svalues[4]; |
| 4549 | 4472 |
| 4550 svalues[0] = EvenSRegisterOf(dtemp0); | 4473 svalues[0] = EvenSRegisterOf(dtemp0); |
| 4551 svalues[1] = OddSRegisterOf(dtemp0); | 4474 svalues[1] = OddSRegisterOf(dtemp0); |
| 4552 svalues[2] = EvenSRegisterOf(dtemp1); | 4475 svalues[2] = EvenSRegisterOf(dtemp1); |
| 4553 svalues[3] = OddSRegisterOf(dtemp1); | 4476 svalues[3] = OddSRegisterOf(dtemp1); |
| 4554 | 4477 |
| 4555 __ vmovq(QTMP, value); | 4478 __ vmovq(QTMP, value); |
| 4556 __ vmovs(sresult0, svalues[mask_ & 0x3]); | 4479 __ vmovs(sresult0, svalues[mask_ & 0x3]); |
| 4557 __ vmovs(sresult1, svalues[(mask_ >> 2) & 0x3]); | 4480 __ vmovs(sresult1, svalues[(mask_ >> 2) & 0x3]); |
| 4558 __ vmovs(sresult2, svalues[(mask_ >> 4) & 0x3]); | 4481 __ vmovs(sresult2, svalues[(mask_ >> 4) & 0x3]); |
| 4559 __ vmovs(sresult3, svalues[(mask_ >> 6) & 0x3]); | 4482 __ vmovs(sresult3, svalues[(mask_ >> 6) & 0x3]); |
| 4560 } | 4483 } |
| 4561 break; | 4484 break; |
| 4562 default: UNREACHABLE(); | 4485 default: |
| 4486 UNREACHABLE(); |
| 4563 } | 4487 } |
| 4564 } | 4488 } |
| 4565 | 4489 |
| 4566 | 4490 |
| 4567 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 4491 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |
| 4568 bool opt) const { | 4492 bool opt) const { |
| 4569 const intptr_t kNumInputs = 2; | 4493 const intptr_t kNumInputs = 2; |
| 4570 const intptr_t kNumTemps = 0; | 4494 const intptr_t kNumTemps = 0; |
| 4571 LocationSummary* summary = new(zone) LocationSummary( | 4495 LocationSummary* summary = new (zone) |
| 4572 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4496 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4573 // Low (< Q7) Q registers are needed for the vcvtds and vmovs instructions. | 4497 // Low (< Q7) Q registers are needed for the vcvtds and vmovs instructions. |
| 4574 summary->set_in(0, Location::FpuRegisterLocation(Q4)); | 4498 summary->set_in(0, Location::FpuRegisterLocation(Q4)); |
| 4575 summary->set_in(1, Location::FpuRegisterLocation(Q5)); | 4499 summary->set_in(1, Location::FpuRegisterLocation(Q5)); |
| 4576 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 4500 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
| 4577 return summary; | 4501 return summary; |
| 4578 } | 4502 } |
| 4579 | 4503 |
| 4580 | 4504 |
| 4581 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4505 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4582 const QRegister left = locs()->in(0).fpu_reg(); | 4506 const QRegister left = locs()->in(0).fpu_reg(); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 4609 right_svalues[0] = EvenSRegisterOf(dright0); | 4533 right_svalues[0] = EvenSRegisterOf(dright0); |
| 4610 right_svalues[1] = OddSRegisterOf(dright0); | 4534 right_svalues[1] = OddSRegisterOf(dright0); |
| 4611 right_svalues[2] = EvenSRegisterOf(dright1); | 4535 right_svalues[2] = EvenSRegisterOf(dright1); |
| 4612 right_svalues[3] = OddSRegisterOf(dright1); | 4536 right_svalues[3] = OddSRegisterOf(dright1); |
| 4613 | 4537 |
| 4614 __ vmovs(sresult0, left_svalues[mask_ & 0x3]); | 4538 __ vmovs(sresult0, left_svalues[mask_ & 0x3]); |
| 4615 __ vmovs(sresult1, left_svalues[(mask_ >> 2) & 0x3]); | 4539 __ vmovs(sresult1, left_svalues[(mask_ >> 2) & 0x3]); |
| 4616 __ vmovs(sresult2, right_svalues[(mask_ >> 4) & 0x3]); | 4540 __ vmovs(sresult2, right_svalues[(mask_ >> 4) & 0x3]); |
| 4617 __ vmovs(sresult3, right_svalues[(mask_ >> 6) & 0x3]); | 4541 __ vmovs(sresult3, right_svalues[(mask_ >> 6) & 0x3]); |
| 4618 break; | 4542 break; |
| 4619 default: UNREACHABLE(); | 4543 default: |
| 4544 UNREACHABLE(); |
| 4620 } | 4545 } |
| 4621 } | 4546 } |
| 4622 | 4547 |
| 4623 | 4548 |
| 4624 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, | 4549 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, |
| 4625 bool opt) const { | 4550 bool opt) const { |
| 4626 const intptr_t kNumInputs = 1; | 4551 const intptr_t kNumInputs = 1; |
| 4627 const intptr_t kNumTemps = 1; | 4552 const intptr_t kNumTemps = 1; |
| 4628 LocationSummary* summary = new(zone) LocationSummary( | 4553 LocationSummary* summary = new (zone) |
| 4629 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4554 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4630 summary->set_in(0, Location::FpuRegisterLocation(Q5)); | 4555 summary->set_in(0, Location::FpuRegisterLocation(Q5)); |
| 4631 summary->set_temp(0, Location::RequiresRegister()); | 4556 summary->set_temp(0, Location::RequiresRegister()); |
| 4632 summary->set_out(0, Location::RequiresRegister()); | 4557 summary->set_out(0, Location::RequiresRegister()); |
| 4633 return summary; | 4558 return summary; |
| 4634 } | 4559 } |
| 4635 | 4560 |
| 4636 | 4561 |
| 4637 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4562 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4638 const QRegister value = locs()->in(0).fpu_reg(); | 4563 const QRegister value = locs()->in(0).fpu_reg(); |
| 4639 const DRegister dvalue0 = EvenDRegisterOf(value); | 4564 const DRegister dvalue0 = EvenDRegisterOf(value); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 4656 // W lane. | 4581 // W lane. |
| 4657 __ vmovrs(temp, OddSRegisterOf(dvalue1)); | 4582 __ vmovrs(temp, OddSRegisterOf(dvalue1)); |
| 4658 __ Lsr(temp, temp, Operand(31)); | 4583 __ Lsr(temp, temp, Operand(31)); |
| 4659 __ orr(out, out, Operand(temp, LSL, 3)); | 4584 __ orr(out, out, Operand(temp, LSL, 3)); |
| 4660 // Tag. | 4585 // Tag. |
| 4661 __ SmiTag(out); | 4586 __ SmiTag(out); |
| 4662 } | 4587 } |
| 4663 | 4588 |
| 4664 | 4589 |
| 4665 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 4590 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
| 4666 Zone* zone, bool opt) const { | 4591 Zone* zone, |
| 4592 bool opt) const { |
| 4667 const intptr_t kNumInputs = 4; | 4593 const intptr_t kNumInputs = 4; |
| 4668 const intptr_t kNumTemps = 0; | 4594 const intptr_t kNumTemps = 0; |
| 4669 LocationSummary* summary = new(zone) LocationSummary( | 4595 LocationSummary* summary = new (zone) |
| 4670 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4596 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4671 summary->set_in(0, Location::RequiresFpuRegister()); | 4597 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4672 summary->set_in(1, Location::RequiresFpuRegister()); | 4598 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4673 summary->set_in(2, Location::RequiresFpuRegister()); | 4599 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4674 summary->set_in(3, Location::RequiresFpuRegister()); | 4600 summary->set_in(3, Location::RequiresFpuRegister()); |
| 4675 // Low (< 7) Q registers are needed for the vcvtsd instruction. | 4601 // Low (< 7) Q registers are needed for the vcvtsd instruction. |
| 4676 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 4602 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
| 4677 return summary; | 4603 return summary; |
| 4678 } | 4604 } |
| 4679 | 4605 |
| 4680 | 4606 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4692 __ vcvtsd(OddSRegisterOf(dr0), EvenDRegisterOf(q1)); | 4618 __ vcvtsd(OddSRegisterOf(dr0), EvenDRegisterOf(q1)); |
| 4693 __ vcvtsd(EvenSRegisterOf(dr1), EvenDRegisterOf(q2)); | 4619 __ vcvtsd(EvenSRegisterOf(dr1), EvenDRegisterOf(q2)); |
| 4694 __ vcvtsd(OddSRegisterOf(dr1), EvenDRegisterOf(q3)); | 4620 __ vcvtsd(OddSRegisterOf(dr1), EvenDRegisterOf(q3)); |
| 4695 } | 4621 } |
| 4696 | 4622 |
| 4697 | 4623 |
| 4698 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, | 4624 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, |
| 4699 bool opt) const { | 4625 bool opt) const { |
| 4700 const intptr_t kNumInputs = 0; | 4626 const intptr_t kNumInputs = 0; |
| 4701 const intptr_t kNumTemps = 0; | 4627 const intptr_t kNumTemps = 0; |
| 4702 LocationSummary* summary = new(zone) LocationSummary( | 4628 LocationSummary* summary = new (zone) |
| 4703 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4629 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4704 summary->set_out(0, Location::RequiresFpuRegister()); | 4630 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4705 return summary; | 4631 return summary; |
| 4706 } | 4632 } |
| 4707 | 4633 |
| 4708 | 4634 |
| 4709 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4635 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4710 const QRegister q = locs()->out(0).fpu_reg(); | 4636 const QRegister q = locs()->out(0).fpu_reg(); |
| 4711 __ veorq(q, q, q); | 4637 __ veorq(q, q, q); |
| 4712 } | 4638 } |
| 4713 | 4639 |
| 4714 | 4640 |
| 4715 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, | 4641 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, |
| 4716 bool opt) const { | 4642 bool opt) const { |
| 4717 const intptr_t kNumInputs = 1; | 4643 const intptr_t kNumInputs = 1; |
| 4718 const intptr_t kNumTemps = 0; | 4644 const intptr_t kNumTemps = 0; |
| 4719 LocationSummary* summary = new(zone) LocationSummary( | 4645 LocationSummary* summary = new (zone) |
| 4720 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4646 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4721 summary->set_in(0, Location::RequiresFpuRegister()); | 4647 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4722 summary->set_out(0, Location::RequiresFpuRegister()); | 4648 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4723 return summary; | 4649 return summary; |
| 4724 } | 4650 } |
| 4725 | 4651 |
| 4726 | 4652 |
| 4727 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4653 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4728 const QRegister value = locs()->in(0).fpu_reg(); | 4654 const QRegister value = locs()->in(0).fpu_reg(); |
| 4729 const QRegister result = locs()->out(0).fpu_reg(); | 4655 const QRegister result = locs()->out(0).fpu_reg(); |
| 4730 | 4656 |
| 4731 const DRegister dvalue0 = EvenDRegisterOf(value); | 4657 const DRegister dvalue0 = EvenDRegisterOf(value); |
| 4732 | 4658 |
| 4733 // Convert to Float32. | 4659 // Convert to Float32. |
| 4734 __ vcvtsd(STMP, dvalue0); | 4660 __ vcvtsd(STMP, dvalue0); |
| 4735 | 4661 |
| 4736 // Splat across all lanes. | 4662 // Splat across all lanes. |
| 4737 __ vdup(kWord, result, DTMP, 0); | 4663 __ vdup(kWord, result, DTMP, 0); |
| 4738 } | 4664 } |
| 4739 | 4665 |
| 4740 | 4666 |
| 4741 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, | 4667 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, |
| 4742 bool opt) const { | 4668 bool opt) const { |
| 4743 const intptr_t kNumInputs = 2; | 4669 const intptr_t kNumInputs = 2; |
| 4744 const intptr_t kNumTemps = 0; | 4670 const intptr_t kNumTemps = 0; |
| 4745 LocationSummary* summary = new(zone) LocationSummary( | 4671 LocationSummary* summary = new (zone) |
| 4746 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4672 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4747 summary->set_in(0, Location::RequiresFpuRegister()); | 4673 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4748 summary->set_in(1, Location::RequiresFpuRegister()); | 4674 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4749 summary->set_out(0, Location::RequiresFpuRegister()); | 4675 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4750 return summary; | 4676 return summary; |
| 4751 } | 4677 } |
| 4752 | 4678 |
| 4753 | 4679 |
| 4754 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4680 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4755 const QRegister left = locs()->in(0).fpu_reg(); | 4681 const QRegister left = locs()->in(0).fpu_reg(); |
| 4756 const QRegister right = locs()->in(1).fpu_reg(); | 4682 const QRegister right = locs()->in(1).fpu_reg(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4771 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: | 4697 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: |
| 4772 __ vcgeqs(result, left, right); | 4698 __ vcgeqs(result, left, right); |
| 4773 break; | 4699 break; |
| 4774 case MethodRecognizer::kFloat32x4LessThan: | 4700 case MethodRecognizer::kFloat32x4LessThan: |
| 4775 __ vcgtqs(result, right, left); | 4701 __ vcgtqs(result, right, left); |
| 4776 break; | 4702 break; |
| 4777 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 4703 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
| 4778 __ vcgeqs(result, right, left); | 4704 __ vcgeqs(result, right, left); |
| 4779 break; | 4705 break; |
| 4780 | 4706 |
| 4781 default: UNREACHABLE(); | 4707 default: |
| 4708 UNREACHABLE(); |
| 4782 } | 4709 } |
| 4783 } | 4710 } |
| 4784 | 4711 |
| 4785 | 4712 |
| 4786 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, | 4713 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, |
| 4787 bool opt) const { | 4714 bool opt) const { |
| 4788 const intptr_t kNumInputs = 2; | 4715 const intptr_t kNumInputs = 2; |
| 4789 const intptr_t kNumTemps = 0; | 4716 const intptr_t kNumTemps = 0; |
| 4790 LocationSummary* summary = new(zone) LocationSummary( | 4717 LocationSummary* summary = new (zone) |
| 4791 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4718 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4792 summary->set_in(0, Location::RequiresFpuRegister()); | 4719 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4793 summary->set_in(1, Location::RequiresFpuRegister()); | 4720 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4794 summary->set_out(0, Location::RequiresFpuRegister()); | 4721 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4795 return summary; | 4722 return summary; |
| 4796 } | 4723 } |
| 4797 | 4724 |
| 4798 | 4725 |
| 4799 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4726 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4800 const QRegister left = locs()->in(0).fpu_reg(); | 4727 const QRegister left = locs()->in(0).fpu_reg(); |
| 4801 const QRegister right = locs()->in(1).fpu_reg(); | 4728 const QRegister right = locs()->in(1).fpu_reg(); |
| 4802 const QRegister result = locs()->out(0).fpu_reg(); | 4729 const QRegister result = locs()->out(0).fpu_reg(); |
| 4803 | 4730 |
| 4804 switch (op_kind()) { | 4731 switch (op_kind()) { |
| 4805 case MethodRecognizer::kFloat32x4Min: | 4732 case MethodRecognizer::kFloat32x4Min: |
| 4806 __ vminqs(result, left, right); | 4733 __ vminqs(result, left, right); |
| 4807 break; | 4734 break; |
| 4808 case MethodRecognizer::kFloat32x4Max: | 4735 case MethodRecognizer::kFloat32x4Max: |
| 4809 __ vmaxqs(result, left, right); | 4736 __ vmaxqs(result, left, right); |
| 4810 break; | 4737 break; |
| 4811 default: UNREACHABLE(); | 4738 default: |
| 4739 UNREACHABLE(); |
| 4812 } | 4740 } |
| 4813 } | 4741 } |
| 4814 | 4742 |
| 4815 | 4743 |
| 4816 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, | 4744 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, |
| 4817 bool opt) const { | 4745 bool opt) const { |
| 4818 const intptr_t kNumInputs = 1; | 4746 const intptr_t kNumInputs = 1; |
| 4819 const intptr_t kNumTemps = 1; | 4747 const intptr_t kNumTemps = 1; |
| 4820 LocationSummary* summary = new(zone) LocationSummary( | 4748 LocationSummary* summary = new (zone) |
| 4821 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4749 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4822 summary->set_in(0, Location::RequiresFpuRegister()); | 4750 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4823 summary->set_out(0, Location::RequiresFpuRegister()); | 4751 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4824 summary->set_temp(0, Location::RequiresFpuRegister()); | 4752 summary->set_temp(0, Location::RequiresFpuRegister()); |
| 4825 return summary; | 4753 return summary; |
| 4826 } | 4754 } |
| 4827 | 4755 |
| 4828 | 4756 |
| 4829 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4757 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4830 const QRegister left = locs()->in(0).fpu_reg(); | 4758 const QRegister left = locs()->in(0).fpu_reg(); |
| 4831 const QRegister result = locs()->out(0).fpu_reg(); | 4759 const QRegister result = locs()->out(0).fpu_reg(); |
| 4832 const QRegister temp = locs()->temp(0).fpu_reg(); | 4760 const QRegister temp = locs()->temp(0).fpu_reg(); |
| 4833 | 4761 |
| 4834 switch (op_kind()) { | 4762 switch (op_kind()) { |
| 4835 case MethodRecognizer::kFloat32x4Sqrt: | 4763 case MethodRecognizer::kFloat32x4Sqrt: |
| 4836 __ Vsqrtqs(result, left, temp); | 4764 __ Vsqrtqs(result, left, temp); |
| 4837 break; | 4765 break; |
| 4838 case MethodRecognizer::kFloat32x4Reciprocal: | 4766 case MethodRecognizer::kFloat32x4Reciprocal: |
| 4839 __ Vreciprocalqs(result, left); | 4767 __ Vreciprocalqs(result, left); |
| 4840 break; | 4768 break; |
| 4841 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 4769 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
| 4842 __ VreciprocalSqrtqs(result, left); | 4770 __ VreciprocalSqrtqs(result, left); |
| 4843 break; | 4771 break; |
| 4844 default: UNREACHABLE(); | 4772 default: |
| 4773 UNREACHABLE(); |
| 4845 } | 4774 } |
| 4846 } | 4775 } |
| 4847 | 4776 |
| 4848 | 4777 |
| 4849 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, | 4778 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, |
| 4850 bool opt) const { | 4779 bool opt) const { |
| 4851 const intptr_t kNumInputs = 2; | 4780 const intptr_t kNumInputs = 2; |
| 4852 const intptr_t kNumTemps = 0; | 4781 const intptr_t kNumTemps = 0; |
| 4853 LocationSummary* summary = new(zone) LocationSummary( | 4782 LocationSummary* summary = new (zone) |
| 4854 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4783 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4855 summary->set_in(0, Location::RequiresFpuRegister()); | 4784 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4856 summary->set_in(1, Location::RequiresFpuRegister()); | 4785 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4857 summary->set_out(0, Location::RequiresFpuRegister()); | 4786 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4858 return summary; | 4787 return summary; |
| 4859 } | 4788 } |
| 4860 | 4789 |
| 4861 | 4790 |
| 4862 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4791 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4863 const QRegister left = locs()->in(0).fpu_reg(); | 4792 const QRegister left = locs()->in(0).fpu_reg(); |
| 4864 const QRegister right = locs()->in(1).fpu_reg(); | 4793 const QRegister right = locs()->in(1).fpu_reg(); |
| 4865 const QRegister result = locs()->out(0).fpu_reg(); | 4794 const QRegister result = locs()->out(0).fpu_reg(); |
| 4866 | 4795 |
| 4867 switch (op_kind()) { | 4796 switch (op_kind()) { |
| 4868 case MethodRecognizer::kFloat32x4Scale: | 4797 case MethodRecognizer::kFloat32x4Scale: |
| 4869 __ vcvtsd(STMP, EvenDRegisterOf(left)); | 4798 __ vcvtsd(STMP, EvenDRegisterOf(left)); |
| 4870 __ vdup(kWord, result, DTMP, 0); | 4799 __ vdup(kWord, result, DTMP, 0); |
| 4871 __ vmulqs(result, result, right); | 4800 __ vmulqs(result, result, right); |
| 4872 break; | 4801 break; |
| 4873 default: UNREACHABLE(); | 4802 default: |
| 4803 UNREACHABLE(); |
| 4874 } | 4804 } |
| 4875 } | 4805 } |
| 4876 | 4806 |
| 4877 | 4807 |
| 4878 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4808 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, |
| 4879 bool opt) const { | 4809 bool opt) const { |
| 4880 const intptr_t kNumInputs = 1; | 4810 const intptr_t kNumInputs = 1; |
| 4881 const intptr_t kNumTemps = 0; | 4811 const intptr_t kNumTemps = 0; |
| 4882 LocationSummary* summary = new(zone) LocationSummary( | 4812 LocationSummary* summary = new (zone) |
| 4883 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4813 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4884 summary->set_in(0, Location::RequiresFpuRegister()); | 4814 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4885 summary->set_out(0, Location::RequiresFpuRegister()); | 4815 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4886 return summary; | 4816 return summary; |
| 4887 } | 4817 } |
| 4888 | 4818 |
| 4889 | 4819 |
| 4890 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4820 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4891 const QRegister left = locs()->in(0).fpu_reg(); | 4821 const QRegister left = locs()->in(0).fpu_reg(); |
| 4892 const QRegister result = locs()->out(0).fpu_reg(); | 4822 const QRegister result = locs()->out(0).fpu_reg(); |
| 4893 | 4823 |
| 4894 switch (op_kind()) { | 4824 switch (op_kind()) { |
| 4895 case MethodRecognizer::kFloat32x4Negate: | 4825 case MethodRecognizer::kFloat32x4Negate: |
| 4896 __ vnegqs(result, left); | 4826 __ vnegqs(result, left); |
| 4897 break; | 4827 break; |
| 4898 case MethodRecognizer::kFloat32x4Absolute: | 4828 case MethodRecognizer::kFloat32x4Absolute: |
| 4899 __ vabsqs(result, left); | 4829 __ vabsqs(result, left); |
| 4900 break; | 4830 break; |
| 4901 default: UNREACHABLE(); | 4831 default: |
| 4832 UNREACHABLE(); |
| 4902 } | 4833 } |
| 4903 } | 4834 } |
| 4904 | 4835 |
| 4905 | 4836 |
| 4906 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, | 4837 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, |
| 4907 bool opt) const { | 4838 bool opt) const { |
| 4908 const intptr_t kNumInputs = 3; | 4839 const intptr_t kNumInputs = 3; |
| 4909 const intptr_t kNumTemps = 0; | 4840 const intptr_t kNumTemps = 0; |
| 4910 LocationSummary* summary = new(zone) LocationSummary( | 4841 LocationSummary* summary = new (zone) |
| 4911 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4842 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4912 summary->set_in(0, Location::RequiresFpuRegister()); | 4843 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4913 summary->set_in(1, Location::RequiresFpuRegister()); | 4844 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4914 summary->set_in(2, Location::RequiresFpuRegister()); | 4845 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4915 summary->set_out(0, Location::RequiresFpuRegister()); | 4846 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4916 return summary; | 4847 return summary; |
| 4917 } | 4848 } |
| 4918 | 4849 |
| 4919 | 4850 |
| 4920 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4851 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4921 const QRegister left = locs()->in(0).fpu_reg(); | 4852 const QRegister left = locs()->in(0).fpu_reg(); |
| 4922 const QRegister lower = locs()->in(1).fpu_reg(); | 4853 const QRegister lower = locs()->in(1).fpu_reg(); |
| 4923 const QRegister upper = locs()->in(2).fpu_reg(); | 4854 const QRegister upper = locs()->in(2).fpu_reg(); |
| 4924 const QRegister result = locs()->out(0).fpu_reg(); | 4855 const QRegister result = locs()->out(0).fpu_reg(); |
| 4925 __ vminqs(result, left, upper); | 4856 __ vminqs(result, left, upper); |
| 4926 __ vmaxqs(result, result, lower); | 4857 __ vmaxqs(result, result, lower); |
| 4927 } | 4858 } |
| 4928 | 4859 |
| 4929 | 4860 |
| 4930 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, | 4861 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, |
| 4931 bool opt) const { | 4862 bool opt) const { |
| 4932 const intptr_t kNumInputs = 2; | 4863 const intptr_t kNumInputs = 2; |
| 4933 const intptr_t kNumTemps = 0; | 4864 const intptr_t kNumTemps = 0; |
| 4934 LocationSummary* summary = new(zone) LocationSummary( | 4865 LocationSummary* summary = new (zone) |
| 4935 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4866 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4936 summary->set_in(0, Location::RequiresFpuRegister()); | 4867 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4937 summary->set_in(1, Location::RequiresFpuRegister()); | 4868 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4938 // Low (< 7) Q registers are needed for the vmovs instruction. | 4869 // Low (< 7) Q registers are needed for the vmovs instruction. |
| 4939 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 4870 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
| 4940 return summary; | 4871 return summary; |
| 4941 } | 4872 } |
| 4942 | 4873 |
| 4943 | 4874 |
| 4944 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4875 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4945 const QRegister replacement = locs()->in(0).fpu_reg(); | 4876 const QRegister replacement = locs()->in(0).fpu_reg(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4964 break; | 4895 break; |
| 4965 case MethodRecognizer::kFloat32x4WithY: | 4896 case MethodRecognizer::kFloat32x4WithY: |
| 4966 __ vmovs(sresult1, STMP); | 4897 __ vmovs(sresult1, STMP); |
| 4967 break; | 4898 break; |
| 4968 case MethodRecognizer::kFloat32x4WithZ: | 4899 case MethodRecognizer::kFloat32x4WithZ: |
| 4969 __ vmovs(sresult2, STMP); | 4900 __ vmovs(sresult2, STMP); |
| 4970 break; | 4901 break; |
| 4971 case MethodRecognizer::kFloat32x4WithW: | 4902 case MethodRecognizer::kFloat32x4WithW: |
| 4972 __ vmovs(sresult3, STMP); | 4903 __ vmovs(sresult3, STMP); |
| 4973 break; | 4904 break; |
| 4974 default: UNREACHABLE(); | 4905 default: |
| 4906 UNREACHABLE(); |
| 4975 } | 4907 } |
| 4976 } | 4908 } |
| 4977 | 4909 |
| 4978 | 4910 |
| 4979 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, | 4911 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, |
| 4980 bool opt) const { | 4912 bool opt) const { |
| 4981 const intptr_t kNumInputs = 1; | 4913 const intptr_t kNumInputs = 1; |
| 4982 const intptr_t kNumTemps = 0; | 4914 const intptr_t kNumTemps = 0; |
| 4983 LocationSummary* summary = new(zone) LocationSummary( | 4915 LocationSummary* summary = new (zone) |
| 4984 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4916 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4985 summary->set_in(0, Location::RequiresFpuRegister()); | 4917 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4986 summary->set_out(0, Location::RequiresFpuRegister()); | 4918 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4987 return summary; | 4919 return summary; |
| 4988 } | 4920 } |
| 4989 | 4921 |
| 4990 | 4922 |
| 4991 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4923 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4992 const QRegister value = locs()->in(0).fpu_reg(); | 4924 const QRegister value = locs()->in(0).fpu_reg(); |
| 4993 const QRegister result = locs()->out(0).fpu_reg(); | 4925 const QRegister result = locs()->out(0).fpu_reg(); |
| 4994 | 4926 |
| 4995 if (value != result) { | 4927 if (value != result) { |
| 4996 __ vmovq(result, value); | 4928 __ vmovq(result, value); |
| 4997 } | 4929 } |
| 4998 } | 4930 } |
| 4999 | 4931 |
| 5000 | 4932 |
| 5001 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 4933 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 5002 bool opt) const { | 4934 bool opt) const { |
| 5003 const intptr_t kNumInputs = 1; | 4935 const intptr_t kNumInputs = 1; |
| 5004 const intptr_t kNumTemps = 0; | 4936 const intptr_t kNumTemps = 0; |
| 5005 LocationSummary* summary = new(zone) LocationSummary( | 4937 LocationSummary* summary = new (zone) |
| 5006 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4938 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5007 summary->set_in(0, Location::RequiresFpuRegister()); | 4939 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5008 summary->set_out(0, Location::RequiresFpuRegister()); | 4940 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5009 return summary; | 4941 return summary; |
| 5010 } | 4942 } |
| 5011 | 4943 |
| 5012 | 4944 |
| 5013 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4945 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5014 const QRegister value = locs()->in(0).fpu_reg(); | 4946 const QRegister value = locs()->in(0).fpu_reg(); |
| 5015 | 4947 |
| 5016 const DRegister dvalue0 = EvenDRegisterOf(value); | 4948 const DRegister dvalue0 = EvenDRegisterOf(value); |
| 5017 const DRegister dvalue1 = OddDRegisterOf(value); | 4949 const DRegister dvalue1 = OddDRegisterOf(value); |
| 5018 | 4950 |
| 5019 const QRegister result = locs()->out(0).fpu_reg(); | 4951 const QRegister result = locs()->out(0).fpu_reg(); |
| 5020 | 4952 |
| 5021 const DRegister dresult0 = EvenDRegisterOf(result); | 4953 const DRegister dresult0 = EvenDRegisterOf(result); |
| 5022 | 4954 |
| 5023 switch (op_kind()) { | 4955 switch (op_kind()) { |
| 5024 case MethodRecognizer::kFloat64x2GetX: | 4956 case MethodRecognizer::kFloat64x2GetX: |
| 5025 __ vmovd(dresult0, dvalue0); | 4957 __ vmovd(dresult0, dvalue0); |
| 5026 break; | 4958 break; |
| 5027 case MethodRecognizer::kFloat64x2GetY: | 4959 case MethodRecognizer::kFloat64x2GetY: |
| 5028 __ vmovd(dresult0, dvalue1); | 4960 __ vmovd(dresult0, dvalue1); |
| 5029 break; | 4961 break; |
| 5030 default: UNREACHABLE(); | 4962 default: |
| 4963 UNREACHABLE(); |
| 5031 } | 4964 } |
| 5032 } | 4965 } |
| 5033 | 4966 |
| 5034 | 4967 |
| 5035 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 4968 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |
| 5036 bool opt) const { | 4969 bool opt) const { |
| 5037 const intptr_t kNumInputs = 0; | 4970 const intptr_t kNumInputs = 0; |
| 5038 const intptr_t kNumTemps = 0; | 4971 const intptr_t kNumTemps = 0; |
| 5039 LocationSummary* summary = new(zone) LocationSummary( | 4972 LocationSummary* summary = new (zone) |
| 5040 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4973 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5041 summary->set_out(0, Location::RequiresFpuRegister()); | 4974 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5042 return summary; | 4975 return summary; |
| 5043 } | 4976 } |
| 5044 | 4977 |
| 5045 | 4978 |
| 5046 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4979 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5047 const QRegister q = locs()->out(0).fpu_reg(); | 4980 const QRegister q = locs()->out(0).fpu_reg(); |
| 5048 __ veorq(q, q, q); | 4981 __ veorq(q, q, q); |
| 5049 } | 4982 } |
| 5050 | 4983 |
| 5051 | 4984 |
| 5052 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 4985 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |
| 5053 bool opt) const { | 4986 bool opt) const { |
| 5054 const intptr_t kNumInputs = 1; | 4987 const intptr_t kNumInputs = 1; |
| 5055 const intptr_t kNumTemps = 0; | 4988 const intptr_t kNumTemps = 0; |
| 5056 LocationSummary* summary = new(zone) LocationSummary( | 4989 LocationSummary* summary = new (zone) |
| 5057 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4990 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5058 summary->set_in(0, Location::RequiresFpuRegister()); | 4991 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5059 summary->set_out(0, Location::RequiresFpuRegister()); | 4992 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5060 return summary; | 4993 return summary; |
| 5061 } | 4994 } |
| 5062 | 4995 |
| 5063 | 4996 |
| 5064 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4997 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5065 const QRegister value = locs()->in(0).fpu_reg(); | 4998 const QRegister value = locs()->in(0).fpu_reg(); |
| 5066 | 4999 |
| 5067 const DRegister dvalue = EvenDRegisterOf(value); | 5000 const DRegister dvalue = EvenDRegisterOf(value); |
| 5068 | 5001 |
| 5069 const QRegister result = locs()->out(0).fpu_reg(); | 5002 const QRegister result = locs()->out(0).fpu_reg(); |
| 5070 | 5003 |
| 5071 const DRegister dresult0 = EvenDRegisterOf(result); | 5004 const DRegister dresult0 = EvenDRegisterOf(result); |
| 5072 const DRegister dresult1 = OddDRegisterOf(result); | 5005 const DRegister dresult1 = OddDRegisterOf(result); |
| 5073 | 5006 |
| 5074 // Splat across all lanes. | 5007 // Splat across all lanes. |
| 5075 __ vmovd(dresult0, dvalue); | 5008 __ vmovd(dresult0, dvalue); |
| 5076 __ vmovd(dresult1, dvalue); | 5009 __ vmovd(dresult1, dvalue); |
| 5077 } | 5010 } |
| 5078 | 5011 |
| 5079 | 5012 |
| 5080 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 5013 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
| 5081 Zone* zone, bool opt) const { | 5014 Zone* zone, |
| 5015 bool opt) const { |
| 5082 const intptr_t kNumInputs = 2; | 5016 const intptr_t kNumInputs = 2; |
| 5083 const intptr_t kNumTemps = 0; | 5017 const intptr_t kNumTemps = 0; |
| 5084 LocationSummary* summary = new(zone) LocationSummary( | 5018 LocationSummary* summary = new (zone) |
| 5085 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5019 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5086 summary->set_in(0, Location::RequiresFpuRegister()); | 5020 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5087 summary->set_in(1, Location::RequiresFpuRegister()); | 5021 summary->set_in(1, Location::RequiresFpuRegister()); |
| 5088 summary->set_out(0, Location::RequiresFpuRegister()); | 5022 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5089 return summary; | 5023 return summary; |
| 5090 } | 5024 } |
| 5091 | 5025 |
| 5092 | 5026 |
| 5093 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5027 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5094 const QRegister q0 = locs()->in(0).fpu_reg(); | 5028 const QRegister q0 = locs()->in(0).fpu_reg(); |
| 5095 const QRegister q1 = locs()->in(1).fpu_reg(); | 5029 const QRegister q1 = locs()->in(1).fpu_reg(); |
| 5096 const QRegister r = locs()->out(0).fpu_reg(); | 5030 const QRegister r = locs()->out(0).fpu_reg(); |
| 5097 | 5031 |
| 5098 const DRegister d0 = EvenDRegisterOf(q0); | 5032 const DRegister d0 = EvenDRegisterOf(q0); |
| 5099 const DRegister d1 = EvenDRegisterOf(q1); | 5033 const DRegister d1 = EvenDRegisterOf(q1); |
| 5100 | 5034 |
| 5101 const DRegister dr0 = EvenDRegisterOf(r); | 5035 const DRegister dr0 = EvenDRegisterOf(r); |
| 5102 const DRegister dr1 = OddDRegisterOf(r); | 5036 const DRegister dr1 = OddDRegisterOf(r); |
| 5103 | 5037 |
| 5104 __ vmovd(dr0, d0); | 5038 __ vmovd(dr0, d0); |
| 5105 __ vmovd(dr1, d1); | 5039 __ vmovd(dr1, d1); |
| 5106 } | 5040 } |
| 5107 | 5041 |
| 5108 | 5042 |
| 5109 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 5043 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
| 5110 Zone* zone, bool opt) const { | 5044 Zone* zone, |
| 5045 bool opt) const { |
| 5111 const intptr_t kNumInputs = 1; | 5046 const intptr_t kNumInputs = 1; |
| 5112 const intptr_t kNumTemps = 0; | 5047 const intptr_t kNumTemps = 0; |
| 5113 LocationSummary* summary = new(zone) LocationSummary( | 5048 LocationSummary* summary = new (zone) |
| 5114 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5049 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5115 summary->set_in(0, Location::RequiresFpuRegister()); | 5050 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5116 // Low (< 7) Q registers are needed for the vcvtsd instruction. | 5051 // Low (< 7) Q registers are needed for the vcvtsd instruction. |
| 5117 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 5052 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
| 5118 return summary; | 5053 return summary; |
| 5119 } | 5054 } |
| 5120 | 5055 |
| 5121 | 5056 |
| 5122 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5057 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5123 const QRegister q = locs()->in(0).fpu_reg(); | 5058 const QRegister q = locs()->in(0).fpu_reg(); |
| 5124 const QRegister r = locs()->out(0).fpu_reg(); | 5059 const QRegister r = locs()->out(0).fpu_reg(); |
| 5125 | 5060 |
| 5126 const DRegister dq0 = EvenDRegisterOf(q); | 5061 const DRegister dq0 = EvenDRegisterOf(q); |
| 5127 const DRegister dq1 = OddDRegisterOf(q); | 5062 const DRegister dq1 = OddDRegisterOf(q); |
| 5128 | 5063 |
| 5129 const DRegister dr0 = EvenDRegisterOf(r); | 5064 const DRegister dr0 = EvenDRegisterOf(r); |
| 5130 | 5065 |
| 5131 // Zero register. | 5066 // Zero register. |
| 5132 __ veorq(r, r, r); | 5067 __ veorq(r, r, r); |
| 5133 // Set X lane. | 5068 // Set X lane. |
| 5134 __ vcvtsd(EvenSRegisterOf(dr0), dq0); | 5069 __ vcvtsd(EvenSRegisterOf(dr0), dq0); |
| 5135 // Set Y lane. | 5070 // Set Y lane. |
| 5136 __ vcvtsd(OddSRegisterOf(dr0), dq1); | 5071 __ vcvtsd(OddSRegisterOf(dr0), dq1); |
| 5137 } | 5072 } |
| 5138 | 5073 |
| 5139 | 5074 |
| 5140 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 5075 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
| 5141 Zone* zone, bool opt) const { | 5076 Zone* zone, |
| 5077 bool opt) const { |
| 5142 const intptr_t kNumInputs = 1; | 5078 const intptr_t kNumInputs = 1; |
| 5143 const intptr_t kNumTemps = 0; | 5079 const intptr_t kNumTemps = 0; |
| 5144 LocationSummary* summary = new(zone) LocationSummary( | 5080 LocationSummary* summary = new (zone) |
| 5145 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5081 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5146 summary->set_in(0, Location::RequiresFpuRegister()); | 5082 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5147 // Low (< 7) Q registers are needed for the vcvtsd instruction. | 5083 // Low (< 7) Q registers are needed for the vcvtsd instruction. |
| 5148 summary->set_out(0, Location::FpuRegisterLocation(Q6)); | 5084 summary->set_out(0, Location::FpuRegisterLocation(Q6)); |
| 5149 return summary; | 5085 return summary; |
| 5150 } | 5086 } |
| 5151 | 5087 |
| 5152 | 5088 |
| 5153 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5089 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5154 const QRegister q = locs()->in(0).fpu_reg(); | 5090 const QRegister q = locs()->in(0).fpu_reg(); |
| 5155 const QRegister r = locs()->out(0).fpu_reg(); | 5091 const QRegister r = locs()->out(0).fpu_reg(); |
| 5156 | 5092 |
| 5157 const DRegister dq0 = EvenDRegisterOf(q); | 5093 const DRegister dq0 = EvenDRegisterOf(q); |
| 5158 | 5094 |
| 5159 const DRegister dr0 = EvenDRegisterOf(r); | 5095 const DRegister dr0 = EvenDRegisterOf(r); |
| 5160 const DRegister dr1 = OddDRegisterOf(r); | 5096 const DRegister dr1 = OddDRegisterOf(r); |
| 5161 | 5097 |
| 5162 // Set X. | 5098 // Set X. |
| 5163 __ vcvtds(dr0, EvenSRegisterOf(dq0)); | 5099 __ vcvtds(dr0, EvenSRegisterOf(dq0)); |
| 5164 // Set Y. | 5100 // Set Y. |
| 5165 __ vcvtds(dr1, OddSRegisterOf(dq0)); | 5101 __ vcvtds(dr1, OddSRegisterOf(dq0)); |
| 5166 } | 5102 } |
| 5167 | 5103 |
| 5168 | 5104 |
| 5169 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, | 5105 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, |
| 5170 bool opt) const { | 5106 bool opt) const { |
| 5171 const intptr_t kNumInputs = 1; | 5107 const intptr_t kNumInputs = 1; |
| 5172 const intptr_t kNumTemps = 0; | 5108 const intptr_t kNumTemps = 0; |
| 5173 LocationSummary* summary = new(zone) LocationSummary( | 5109 LocationSummary* summary = new (zone) |
| 5174 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5110 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5175 | 5111 |
| 5176 if (representation() == kTagged) { | 5112 if (representation() == kTagged) { |
| 5177 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 5113 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |
| 5178 // Grabbing the S components means we need a low (< 7) Q. | 5114 // Grabbing the S components means we need a low (< 7) Q. |
| 5179 summary->set_in(0, Location::FpuRegisterLocation(Q6)); | 5115 summary->set_in(0, Location::FpuRegisterLocation(Q6)); |
| 5180 summary->set_out(0, Location::RequiresRegister()); | 5116 summary->set_out(0, Location::RequiresRegister()); |
| 5181 } else { | 5117 } else { |
| 5182 summary->set_in(0, Location::RequiresFpuRegister()); | 5118 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5183 summary->set_out(0, Location::RequiresFpuRegister()); | 5119 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5184 } | 5120 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5220 __ vnegd(dresult1, dvalue1); | 5156 __ vnegd(dresult1, dvalue1); |
| 5221 break; | 5157 break; |
| 5222 case MethodRecognizer::kFloat64x2Abs: | 5158 case MethodRecognizer::kFloat64x2Abs: |
| 5223 __ vabsd(dresult0, dvalue0); | 5159 __ vabsd(dresult0, dvalue0); |
| 5224 __ vabsd(dresult1, dvalue1); | 5160 __ vabsd(dresult1, dvalue1); |
| 5225 break; | 5161 break; |
| 5226 case MethodRecognizer::kFloat64x2Sqrt: | 5162 case MethodRecognizer::kFloat64x2Sqrt: |
| 5227 __ vsqrtd(dresult0, dvalue0); | 5163 __ vsqrtd(dresult0, dvalue0); |
| 5228 __ vsqrtd(dresult1, dvalue1); | 5164 __ vsqrtd(dresult1, dvalue1); |
| 5229 break; | 5165 break; |
| 5230 default: UNREACHABLE(); | 5166 default: |
| 5167 UNREACHABLE(); |
| 5231 } | 5168 } |
| 5232 } | 5169 } |
| 5233 | 5170 |
| 5234 | 5171 |
| 5235 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, | 5172 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, |
| 5236 bool opt) const { | 5173 bool opt) const { |
| 5237 const intptr_t kNumInputs = 2; | 5174 const intptr_t kNumInputs = 2; |
| 5238 const intptr_t kNumTemps = 0; | 5175 const intptr_t kNumTemps = 0; |
| 5239 LocationSummary* summary = new(zone) LocationSummary( | 5176 LocationSummary* summary = new (zone) |
| 5240 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5177 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5241 summary->set_in(0, Location::RequiresFpuRegister()); | 5178 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5242 summary->set_in(1, Location::RequiresFpuRegister()); | 5179 summary->set_in(1, Location::RequiresFpuRegister()); |
| 5243 summary->set_out(0, Location::SameAsFirstInput()); | 5180 summary->set_out(0, Location::SameAsFirstInput()); |
| 5244 return summary; | 5181 return summary; |
| 5245 } | 5182 } |
| 5246 | 5183 |
| 5247 | 5184 |
| 5248 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5185 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5249 const QRegister left = locs()->in(0).fpu_reg(); | 5186 const QRegister left = locs()->in(0).fpu_reg(); |
| 5250 const DRegister left0 = EvenDRegisterOf(left); | 5187 const DRegister left0 = EvenDRegisterOf(left); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5293 __ Bind(&g0); | 5230 __ Bind(&g0); |
| 5294 // Y lane. | 5231 // Y lane. |
| 5295 Label g1; | 5232 Label g1; |
| 5296 __ vcmpd(left1, right1); | 5233 __ vcmpd(left1, right1); |
| 5297 __ vmstat(); | 5234 __ vmstat(); |
| 5298 __ b(&g1, GT); | 5235 __ b(&g1, GT); |
| 5299 __ vmovd(left1, right1); | 5236 __ vmovd(left1, right1); |
| 5300 __ Bind(&g1); | 5237 __ Bind(&g1); |
| 5301 break; | 5238 break; |
| 5302 } | 5239 } |
| 5303 default: UNREACHABLE(); | 5240 default: |
| 5241 UNREACHABLE(); |
| 5304 } | 5242 } |
| 5305 } | 5243 } |
| 5306 | 5244 |
| 5307 | 5245 |
| 5308 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary( | 5246 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, |
| 5309 Zone* zone, bool opt) const { | 5247 bool opt) const { |
| 5310 const intptr_t kNumInputs = 4; | 5248 const intptr_t kNumInputs = 4; |
| 5311 const intptr_t kNumTemps = 0; | 5249 const intptr_t kNumTemps = 0; |
| 5312 LocationSummary* summary = new(zone) LocationSummary( | 5250 LocationSummary* summary = new (zone) |
| 5313 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5251 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5314 summary->set_in(0, Location::RequiresRegister()); | 5252 summary->set_in(0, Location::RequiresRegister()); |
| 5315 summary->set_in(1, Location::RequiresRegister()); | 5253 summary->set_in(1, Location::RequiresRegister()); |
| 5316 summary->set_in(2, Location::RequiresRegister()); | 5254 summary->set_in(2, Location::RequiresRegister()); |
| 5317 summary->set_in(3, Location::RequiresRegister()); | 5255 summary->set_in(3, Location::RequiresRegister()); |
| 5318 summary->set_out(0, Location::RequiresRegister()); | 5256 summary->set_out(0, Location::RequiresRegister()); |
| 5319 return summary; | 5257 return summary; |
| 5320 } | 5258 } |
| 5321 | 5259 |
| 5322 | 5260 |
| 5323 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5261 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5324 const Register v0 = locs()->in(0).reg(); | 5262 const Register v0 = locs()->in(0).reg(); |
| 5325 const Register v1 = locs()->in(1).reg(); | 5263 const Register v1 = locs()->in(1).reg(); |
| 5326 const Register v2 = locs()->in(2).reg(); | 5264 const Register v2 = locs()->in(2).reg(); |
| 5327 const Register v3 = locs()->in(3).reg(); | 5265 const Register v3 = locs()->in(3).reg(); |
| 5328 const QRegister result = locs()->out(0).fpu_reg(); | 5266 const QRegister result = locs()->out(0).fpu_reg(); |
| 5329 const DRegister dresult0 = EvenDRegisterOf(result); | 5267 const DRegister dresult0 = EvenDRegisterOf(result); |
| 5330 const DRegister dresult1 = OddDRegisterOf(result); | 5268 const DRegister dresult1 = OddDRegisterOf(result); |
| 5331 __ veorq(result, result, result); | 5269 __ veorq(result, result, result); |
| 5332 __ vmovdrr(dresult0, v0, v1); | 5270 __ vmovdrr(dresult0, v0, v1); |
| 5333 __ vmovdrr(dresult1, v2, v3); | 5271 __ vmovdrr(dresult1, v2, v3); |
| 5334 } | 5272 } |
| 5335 | 5273 |
| 5336 | 5274 |
| 5337 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 5275 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
| 5338 Zone* zone, bool opt) const { | 5276 Zone* zone, |
| 5277 bool opt) const { |
| 5339 const intptr_t kNumInputs = 4; | 5278 const intptr_t kNumInputs = 4; |
| 5340 const intptr_t kNumTemps = 1; | 5279 const intptr_t kNumTemps = 1; |
| 5341 LocationSummary* summary = new(zone) LocationSummary( | 5280 LocationSummary* summary = new (zone) |
| 5342 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5281 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5343 summary->set_in(0, Location::RequiresRegister()); | 5282 summary->set_in(0, Location::RequiresRegister()); |
| 5344 summary->set_in(1, Location::RequiresRegister()); | 5283 summary->set_in(1, Location::RequiresRegister()); |
| 5345 summary->set_in(2, Location::RequiresRegister()); | 5284 summary->set_in(2, Location::RequiresRegister()); |
| 5346 summary->set_in(3, Location::RequiresRegister()); | 5285 summary->set_in(3, Location::RequiresRegister()); |
| 5347 summary->set_temp(0, Location::RequiresRegister()); | 5286 summary->set_temp(0, Location::RequiresRegister()); |
| 5348 summary->set_out(0, Location::RequiresRegister()); | 5287 summary->set_out(0, Location::RequiresRegister()); |
| 5349 return summary; | 5288 return summary; |
| 5350 } | 5289 } |
| 5351 | 5290 |
| 5352 | 5291 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 5375 | 5314 |
| 5376 __ cmp(v3, Operand(IP)); | 5315 __ cmp(v3, Operand(IP)); |
| 5377 __ vmovdr(dresult1, 1, temp, EQ); | 5316 __ vmovdr(dresult1, 1, temp, EQ); |
| 5378 } | 5317 } |
| 5379 | 5318 |
| 5380 | 5319 |
| 5381 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, | 5320 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, |
| 5382 bool opt) const { | 5321 bool opt) const { |
| 5383 const intptr_t kNumInputs = 1; | 5322 const intptr_t kNumInputs = 1; |
| 5384 const intptr_t kNumTemps = 0; | 5323 const intptr_t kNumTemps = 0; |
| 5385 LocationSummary* summary = new(zone) LocationSummary( | 5324 LocationSummary* summary = new (zone) |
| 5386 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5325 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5387 // Low (< 7) Q registers are needed for the vmovrs instruction. | 5326 // Low (< 7) Q registers are needed for the vmovrs instruction. |
| 5388 summary->set_in(0, Location::FpuRegisterLocation(Q6)); | 5327 summary->set_in(0, Location::FpuRegisterLocation(Q6)); |
| 5389 summary->set_out(0, Location::RequiresRegister()); | 5328 summary->set_out(0, Location::RequiresRegister()); |
| 5390 return summary; | 5329 return summary; |
| 5391 } | 5330 } |
| 5392 | 5331 |
| 5393 | 5332 |
| 5394 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5333 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5395 const QRegister value = locs()->in(0).fpu_reg(); | 5334 const QRegister value = locs()->in(0).fpu_reg(); |
| 5396 const Register result = locs()->out(0).reg(); | 5335 const Register result = locs()->out(0).reg(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5408 break; | 5347 break; |
| 5409 case MethodRecognizer::kInt32x4GetFlagY: | 5348 case MethodRecognizer::kInt32x4GetFlagY: |
| 5410 __ vmovrs(result, svalue1); | 5349 __ vmovrs(result, svalue1); |
| 5411 break; | 5350 break; |
| 5412 case MethodRecognizer::kInt32x4GetFlagZ: | 5351 case MethodRecognizer::kInt32x4GetFlagZ: |
| 5413 __ vmovrs(result, svalue2); | 5352 __ vmovrs(result, svalue2); |
| 5414 break; | 5353 break; |
| 5415 case MethodRecognizer::kInt32x4GetFlagW: | 5354 case MethodRecognizer::kInt32x4GetFlagW: |
| 5416 __ vmovrs(result, svalue3); | 5355 __ vmovrs(result, svalue3); |
| 5417 break; | 5356 break; |
| 5418 default: UNREACHABLE(); | 5357 default: |
| 5358 UNREACHABLE(); |
| 5419 } | 5359 } |
| 5420 | 5360 |
| 5421 __ tst(result, Operand(result)); | 5361 __ tst(result, Operand(result)); |
| 5422 __ LoadObject(result, Bool::True(), NE); | 5362 __ LoadObject(result, Bool::True(), NE); |
| 5423 __ LoadObject(result, Bool::False(), EQ); | 5363 __ LoadObject(result, Bool::False(), EQ); |
| 5424 } | 5364 } |
| 5425 | 5365 |
| 5426 | 5366 |
| 5427 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, | 5367 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, |
| 5428 bool opt) const { | 5368 bool opt) const { |
| 5429 const intptr_t kNumInputs = 3; | 5369 const intptr_t kNumInputs = 3; |
| 5430 const intptr_t kNumTemps = 1; | 5370 const intptr_t kNumTemps = 1; |
| 5431 LocationSummary* summary = new(zone) LocationSummary( | 5371 LocationSummary* summary = new (zone) |
| 5432 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5372 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5433 summary->set_in(0, Location::RequiresFpuRegister()); | 5373 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5434 summary->set_in(1, Location::RequiresFpuRegister()); | 5374 summary->set_in(1, Location::RequiresFpuRegister()); |
| 5435 summary->set_in(2, Location::RequiresFpuRegister()); | 5375 summary->set_in(2, Location::RequiresFpuRegister()); |
| 5436 summary->set_temp(0, Location::RequiresFpuRegister()); | 5376 summary->set_temp(0, Location::RequiresFpuRegister()); |
| 5437 summary->set_out(0, Location::RequiresFpuRegister()); | 5377 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5438 return summary; | 5378 return summary; |
| 5439 } | 5379 } |
| 5440 | 5380 |
| 5441 | 5381 |
| 5442 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5382 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5456 __ vandq(temp, temp, falseValue); | 5396 __ vandq(temp, temp, falseValue); |
| 5457 // out = mask | temp. | 5397 // out = mask | temp. |
| 5458 __ vorrq(out, mask, temp); | 5398 __ vorrq(out, mask, temp); |
| 5459 } | 5399 } |
| 5460 | 5400 |
| 5461 | 5401 |
| 5462 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, | 5402 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, |
| 5463 bool opt) const { | 5403 bool opt) const { |
| 5464 const intptr_t kNumInputs = 2; | 5404 const intptr_t kNumInputs = 2; |
| 5465 const intptr_t kNumTemps = 0; | 5405 const intptr_t kNumTemps = 0; |
| 5466 LocationSummary* summary = new(zone) LocationSummary( | 5406 LocationSummary* summary = new (zone) |
| 5467 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5407 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5468 summary->set_in(0, Location::RequiresFpuRegister()); | 5408 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5469 summary->set_in(1, Location::RequiresRegister()); | 5409 summary->set_in(1, Location::RequiresRegister()); |
| 5470 summary->set_out(0, Location::RequiresFpuRegister()); | 5410 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5471 return summary; | 5411 return summary; |
| 5472 } | 5412 } |
| 5473 | 5413 |
| 5474 | 5414 |
| 5475 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5415 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5476 const QRegister mask = locs()->in(0).fpu_reg(); | 5416 const QRegister mask = locs()->in(0).fpu_reg(); |
| 5477 const Register flag = locs()->in(1).reg(); | 5417 const Register flag = locs()->in(1).reg(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5493 break; | 5433 break; |
| 5494 case MethodRecognizer::kInt32x4WithFlagY: | 5434 case MethodRecognizer::kInt32x4WithFlagY: |
| 5495 __ vmovdr(dresult0, 1, TMP); | 5435 __ vmovdr(dresult0, 1, TMP); |
| 5496 break; | 5436 break; |
| 5497 case MethodRecognizer::kInt32x4WithFlagZ: | 5437 case MethodRecognizer::kInt32x4WithFlagZ: |
| 5498 __ vmovdr(dresult1, 0, TMP); | 5438 __ vmovdr(dresult1, 0, TMP); |
| 5499 break; | 5439 break; |
| 5500 case MethodRecognizer::kInt32x4WithFlagW: | 5440 case MethodRecognizer::kInt32x4WithFlagW: |
| 5501 __ vmovdr(dresult1, 1, TMP); | 5441 __ vmovdr(dresult1, 1, TMP); |
| 5502 break; | 5442 break; |
| 5503 default: UNREACHABLE(); | 5443 default: |
| 5444 UNREACHABLE(); |
| 5504 } | 5445 } |
| 5505 } | 5446 } |
| 5506 | 5447 |
| 5507 | 5448 |
| 5508 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, | 5449 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, |
| 5509 bool opt) const { | 5450 bool opt) const { |
| 5510 const intptr_t kNumInputs = 1; | 5451 const intptr_t kNumInputs = 1; |
| 5511 const intptr_t kNumTemps = 0; | 5452 const intptr_t kNumTemps = 0; |
| 5512 LocationSummary* summary = new(zone) LocationSummary( | 5453 LocationSummary* summary = new (zone) |
| 5513 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5454 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5514 summary->set_in(0, Location::RequiresFpuRegister()); | 5455 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5515 summary->set_out(0, Location::RequiresFpuRegister()); | 5456 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5516 return summary; | 5457 return summary; |
| 5517 } | 5458 } |
| 5518 | 5459 |
| 5519 | 5460 |
| 5520 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5461 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5521 const QRegister value = locs()->in(0).fpu_reg(); | 5462 const QRegister value = locs()->in(0).fpu_reg(); |
| 5522 const QRegister result = locs()->out(0).fpu_reg(); | 5463 const QRegister result = locs()->out(0).fpu_reg(); |
| 5523 | 5464 |
| 5524 if (value != result) { | 5465 if (value != result) { |
| 5525 __ vmovq(result, value); | 5466 __ vmovq(result, value); |
| 5526 } | 5467 } |
| 5527 } | 5468 } |
| 5528 | 5469 |
| 5529 | 5470 |
| 5530 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, | 5471 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 5531 bool opt) const { | 5472 bool opt) const { |
| 5532 const intptr_t kNumInputs = 2; | 5473 const intptr_t kNumInputs = 2; |
| 5533 const intptr_t kNumTemps = 0; | 5474 const intptr_t kNumTemps = 0; |
| 5534 LocationSummary* summary = new(zone) LocationSummary( | 5475 LocationSummary* summary = new (zone) |
| 5535 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5476 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5536 summary->set_in(0, Location::RequiresFpuRegister()); | 5477 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5537 summary->set_in(1, Location::RequiresFpuRegister()); | 5478 summary->set_in(1, Location::RequiresFpuRegister()); |
| 5538 summary->set_out(0, Location::RequiresFpuRegister()); | 5479 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5539 return summary; | 5480 return summary; |
| 5540 } | 5481 } |
| 5541 | 5482 |
| 5542 | 5483 |
| 5543 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5484 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5544 const QRegister left = locs()->in(0).fpu_reg(); | 5485 const QRegister left = locs()->in(0).fpu_reg(); |
| 5545 const QRegister right = locs()->in(1).fpu_reg(); | 5486 const QRegister right = locs()->in(1).fpu_reg(); |
| 5546 const QRegister result = locs()->out(0).fpu_reg(); | 5487 const QRegister result = locs()->out(0).fpu_reg(); |
| 5547 switch (op_kind()) { | 5488 switch (op_kind()) { |
| 5548 case Token::kBIT_AND: __ vandq(result, left, right); break; | 5489 case Token::kBIT_AND: |
| 5549 case Token::kBIT_OR: __ vorrq(result, left, right); break; | 5490 __ vandq(result, left, right); |
| 5550 case Token::kBIT_XOR: __ veorq(result, left, right); break; | 5491 break; |
| 5551 case Token::kADD: __ vaddqi(kWord, result, left, right); break; | 5492 case Token::kBIT_OR: |
| 5552 case Token::kSUB: __ vsubqi(kWord, result, left, right); break; | 5493 __ vorrq(result, left, right); |
| 5553 default: UNREACHABLE(); | 5494 break; |
| 5495 case Token::kBIT_XOR: |
| 5496 __ veorq(result, left, right); |
| 5497 break; |
| 5498 case Token::kADD: |
| 5499 __ vaddqi(kWord, result, left, right); |
| 5500 break; |
| 5501 case Token::kSUB: |
| 5502 __ vsubqi(kWord, result, left, right); |
| 5503 break; |
| 5504 default: |
| 5505 UNREACHABLE(); |
| 5554 } | 5506 } |
| 5555 } | 5507 } |
| 5556 | 5508 |
| 5557 | 5509 |
| 5558 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 5510 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |
| 5559 bool opt) const { | 5511 bool opt) const { |
| 5560 ASSERT((kind() == MathUnaryInstr::kSqrt) || | 5512 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
| 5561 (kind() == MathUnaryInstr::kDoubleSquare)); | 5513 (kind() == MathUnaryInstr::kDoubleSquare)); |
| 5562 const intptr_t kNumInputs = 1; | 5514 const intptr_t kNumInputs = 1; |
| 5563 const intptr_t kNumTemps = 0; | 5515 const intptr_t kNumTemps = 0; |
| 5564 LocationSummary* summary = new(zone) LocationSummary( | 5516 LocationSummary* summary = new (zone) |
| 5565 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5517 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5566 summary->set_in(0, Location::RequiresFpuRegister()); | 5518 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5567 summary->set_out(0, Location::RequiresFpuRegister()); | 5519 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5568 return summary; | 5520 return summary; |
| 5569 } | 5521 } |
| 5570 | 5522 |
| 5571 | 5523 |
| 5572 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5524 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5573 if (kind() == MathUnaryInstr::kSqrt) { | 5525 if (kind() == MathUnaryInstr::kSqrt) { |
| 5574 const DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 5526 const DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
| 5575 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5527 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
| 5576 __ vsqrtd(result, val); | 5528 __ vsqrtd(result, val); |
| 5577 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 5529 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
| 5578 const DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 5530 const DRegister val = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
| 5579 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5531 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
| 5580 __ vmuld(result, val, val); | 5532 __ vmuld(result, val, val); |
| 5581 } else { | 5533 } else { |
| 5582 UNREACHABLE(); | 5534 UNREACHABLE(); |
| 5583 } | 5535 } |
| 5584 } | 5536 } |
| 5585 | 5537 |
| 5586 | 5538 |
| 5587 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 5539 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |
| 5588 Zone* zone, bool opt) const { | 5540 Zone* zone, |
| 5541 bool opt) const { |
| 5589 const intptr_t kNumTemps = 0; | 5542 const intptr_t kNumTemps = 0; |
| 5590 LocationSummary* summary = new(zone) LocationSummary( | 5543 LocationSummary* summary = new (zone) |
| 5591 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5544 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 5592 summary->set_in(0, Location::RegisterLocation(R0)); | 5545 summary->set_in(0, Location::RegisterLocation(R0)); |
| 5593 summary->set_in(1, Location::RegisterLocation(R1)); | 5546 summary->set_in(1, Location::RegisterLocation(R1)); |
| 5594 summary->set_in(2, Location::RegisterLocation(R2)); | 5547 summary->set_in(2, Location::RegisterLocation(R2)); |
| 5595 summary->set_in(3, Location::RegisterLocation(R3)); | 5548 summary->set_in(3, Location::RegisterLocation(R3)); |
| 5596 summary->set_out(0, Location::RegisterLocation(R0)); | 5549 summary->set_out(0, Location::RegisterLocation(R0)); |
| 5597 return summary; | 5550 return summary; |
| 5598 } | 5551 } |
| 5599 | 5552 |
| 5600 | 5553 |
| 5601 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 5554 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |
| 5602 FlowGraphCompiler* compiler) { | 5555 FlowGraphCompiler* compiler) { |
| 5603 | |
| 5604 // Call the function. | 5556 // Call the function. |
| 5605 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 5557 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |
| 5606 } | 5558 } |
| 5607 | 5559 |
| 5608 | 5560 |
| 5609 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 5561 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |
| 5610 bool opt) const { | 5562 bool opt) const { |
| 5611 if (result_cid() == kDoubleCid) { | 5563 if (result_cid() == kDoubleCid) { |
| 5612 const intptr_t kNumInputs = 2; | 5564 const intptr_t kNumInputs = 2; |
| 5613 const intptr_t kNumTemps = 1; | 5565 const intptr_t kNumTemps = 1; |
| 5614 LocationSummary* summary = new(zone) LocationSummary( | 5566 LocationSummary* summary = new (zone) |
| 5615 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5567 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5616 summary->set_in(0, Location::RequiresFpuRegister()); | 5568 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5617 summary->set_in(1, Location::RequiresFpuRegister()); | 5569 summary->set_in(1, Location::RequiresFpuRegister()); |
| 5618 // Reuse the left register so that code can be made shorter. | 5570 // Reuse the left register so that code can be made shorter. |
| 5619 summary->set_out(0, Location::SameAsFirstInput()); | 5571 summary->set_out(0, Location::SameAsFirstInput()); |
| 5620 summary->set_temp(0, Location::RequiresRegister()); | 5572 summary->set_temp(0, Location::RequiresRegister()); |
| 5621 return summary; | 5573 return summary; |
| 5622 } | 5574 } |
| 5623 ASSERT(result_cid() == kSmiCid); | 5575 ASSERT(result_cid() == kSmiCid); |
| 5624 const intptr_t kNumInputs = 2; | 5576 const intptr_t kNumInputs = 2; |
| 5625 const intptr_t kNumTemps = 0; | 5577 const intptr_t kNumTemps = 0; |
| 5626 LocationSummary* summary = new(zone) LocationSummary( | 5578 LocationSummary* summary = new (zone) |
| 5627 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5579 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5628 summary->set_in(0, Location::RequiresRegister()); | 5580 summary->set_in(0, Location::RequiresRegister()); |
| 5629 summary->set_in(1, Location::RequiresRegister()); | 5581 summary->set_in(1, Location::RequiresRegister()); |
| 5630 // Reuse the left register so that code can be made shorter. | 5582 // Reuse the left register so that code can be made shorter. |
| 5631 summary->set_out(0, Location::SameAsFirstInput()); | 5583 summary->set_out(0, Location::SameAsFirstInput()); |
| 5632 return summary; | 5584 return summary; |
| 5633 } | 5585 } |
| 5634 | 5586 |
| 5635 | 5587 |
| 5636 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5588 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5637 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 5589 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5689 } else { | 5641 } else { |
| 5690 __ mov(result, Operand(right), LT); | 5642 __ mov(result, Operand(right), LT); |
| 5691 } | 5643 } |
| 5692 } | 5644 } |
| 5693 | 5645 |
| 5694 | 5646 |
| 5695 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 5647 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 5696 bool opt) const { | 5648 bool opt) const { |
| 5697 const intptr_t kNumInputs = 1; | 5649 const intptr_t kNumInputs = 1; |
| 5698 const intptr_t kNumTemps = 0; | 5650 const intptr_t kNumTemps = 0; |
| 5699 LocationSummary* summary = new(zone) LocationSummary( | 5651 LocationSummary* summary = new (zone) |
| 5700 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5652 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5701 summary->set_in(0, Location::RequiresRegister()); | 5653 summary->set_in(0, Location::RequiresRegister()); |
| 5702 // We make use of 3-operand instructions by not requiring result register | 5654 // We make use of 3-operand instructions by not requiring result register |
| 5703 // to be identical to first input register as on Intel. | 5655 // to be identical to first input register as on Intel. |
| 5704 summary->set_out(0, Location::RequiresRegister()); | 5656 summary->set_out(0, Location::RequiresRegister()); |
| 5705 return summary; | 5657 return summary; |
| 5706 } | 5658 } |
| 5707 | 5659 |
| 5708 | 5660 |
| 5709 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5661 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5710 const Register value = locs()->in(0).reg(); | 5662 const Register value = locs()->in(0).reg(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5724 default: | 5676 default: |
| 5725 UNREACHABLE(); | 5677 UNREACHABLE(); |
| 5726 } | 5678 } |
| 5727 } | 5679 } |
| 5728 | 5680 |
| 5729 | 5681 |
| 5730 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 5682 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 5731 bool opt) const { | 5683 bool opt) const { |
| 5732 const intptr_t kNumInputs = 1; | 5684 const intptr_t kNumInputs = 1; |
| 5733 const intptr_t kNumTemps = 0; | 5685 const intptr_t kNumTemps = 0; |
| 5734 LocationSummary* summary = new(zone) LocationSummary( | 5686 LocationSummary* summary = new (zone) |
| 5735 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5687 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5736 summary->set_in(0, Location::RequiresFpuRegister()); | 5688 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5737 summary->set_out(0, Location::RequiresFpuRegister()); | 5689 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5738 return summary; | 5690 return summary; |
| 5739 } | 5691 } |
| 5740 | 5692 |
| 5741 | 5693 |
| 5742 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5694 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5743 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5695 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
| 5744 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 5696 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
| 5745 __ vnegd(result, value); | 5697 __ vnegd(result, value); |
| 5746 } | 5698 } |
| 5747 | 5699 |
| 5748 | 5700 |
| 5749 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 5701 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5750 bool opt) const { | 5702 bool opt) const { |
| 5751 const intptr_t kNumInputs = 1; | 5703 const intptr_t kNumInputs = 1; |
| 5752 const intptr_t kNumTemps = 0; | 5704 const intptr_t kNumTemps = 0; |
| 5753 LocationSummary* result = new(zone) LocationSummary( | 5705 LocationSummary* result = new (zone) |
| 5754 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5706 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5755 result->set_in(0, Location::RequiresRegister()); | 5707 result->set_in(0, Location::RequiresRegister()); |
| 5756 result->set_out(0, Location::RequiresFpuRegister()); | 5708 result->set_out(0, Location::RequiresFpuRegister()); |
| 5757 return result; | 5709 return result; |
| 5758 } | 5710 } |
| 5759 | 5711 |
| 5760 | 5712 |
| 5761 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5713 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5762 const Register value = locs()->in(0).reg(); | 5714 const Register value = locs()->in(0).reg(); |
| 5763 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5715 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
| 5764 __ vmovdr(DTMP, 0, value); | 5716 __ vmovdr(DTMP, 0, value); |
| 5765 __ vcvtdi(result, STMP); | 5717 __ vcvtdi(result, STMP); |
| 5766 } | 5718 } |
| 5767 | 5719 |
| 5768 | 5720 |
| 5769 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 5721 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5770 bool opt) const { | 5722 bool opt) const { |
| 5771 const intptr_t kNumInputs = 1; | 5723 const intptr_t kNumInputs = 1; |
| 5772 const intptr_t kNumTemps = 0; | 5724 const intptr_t kNumTemps = 0; |
| 5773 LocationSummary* result = new(zone) LocationSummary( | 5725 LocationSummary* result = new (zone) |
| 5774 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5726 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5775 result->set_in(0, Location::RequiresRegister()); | 5727 result->set_in(0, Location::RequiresRegister()); |
| 5776 result->set_out(0, Location::RequiresFpuRegister()); | 5728 result->set_out(0, Location::RequiresFpuRegister()); |
| 5777 return result; | 5729 return result; |
| 5778 } | 5730 } |
| 5779 | 5731 |
| 5780 | 5732 |
| 5781 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5733 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5782 const Register value = locs()->in(0).reg(); | 5734 const Register value = locs()->in(0).reg(); |
| 5783 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5735 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
| 5784 __ SmiUntag(IP, value); | 5736 __ SmiUntag(IP, value); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5796 | 5748 |
| 5797 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5749 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5798 UNIMPLEMENTED(); | 5750 UNIMPLEMENTED(); |
| 5799 } | 5751 } |
| 5800 | 5752 |
| 5801 | 5753 |
| 5802 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 5754 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |
| 5803 bool opt) const { | 5755 bool opt) const { |
| 5804 const intptr_t kNumInputs = 1; | 5756 const intptr_t kNumInputs = 1; |
| 5805 const intptr_t kNumTemps = 0; | 5757 const intptr_t kNumTemps = 0; |
| 5806 LocationSummary* result = new(zone) LocationSummary( | 5758 LocationSummary* result = new (zone) |
| 5807 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5759 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 5808 result->set_in(0, Location::RegisterLocation(R1)); | 5760 result->set_in(0, Location::RegisterLocation(R1)); |
| 5809 result->set_out(0, Location::RegisterLocation(R0)); | 5761 result->set_out(0, Location::RegisterLocation(R0)); |
| 5810 return result; | 5762 return result; |
| 5811 } | 5763 } |
| 5812 | 5764 |
| 5813 | 5765 |
| 5814 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5766 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5815 const Register result = locs()->out(0).reg(); | 5767 const Register result = locs()->out(0).reg(); |
| 5816 const Register value_obj = locs()->in(0).reg(); | 5768 const Register value_obj = locs()->in(0).reg(); |
| 5817 ASSERT(result == R0); | 5769 ASSERT(result == R0); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 5835 __ b(&done, PL); | 5787 __ b(&done, PL); |
| 5836 | 5788 |
| 5837 __ Bind(&do_call); | 5789 __ Bind(&do_call); |
| 5838 __ Push(value_obj); | 5790 __ Push(value_obj); |
| 5839 ASSERT(instance_call()->HasICData()); | 5791 ASSERT(instance_call()->HasICData()); |
| 5840 const ICData& ic_data = *instance_call()->ic_data(); | 5792 const ICData& ic_data = *instance_call()->ic_data(); |
| 5841 ASSERT((ic_data.NumberOfChecks() == 1)); | 5793 ASSERT((ic_data.NumberOfChecks() == 1)); |
| 5842 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 5794 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
| 5843 | 5795 |
| 5844 const intptr_t kNumberOfArguments = 1; | 5796 const intptr_t kNumberOfArguments = 1; |
| 5845 compiler->GenerateStaticCall(deopt_id(), | 5797 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, |
| 5846 instance_call()->token_pos(), | |
| 5847 target, | |
| 5848 kNumberOfArguments, | 5798 kNumberOfArguments, |
| 5849 Object::null_array(), // No argument names., | 5799 Object::null_array(), // No argument names., |
| 5850 locs(), | 5800 locs(), ICData::Handle()); |
| 5851 ICData::Handle()); | |
| 5852 __ Bind(&done); | 5801 __ Bind(&done); |
| 5853 } | 5802 } |
| 5854 | 5803 |
| 5855 | 5804 |
| 5856 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 5805 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |
| 5857 bool opt) const { | 5806 bool opt) const { |
| 5858 const intptr_t kNumInputs = 1; | 5807 const intptr_t kNumInputs = 1; |
| 5859 const intptr_t kNumTemps = 0; | 5808 const intptr_t kNumTemps = 0; |
| 5860 LocationSummary* result = new(zone) LocationSummary( | 5809 LocationSummary* result = new (zone) |
| 5861 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5810 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5862 result->set_in(0, Location::RequiresFpuRegister()); | 5811 result->set_in(0, Location::RequiresFpuRegister()); |
| 5863 result->set_out(0, Location::RequiresRegister()); | 5812 result->set_out(0, Location::RequiresRegister()); |
| 5864 return result; | 5813 return result; |
| 5865 } | 5814 } |
| 5866 | 5815 |
| 5867 | 5816 |
| 5868 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5817 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5869 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 5818 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
| 5870 const Register result = locs()->out(0).reg(); | 5819 const Register result = locs()->out(0).reg(); |
| 5871 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 5820 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 5893 | 5842 |
| 5894 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5843 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5895 UNIMPLEMENTED(); | 5844 UNIMPLEMENTED(); |
| 5896 } | 5845 } |
| 5897 | 5846 |
| 5898 | 5847 |
| 5899 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 5848 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |
| 5900 bool opt) const { | 5849 bool opt) const { |
| 5901 const intptr_t kNumInputs = 1; | 5850 const intptr_t kNumInputs = 1; |
| 5902 const intptr_t kNumTemps = 0; | 5851 const intptr_t kNumTemps = 0; |
| 5903 LocationSummary* result = new(zone) LocationSummary( | 5852 LocationSummary* result = new (zone) |
| 5904 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5853 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5905 // Low (<= Q7) Q registers are needed for the conversion instructions. | 5854 // Low (<= Q7) Q registers are needed for the conversion instructions. |
| 5906 result->set_in(0, Location::RequiresFpuRegister()); | 5855 result->set_in(0, Location::RequiresFpuRegister()); |
| 5907 result->set_out(0, Location::FpuRegisterLocation(Q7)); | 5856 result->set_out(0, Location::FpuRegisterLocation(Q7)); |
| 5908 return result; | 5857 return result; |
| 5909 } | 5858 } |
| 5910 | 5859 |
| 5911 | 5860 |
| 5912 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5861 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5913 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 5862 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
| 5914 const SRegister result = | 5863 const SRegister result = |
| 5915 EvenSRegisterOf(EvenDRegisterOf(locs()->out(0).fpu_reg())); | 5864 EvenSRegisterOf(EvenDRegisterOf(locs()->out(0).fpu_reg())); |
| 5916 __ vcvtsd(result, value); | 5865 __ vcvtsd(result, value); |
| 5917 } | 5866 } |
| 5918 | 5867 |
| 5919 | 5868 |
| 5920 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 5869 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5921 bool opt) const { | 5870 bool opt) const { |
| 5922 const intptr_t kNumInputs = 1; | 5871 const intptr_t kNumInputs = 1; |
| 5923 const intptr_t kNumTemps = 0; | 5872 const intptr_t kNumTemps = 0; |
| 5924 LocationSummary* result = new(zone) LocationSummary( | 5873 LocationSummary* result = new (zone) |
| 5925 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5874 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5926 // Low (<= Q7) Q registers are needed for the conversion instructions. | 5875 // Low (<= Q7) Q registers are needed for the conversion instructions. |
| 5927 result->set_in(0, Location::FpuRegisterLocation(Q7)); | 5876 result->set_in(0, Location::FpuRegisterLocation(Q7)); |
| 5928 result->set_out(0, Location::RequiresFpuRegister()); | 5877 result->set_out(0, Location::RequiresFpuRegister()); |
| 5929 return result; | 5878 return result; |
| 5930 } | 5879 } |
| 5931 | 5880 |
| 5932 | 5881 |
| 5933 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5882 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5934 const SRegister value = | 5883 const SRegister value = |
| 5935 EvenSRegisterOf(EvenDRegisterOf(locs()->in(0).fpu_reg())); | 5884 EvenSRegisterOf(EvenDRegisterOf(locs()->in(0).fpu_reg())); |
| 5936 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5885 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
| 5937 __ vcvtds(result, value); | 5886 __ vcvtds(result, value); |
| 5938 } | 5887 } |
| 5939 | 5888 |
| 5940 | 5889 |
| 5941 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 5890 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |
| 5942 bool opt) const { | 5891 bool opt) const { |
| 5943 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 5892 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
| 5944 const intptr_t kNumTemps = | 5893 const intptr_t kNumTemps = |
| 5945 (TargetCPUFeatures::hardfp_supported()) ? | 5894 (TargetCPUFeatures::hardfp_supported()) |
| 5946 ((recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0) : 4; | 5895 ? ((recognized_kind() == MethodRecognizer::kMathDoublePow) ? 1 : 0) |
| 5947 LocationSummary* result = new(zone) LocationSummary( | 5896 : 4; |
| 5948 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5897 LocationSummary* result = new (zone) |
| 5898 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 5949 result->set_in(0, Location::FpuRegisterLocation(Q0)); | 5899 result->set_in(0, Location::FpuRegisterLocation(Q0)); |
| 5950 if (InputCount() == 2) { | 5900 if (InputCount() == 2) { |
| 5951 result->set_in(1, Location::FpuRegisterLocation(Q1)); | 5901 result->set_in(1, Location::FpuRegisterLocation(Q1)); |
| 5952 } | 5902 } |
| 5953 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5903 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 5954 result->set_temp(0, Location::RegisterLocation(R2)); | 5904 result->set_temp(0, Location::RegisterLocation(R2)); |
| 5955 if (!TargetCPUFeatures::hardfp_supported()) { | 5905 if (!TargetCPUFeatures::hardfp_supported()) { |
| 5956 result->set_temp(1, Location::RegisterLocation(R0)); | 5906 result->set_temp(1, Location::RegisterLocation(R0)); |
| 5957 result->set_temp(2, Location::RegisterLocation(R1)); | 5907 result->set_temp(2, Location::RegisterLocation(R1)); |
| 5958 result->set_temp(3, Location::RegisterLocation(R3)); | 5908 result->set_temp(3, Location::RegisterLocation(R3)); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5997 const DRegister saved_base = OddDRegisterOf(locs->in(0).fpu_reg()); | 5947 const DRegister saved_base = OddDRegisterOf(locs->in(0).fpu_reg()); |
| 5998 ASSERT((base == result) && (result != saved_base)); | 5948 ASSERT((base == result) && (result != saved_base)); |
| 5999 | 5949 |
| 6000 Label skip_call, try_sqrt, check_base, return_nan; | 5950 Label skip_call, try_sqrt, check_base, return_nan; |
| 6001 __ vmovd(saved_base, base); | 5951 __ vmovd(saved_base, base); |
| 6002 __ LoadDImmediate(result, 1.0, temp); | 5952 __ LoadDImmediate(result, 1.0, temp); |
| 6003 // exponent == 0.0 -> return 1.0; | 5953 // exponent == 0.0 -> return 1.0; |
| 6004 __ vcmpdz(exp); | 5954 __ vcmpdz(exp); |
| 6005 __ vmstat(); | 5955 __ vmstat(); |
| 6006 __ b(&check_base, VS); // NaN -> check base. | 5956 __ b(&check_base, VS); // NaN -> check base. |
| 6007 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. | 5957 __ b(&skip_call, EQ); // exp is 0.0, result is 1.0. |
| 6008 | 5958 |
| 6009 // exponent == 1.0 ? | 5959 // exponent == 1.0 ? |
| 6010 __ vcmpd(exp, result); | 5960 __ vcmpd(exp, result); |
| 6011 __ vmstat(); | 5961 __ vmstat(); |
| 6012 Label return_base; | 5962 Label return_base; |
| 6013 __ b(&return_base, EQ); | 5963 __ b(&return_base, EQ); |
| 6014 | 5964 |
| 6015 // exponent == 2.0 ? | 5965 // exponent == 2.0 ? |
| 6016 __ LoadDImmediate(DTMP, 2.0, temp); | 5966 __ LoadDImmediate(DTMP, 2.0, temp); |
| 6017 __ vcmpd(exp, DTMP); | 5967 __ vcmpd(exp, DTMP); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6127 __ vmovdrr(D1, R2, R3); | 6077 __ vmovdrr(D1, R2, R3); |
| 6128 } | 6078 } |
| 6129 } | 6079 } |
| 6130 | 6080 |
| 6131 | 6081 |
| 6132 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 6082 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |
| 6133 bool opt) const { | 6083 bool opt) const { |
| 6134 // Only use this instruction in optimized code. | 6084 // Only use this instruction in optimized code. |
| 6135 ASSERT(opt); | 6085 ASSERT(opt); |
| 6136 const intptr_t kNumInputs = 1; | 6086 const intptr_t kNumInputs = 1; |
| 6137 LocationSummary* summary = new(zone) LocationSummary( | 6087 LocationSummary* summary = |
| 6138 zone, kNumInputs, 0, LocationSummary::kNoCall); | 6088 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 6139 if (representation() == kUnboxedDouble) { | 6089 if (representation() == kUnboxedDouble) { |
| 6140 if (index() == 0) { | 6090 if (index() == 0) { |
| 6141 summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), | 6091 summary->set_in( |
| 6142 Location::Any())); | 6092 0, Location::Pair(Location::RequiresFpuRegister(), Location::Any())); |
| 6143 } else { | 6093 } else { |
| 6144 ASSERT(index() == 1); | 6094 ASSERT(index() == 1); |
| 6145 summary->set_in(0, Location::Pair(Location::Any(), | 6095 summary->set_in( |
| 6146 Location::RequiresFpuRegister())); | 6096 0, Location::Pair(Location::Any(), Location::RequiresFpuRegister())); |
| 6147 } | 6097 } |
| 6148 summary->set_out(0, Location::RequiresFpuRegister()); | 6098 summary->set_out(0, Location::RequiresFpuRegister()); |
| 6149 } else { | 6099 } else { |
| 6150 ASSERT(representation() == kTagged); | 6100 ASSERT(representation() == kTagged); |
| 6151 if (index() == 0) { | 6101 if (index() == 0) { |
| 6152 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6102 summary->set_in( |
| 6153 Location::Any())); | 6103 0, Location::Pair(Location::RequiresRegister(), Location::Any())); |
| 6154 } else { | 6104 } else { |
| 6155 ASSERT(index() == 1); | 6105 ASSERT(index() == 1); |
| 6156 summary->set_in(0, Location::Pair(Location::Any(), | 6106 summary->set_in( |
| 6157 Location::RequiresRegister())); | 6107 0, Location::Pair(Location::Any(), Location::RequiresRegister())); |
| 6158 } | 6108 } |
| 6159 summary->set_out(0, Location::RequiresRegister()); | 6109 summary->set_out(0, Location::RequiresRegister()); |
| 6160 } | 6110 } |
| 6161 return summary; | 6111 return summary; |
| 6162 } | 6112 } |
| 6163 | 6113 |
| 6164 | 6114 |
| 6165 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6115 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6166 ASSERT(locs()->in(0).IsPairLocation()); | 6116 ASSERT(locs()->in(0).IsPairLocation()); |
| 6167 PairLocation* pair = locs()->in(0).AsPairLocation(); | 6117 PairLocation* pair = locs()->in(0).AsPairLocation(); |
| 6168 Location in_loc = pair->At(index()); | 6118 Location in_loc = pair->At(index()); |
| 6169 if (representation() == kUnboxedDouble) { | 6119 if (representation() == kUnboxedDouble) { |
| 6170 const QRegister out = locs()->out(0).fpu_reg(); | 6120 const QRegister out = locs()->out(0).fpu_reg(); |
| 6171 const QRegister in = in_loc.fpu_reg(); | 6121 const QRegister in = in_loc.fpu_reg(); |
| 6172 __ vmovq(out, in); | 6122 __ vmovq(out, in); |
| 6173 } else { | 6123 } else { |
| 6174 ASSERT(representation() == kTagged); | 6124 ASSERT(representation() == kTagged); |
| 6175 const Register out = locs()->out(0).reg(); | 6125 const Register out = locs()->out(0).reg(); |
| 6176 const Register in = in_loc.reg(); | 6126 const Register in = in_loc.reg(); |
| 6177 __ mov(out, Operand(in)); | 6127 __ mov(out, Operand(in)); |
| 6178 } | 6128 } |
| 6179 } | 6129 } |
| 6180 | 6130 |
| 6181 | 6131 |
| 6182 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, | 6132 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, |
| 6183 bool opt) const { | 6133 bool opt) const { |
| 6184 if (kind() == MergedMathInstr::kTruncDivMod) { | 6134 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 6185 const intptr_t kNumInputs = 2; | 6135 const intptr_t kNumInputs = 2; |
| 6186 const intptr_t kNumTemps = 2; | 6136 const intptr_t kNumTemps = 2; |
| 6187 LocationSummary* summary = new(zone) LocationSummary( | 6137 LocationSummary* summary = new (zone) |
| 6188 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6138 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6189 summary->set_in(0, Location::RequiresRegister()); | 6139 summary->set_in(0, Location::RequiresRegister()); |
| 6190 summary->set_in(1, Location::RequiresRegister()); | 6140 summary->set_in(1, Location::RequiresRegister()); |
| 6191 summary->set_temp(0, Location::RequiresRegister()); | 6141 summary->set_temp(0, Location::RequiresRegister()); |
| 6192 summary->set_temp(1, Location::RequiresFpuRegister()); | 6142 summary->set_temp(1, Location::RequiresFpuRegister()); |
| 6193 // Output is a pair of registers. | 6143 // Output is a pair of registers. |
| 6194 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6144 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 6195 Location::RequiresRegister())); | 6145 Location::RequiresRegister())); |
| 6196 return summary; | 6146 return summary; |
| 6197 } | 6147 } |
| 6198 UNIMPLEMENTED(); | 6148 UNIMPLEMENTED(); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6255 return; | 6205 return; |
| 6256 } | 6206 } |
| 6257 if (kind() == MergedMathInstr::kSinCos) { | 6207 if (kind() == MergedMathInstr::kSinCos) { |
| 6258 UNIMPLEMENTED(); | 6208 UNIMPLEMENTED(); |
| 6259 } | 6209 } |
| 6260 UNIMPLEMENTED(); | 6210 UNIMPLEMENTED(); |
| 6261 } | 6211 } |
| 6262 | 6212 |
| 6263 | 6213 |
| 6264 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 6214 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
| 6265 Zone* zone, bool opt) const { | 6215 Zone* zone, |
| 6216 bool opt) const { |
| 6266 return MakeCallSummary(zone); | 6217 return MakeCallSummary(zone); |
| 6267 } | 6218 } |
| 6268 | 6219 |
| 6269 | 6220 |
| 6270 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, | 6221 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6271 bool opt) const { | |
| 6272 comparison()->InitializeLocationSummary(zone, opt); | 6222 comparison()->InitializeLocationSummary(zone, opt); |
| 6273 // Branches don't produce a result. | 6223 // Branches don't produce a result. |
| 6274 comparison()->locs()->set_out(0, Location::NoLocation()); | 6224 comparison()->locs()->set_out(0, Location::NoLocation()); |
| 6275 return comparison()->locs(); | 6225 return comparison()->locs(); |
| 6276 } | 6226 } |
| 6277 | 6227 |
| 6278 | 6228 |
| 6279 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6229 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6280 comparison()->EmitBranchCode(compiler, this); | 6230 comparison()->EmitBranchCode(compiler, this); |
| 6281 } | 6231 } |
| 6282 | 6232 |
| 6283 | 6233 |
| 6284 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 6234 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
| 6285 bool opt) const { | 6235 bool opt) const { |
| 6286 const intptr_t kNumInputs = 1; | 6236 const intptr_t kNumInputs = 1; |
| 6287 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); | 6237 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); |
| 6288 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 6238 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
| 6289 LocationSummary* summary = new(zone) LocationSummary( | 6239 LocationSummary* summary = new (zone) |
| 6290 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6240 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6291 summary->set_in(0, Location::RequiresRegister()); | 6241 summary->set_in(0, Location::RequiresRegister()); |
| 6292 if (!IsNullCheck()) { | 6242 if (!IsNullCheck()) { |
| 6293 summary->set_temp(0, Location::RequiresRegister()); | 6243 summary->set_temp(0, Location::RequiresRegister()); |
| 6294 if (need_mask_temp) { | 6244 if (need_mask_temp) { |
| 6295 summary->set_temp(1, Location::RequiresRegister()); | 6245 summary->set_temp(1, Location::RequiresRegister()); |
| 6296 } | 6246 } |
| 6297 } | 6247 } |
| 6298 return summary; | 6248 return summary; |
| 6299 } | 6249 } |
| 6300 | 6250 |
| 6301 | 6251 |
| 6302 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6252 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6303 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 6253 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass, |
| 6304 ICData::kDeoptCheckClass, | |
| 6305 licm_hoisted_ ? ICData::kHoisted : 0); | 6254 licm_hoisted_ ? ICData::kHoisted : 0); |
| 6306 if (IsNullCheck()) { | 6255 if (IsNullCheck()) { |
| 6307 __ CompareObject(locs()->in(0).reg(), Object::null_object()); | 6256 __ CompareObject(locs()->in(0).reg(), Object::null_object()); |
| 6308 ASSERT(DeoptIfNull() || DeoptIfNotNull()); | 6257 ASSERT(DeoptIfNull() || DeoptIfNotNull()); |
| 6309 Condition cond = DeoptIfNull() ? EQ : NE; | 6258 Condition cond = DeoptIfNull() ? EQ : NE; |
| 6310 __ b(deopt, cond); | 6259 __ b(deopt, cond); |
| 6311 return; | 6260 return; |
| 6312 } | 6261 } |
| 6313 | 6262 |
| 6314 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 6263 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
| (...skipping 21 matching lines...) Expand all Loading... |
| 6336 // Only need mask if there are missing numbers in the range. | 6285 // Only need mask if there are missing numbers in the range. |
| 6337 ASSERT(cids_.length() > 2); | 6286 ASSERT(cids_.length() > 2); |
| 6338 Register mask_reg = locs()->temp(1).reg(); | 6287 Register mask_reg = locs()->temp(1).reg(); |
| 6339 __ LoadImmediate(mask_reg, 1); | 6288 __ LoadImmediate(mask_reg, 1); |
| 6340 __ Lsl(mask_reg, mask_reg, temp); | 6289 __ Lsl(mask_reg, mask_reg, temp); |
| 6341 __ TestImmediate(mask_reg, mask); | 6290 __ TestImmediate(mask_reg, mask); |
| 6342 __ b(deopt, EQ); | 6291 __ b(deopt, EQ); |
| 6343 } | 6292 } |
| 6344 } else { | 6293 } else { |
| 6345 GrowableArray<CidTarget> sorted_ic_data; | 6294 GrowableArray<CidTarget> sorted_ic_data; |
| 6346 FlowGraphCompiler::SortICDataByCount(unary_checks(), | 6295 FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data, |
| 6347 &sorted_ic_data, | |
| 6348 /* drop_smi = */ true); | 6296 /* drop_smi = */ true); |
| 6349 const intptr_t num_checks = sorted_ic_data.length(); | 6297 const intptr_t num_checks = sorted_ic_data.length(); |
| 6350 for (intptr_t i = 0; i < num_checks; i++) { | 6298 for (intptr_t i = 0; i < num_checks; i++) { |
| 6351 const intptr_t cid = sorted_ic_data[i].cid; | 6299 const intptr_t cid = sorted_ic_data[i].cid; |
| 6352 ASSERT(cid != kSmiCid); | 6300 ASSERT(cid != kSmiCid); |
| 6353 __ CompareImmediate(temp, cid); | 6301 __ CompareImmediate(temp, cid); |
| 6354 if (i == (num_checks - 1)) { | 6302 if (i == (num_checks - 1)) { |
| 6355 __ b(deopt, NE); | 6303 __ b(deopt, NE); |
| 6356 } else { | 6304 } else { |
| 6357 __ b(&is_ok, EQ); | 6305 __ b(&is_ok, EQ); |
| 6358 } | 6306 } |
| 6359 } | 6307 } |
| 6360 } | 6308 } |
| 6361 __ Bind(&is_ok); | 6309 __ Bind(&is_ok); |
| 6362 } | 6310 } |
| 6363 | 6311 |
| 6364 | 6312 |
| 6365 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 6313 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
| 6366 bool opt) const { | 6314 bool opt) const { |
| 6367 const intptr_t kNumInputs = 1; | 6315 const intptr_t kNumInputs = 1; |
| 6368 const intptr_t kNumTemps = 0; | 6316 const intptr_t kNumTemps = 0; |
| 6369 LocationSummary* summary = new(zone) LocationSummary( | 6317 LocationSummary* summary = new (zone) |
| 6370 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6318 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6371 summary->set_in(0, Location::RequiresRegister()); | 6319 summary->set_in(0, Location::RequiresRegister()); |
| 6372 return summary; | 6320 return summary; |
| 6373 } | 6321 } |
| 6374 | 6322 |
| 6375 | 6323 |
| 6376 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6324 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6377 const Register value = locs()->in(0).reg(); | 6325 const Register value = locs()->in(0).reg(); |
| 6378 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 6326 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, |
| 6379 ICData::kDeoptCheckSmi, | |
| 6380 licm_hoisted_ ? ICData::kHoisted : 0); | 6327 licm_hoisted_ ? ICData::kHoisted : 0); |
| 6381 __ BranchIfNotSmi(value, deopt); | 6328 __ BranchIfNotSmi(value, deopt); |
| 6382 } | 6329 } |
| 6383 | 6330 |
| 6384 | 6331 |
| 6385 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 6332 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
| 6386 bool opt) const { | 6333 bool opt) const { |
| 6387 const intptr_t kNumInputs = 1; | 6334 const intptr_t kNumInputs = 1; |
| 6388 const intptr_t kNumTemps = 0; | 6335 const intptr_t kNumTemps = 0; |
| 6389 LocationSummary* summary = new(zone) LocationSummary( | 6336 LocationSummary* summary = new (zone) |
| 6390 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6337 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6391 summary->set_in(0, Location::RequiresRegister()); | 6338 summary->set_in(0, Location::RequiresRegister()); |
| 6392 return summary; | 6339 return summary; |
| 6393 } | 6340 } |
| 6394 | 6341 |
| 6395 | 6342 |
| 6396 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6343 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6397 Register value = locs()->in(0).reg(); | 6344 Register value = locs()->in(0).reg(); |
| 6398 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 6345 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
| 6399 __ CompareImmediate(value, Smi::RawValue(cid_)); | 6346 __ CompareImmediate(value, Smi::RawValue(cid_)); |
| 6400 __ b(deopt, NE); | 6347 __ b(deopt, NE); |
| 6401 } | 6348 } |
| 6402 | 6349 |
| 6403 | 6350 |
| 6404 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, | 6351 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, |
| 6405 bool opt) const { | 6352 bool opt) const { |
| 6406 const intptr_t kNumInputs = 2; | 6353 const intptr_t kNumInputs = 2; |
| 6407 const intptr_t kNumTemps = 0; | 6354 const intptr_t kNumTemps = 0; |
| 6408 LocationSummary* locs = new(zone) LocationSummary( | 6355 LocationSummary* locs = new (zone) LocationSummary( |
| 6409 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 6356 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 6410 locs->set_in(kLengthPos, Location::RequiresRegister()); | 6357 locs->set_in(kLengthPos, Location::RequiresRegister()); |
| 6411 locs->set_in(kIndexPos, Location::RequiresRegister()); | 6358 locs->set_in(kIndexPos, Location::RequiresRegister()); |
| 6412 return locs; | 6359 return locs; |
| 6413 } | 6360 } |
| 6414 | 6361 |
| 6415 | 6362 |
| 6416 class RangeErrorSlowPath : public SlowPathCode { | 6363 class RangeErrorSlowPath : public SlowPathCode { |
| 6417 public: | 6364 public: |
| 6418 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) | 6365 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) |
| 6419 : instruction_(instruction), try_index_(try_index) { } | 6366 : instruction_(instruction), try_index_(try_index) {} |
| 6420 | 6367 |
| 6421 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 6368 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6422 if (Assembler::EmittingComments()) { | 6369 if (Assembler::EmittingComments()) { |
| 6423 __ Comment("slow path check bound operation"); | 6370 __ Comment("slow path check bound operation"); |
| 6424 } | 6371 } |
| 6425 __ Bind(entry_label()); | 6372 __ Bind(entry_label()); |
| 6426 LocationSummary* locs = instruction_->locs(); | 6373 LocationSummary* locs = instruction_->locs(); |
| 6427 __ Push(locs->in(0).reg()); | 6374 __ Push(locs->in(0).reg()); |
| 6428 __ Push(locs->in(1).reg()); | 6375 __ Push(locs->in(1).reg()); |
| 6429 __ CallRuntime(kRangeErrorRuntimeEntry, 2); | 6376 __ CallRuntime(kRangeErrorRuntimeEntry, 2); |
| 6430 compiler->pc_descriptors_list()->AddDescriptor( | 6377 compiler->pc_descriptors_list()->AddDescriptor( |
| 6431 RawPcDescriptors::kOther, | 6378 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), |
| 6432 compiler->assembler()->CodeSize(), | 6379 instruction_->deopt_id(), instruction_->token_pos(), try_index_); |
| 6433 instruction_->deopt_id(), | |
| 6434 instruction_->token_pos(), | |
| 6435 try_index_); | |
| 6436 compiler->RecordSafepoint(locs, 2); | 6380 compiler->RecordSafepoint(locs, 2); |
| 6437 __ bkpt(0); | 6381 __ bkpt(0); |
| 6438 } | 6382 } |
| 6439 | 6383 |
| 6440 private: | 6384 private: |
| 6441 GenericCheckBoundInstr* instruction_; | 6385 GenericCheckBoundInstr* instruction_; |
| 6442 intptr_t try_index_; | 6386 intptr_t try_index_; |
| 6443 }; | 6387 }; |
| 6444 | 6388 |
| 6445 | 6389 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 6458 } | 6402 } |
| 6459 __ cmp(index, Operand(length)); | 6403 __ cmp(index, Operand(length)); |
| 6460 __ b(slow_path->entry_label(), CS); | 6404 __ b(slow_path->entry_label(), CS); |
| 6461 } | 6405 } |
| 6462 | 6406 |
| 6463 | 6407 |
| 6464 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 6408 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
| 6465 bool opt) const { | 6409 bool opt) const { |
| 6466 const intptr_t kNumInputs = 2; | 6410 const intptr_t kNumInputs = 2; |
| 6467 const intptr_t kNumTemps = 0; | 6411 const intptr_t kNumTemps = 0; |
| 6468 LocationSummary* locs = new(zone) LocationSummary( | 6412 LocationSummary* locs = new (zone) |
| 6469 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6413 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6470 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 6414 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
| 6471 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 6415 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
| 6472 return locs; | 6416 return locs; |
| 6473 } | 6417 } |
| 6474 | 6418 |
| 6475 | 6419 |
| 6476 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6420 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6477 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 6421 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |
| 6478 flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 6422 flags |= licm_hoisted_ ? ICData::kHoisted : 0; |
| 6479 Label* deopt = compiler->AddDeoptStub( | 6423 Label* deopt = |
| 6480 deopt_id(), | 6424 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); |
| 6481 ICData::kDeoptCheckArrayBound, | |
| 6482 flags); | |
| 6483 | 6425 |
| 6484 Location length_loc = locs()->in(kLengthPos); | 6426 Location length_loc = locs()->in(kLengthPos); |
| 6485 Location index_loc = locs()->in(kIndexPos); | 6427 Location index_loc = locs()->in(kIndexPos); |
| 6486 | 6428 |
| 6487 if (length_loc.IsConstant() && index_loc.IsConstant()) { | 6429 if (length_loc.IsConstant() && index_loc.IsConstant()) { |
| 6488 ASSERT((Smi::Cast(length_loc.constant()).Value() <= | 6430 ASSERT((Smi::Cast(length_loc.constant()).Value() <= |
| 6489 Smi::Cast(index_loc.constant()).Value()) || | 6431 Smi::Cast(index_loc.constant()).Value()) || |
| 6490 (Smi::Cast(index_loc.constant()).Value() < 0)); | 6432 (Smi::Cast(index_loc.constant()).Value() < 0)); |
| 6491 // Unconditionally deoptimize for constant bounds checks because they | 6433 // Unconditionally deoptimize for constant bounds checks because they |
| 6492 // only occur only when index is out-of-bounds. | 6434 // only occur only when index is out-of-bounds. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 6522 __ cmp(index, Operand(length)); | 6464 __ cmp(index, Operand(length)); |
| 6523 __ b(deopt, CS); | 6465 __ b(deopt, CS); |
| 6524 } | 6466 } |
| 6525 } | 6467 } |
| 6526 | 6468 |
| 6527 | 6469 |
| 6528 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, | 6470 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, |
| 6529 bool opt) const { | 6471 bool opt) const { |
| 6530 const intptr_t kNumInputs = 2; | 6472 const intptr_t kNumInputs = 2; |
| 6531 const intptr_t kNumTemps = 0; | 6473 const intptr_t kNumTemps = 0; |
| 6532 LocationSummary* summary = new(zone) LocationSummary( | 6474 LocationSummary* summary = new (zone) |
| 6533 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6475 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6534 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6476 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 6535 Location::RequiresRegister())); | 6477 Location::RequiresRegister())); |
| 6536 summary->set_in(1, Location::Pair(Location::RequiresRegister(), | 6478 summary->set_in(1, Location::Pair(Location::RequiresRegister(), |
| 6537 Location::RequiresRegister())); | 6479 Location::RequiresRegister())); |
| 6538 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6480 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 6539 Location::RequiresRegister())); | 6481 Location::RequiresRegister())); |
| 6540 return summary; | 6482 return summary; |
| 6541 } | 6483 } |
| 6542 | 6484 |
| 6543 | 6485 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 6561 __ and_(out_lo, left_lo, Operand(right_lo)); | 6503 __ and_(out_lo, left_lo, Operand(right_lo)); |
| 6562 __ and_(out_hi, left_hi, Operand(right_hi)); | 6504 __ and_(out_hi, left_hi, Operand(right_hi)); |
| 6563 break; | 6505 break; |
| 6564 } | 6506 } |
| 6565 case Token::kBIT_OR: { | 6507 case Token::kBIT_OR: { |
| 6566 __ orr(out_lo, left_lo, Operand(right_lo)); | 6508 __ orr(out_lo, left_lo, Operand(right_lo)); |
| 6567 __ orr(out_hi, left_hi, Operand(right_hi)); | 6509 __ orr(out_hi, left_hi, Operand(right_hi)); |
| 6568 break; | 6510 break; |
| 6569 } | 6511 } |
| 6570 case Token::kBIT_XOR: { | 6512 case Token::kBIT_XOR: { |
| 6571 __ eor(out_lo, left_lo, Operand(right_lo)); | 6513 __ eor(out_lo, left_lo, Operand(right_lo)); |
| 6572 __ eor(out_hi, left_hi, Operand(right_hi)); | 6514 __ eor(out_hi, left_hi, Operand(right_hi)); |
| 6573 break; | 6515 break; |
| 6574 } | 6516 } |
| 6575 case Token::kADD: | 6517 case Token::kADD: |
| 6576 case Token::kSUB: { | 6518 case Token::kSUB: { |
| 6577 if (op_kind() == Token::kADD) { | 6519 if (op_kind() == Token::kADD) { |
| 6578 __ adds(out_lo, left_lo, Operand(right_lo)); | 6520 __ adds(out_lo, left_lo, Operand(right_lo)); |
| 6579 __ adcs(out_hi, left_hi, Operand(right_hi)); | 6521 __ adcs(out_hi, left_hi, Operand(right_hi)); |
| 6580 } else { | 6522 } else { |
| 6581 ASSERT(op_kind() == Token::kSUB); | 6523 ASSERT(op_kind() == Token::kSUB); |
| 6582 __ subs(out_lo, left_lo, Operand(right_lo)); | 6524 __ subs(out_lo, left_lo, Operand(right_lo)); |
| 6583 __ sbcs(out_hi, left_hi, Operand(right_hi)); | 6525 __ sbcs(out_hi, left_hi, Operand(right_hi)); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 6602 default: | 6544 default: |
| 6603 UNREACHABLE(); | 6545 UNREACHABLE(); |
| 6604 } | 6546 } |
| 6605 } | 6547 } |
| 6606 | 6548 |
| 6607 | 6549 |
| 6608 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, | 6550 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, |
| 6609 bool opt) const { | 6551 bool opt) const { |
| 6610 const intptr_t kNumInputs = 2; | 6552 const intptr_t kNumInputs = 2; |
| 6611 const intptr_t kNumTemps = 0; | 6553 const intptr_t kNumTemps = 0; |
| 6612 LocationSummary* summary = new(zone) LocationSummary( | 6554 LocationSummary* summary = new (zone) |
| 6613 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6555 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6614 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6556 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 6615 Location::RequiresRegister())); | 6557 Location::RequiresRegister())); |
| 6616 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); | 6558 summary->set_in(1, Location::WritableRegisterOrSmiConstant(right())); |
| 6617 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6559 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 6618 Location::RequiresRegister())); | 6560 Location::RequiresRegister())); |
| 6619 return summary; | 6561 return summary; |
| 6620 } | 6562 } |
| 6621 | 6563 |
| 6622 | 6564 |
| 6623 static const intptr_t kMintShiftCountLimit = 63; | 6565 static const intptr_t kMintShiftCountLimit = 63; |
| 6624 | 6566 |
| 6625 bool ShiftMintOpInstr::has_shift_count_check() const { | 6567 bool ShiftMintOpInstr::has_shift_count_check() const { |
| 6626 return !RangeUtils::IsWithin( | 6568 return !RangeUtils::IsWithin(right()->definition()->range(), 0, |
| 6627 right()->definition()->range(), 0, kMintShiftCountLimit); | 6569 kMintShiftCountLimit); |
| 6628 } | 6570 } |
| 6629 | 6571 |
| 6630 | 6572 |
| 6631 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6573 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6632 PairLocation* left_pair = locs()->in(0).AsPairLocation(); | 6574 PairLocation* left_pair = locs()->in(0).AsPairLocation(); |
| 6633 Register left_lo = left_pair->At(0).reg(); | 6575 Register left_lo = left_pair->At(0).reg(); |
| 6634 Register left_hi = left_pair->At(1).reg(); | 6576 Register left_hi = left_pair->At(1).reg(); |
| 6635 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6577 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
| 6636 Register out_lo = out_pair->At(0).reg(); | 6578 Register out_lo = out_pair->At(0).reg(); |
| 6637 Register out_hi = out_pair->At(1).reg(); | 6579 Register out_hi = out_pair->At(1).reg(); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6747 UNREACHABLE(); | 6689 UNREACHABLE(); |
| 6748 } | 6690 } |
| 6749 } | 6691 } |
| 6750 } | 6692 } |
| 6751 | 6693 |
| 6752 | 6694 |
| 6753 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, | 6695 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, |
| 6754 bool opt) const { | 6696 bool opt) const { |
| 6755 const intptr_t kNumInputs = 1; | 6697 const intptr_t kNumInputs = 1; |
| 6756 const intptr_t kNumTemps = 0; | 6698 const intptr_t kNumTemps = 0; |
| 6757 LocationSummary* summary = new(zone) LocationSummary( | 6699 LocationSummary* summary = new (zone) |
| 6758 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6700 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6759 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6701 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 6760 Location::RequiresRegister())); | 6702 Location::RequiresRegister())); |
| 6761 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6703 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 6762 Location::RequiresRegister())); | 6704 Location::RequiresRegister())); |
| 6763 return summary; | 6705 return summary; |
| 6764 } | 6706 } |
| 6765 | 6707 |
| 6766 | 6708 |
| 6767 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6709 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6768 ASSERT(op_kind() == Token::kBIT_NOT); | 6710 ASSERT(op_kind() == Token::kBIT_NOT); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 6790 | 6732 |
| 6791 CompileType UnaryUint32OpInstr::ComputeType() const { | 6733 CompileType UnaryUint32OpInstr::ComputeType() const { |
| 6792 return CompileType::Int(); | 6734 return CompileType::Int(); |
| 6793 } | 6735 } |
| 6794 | 6736 |
| 6795 | 6737 |
| 6796 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 6738 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 6797 bool opt) const { | 6739 bool opt) const { |
| 6798 const intptr_t kNumInputs = 2; | 6740 const intptr_t kNumInputs = 2; |
| 6799 const intptr_t kNumTemps = 0; | 6741 const intptr_t kNumTemps = 0; |
| 6800 LocationSummary* summary = new(zone) LocationSummary( | 6742 LocationSummary* summary = new (zone) |
| 6801 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6743 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6802 summary->set_in(0, Location::RequiresRegister()); | 6744 summary->set_in(0, Location::RequiresRegister()); |
| 6803 summary->set_in(1, Location::RequiresRegister()); | 6745 summary->set_in(1, Location::RequiresRegister()); |
| 6804 summary->set_out(0, Location::RequiresRegister()); | 6746 summary->set_out(0, Location::RequiresRegister()); |
| 6805 return summary; | 6747 return summary; |
| 6806 } | 6748 } |
| 6807 | 6749 |
| 6808 | 6750 |
| 6809 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6751 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6810 Register left = locs()->in(0).reg(); | 6752 Register left = locs()->in(0).reg(); |
| 6811 Register right = locs()->in(1).reg(); | 6753 Register right = locs()->in(1).reg(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 6833 default: | 6775 default: |
| 6834 UNREACHABLE(); | 6776 UNREACHABLE(); |
| 6835 } | 6777 } |
| 6836 } | 6778 } |
| 6837 | 6779 |
| 6838 | 6780 |
| 6839 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, | 6781 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 6840 bool opt) const { | 6782 bool opt) const { |
| 6841 const intptr_t kNumInputs = 2; | 6783 const intptr_t kNumInputs = 2; |
| 6842 const intptr_t kNumTemps = 1; | 6784 const intptr_t kNumTemps = 1; |
| 6843 LocationSummary* summary = new(zone) LocationSummary( | 6785 LocationSummary* summary = new (zone) |
| 6844 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6786 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6845 summary->set_in(0, Location::RequiresRegister()); | 6787 summary->set_in(0, Location::RequiresRegister()); |
| 6846 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 6788 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 6847 summary->set_temp(0, Location::RequiresRegister()); | 6789 summary->set_temp(0, Location::RequiresRegister()); |
| 6848 summary->set_out(0, Location::RequiresRegister()); | 6790 summary->set_out(0, Location::RequiresRegister()); |
| 6849 return summary; | 6791 return summary; |
| 6850 } | 6792 } |
| 6851 | 6793 |
| 6852 | 6794 |
| 6853 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6795 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6854 const intptr_t kShifterLimit = 31; | 6796 const intptr_t kShifterLimit = 31; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6903 default: | 6845 default: |
| 6904 UNREACHABLE(); | 6846 UNREACHABLE(); |
| 6905 } | 6847 } |
| 6906 } | 6848 } |
| 6907 | 6849 |
| 6908 | 6850 |
| 6909 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 6851 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 6910 bool opt) const { | 6852 bool opt) const { |
| 6911 const intptr_t kNumInputs = 1; | 6853 const intptr_t kNumInputs = 1; |
| 6912 const intptr_t kNumTemps = 0; | 6854 const intptr_t kNumTemps = 0; |
| 6913 LocationSummary* summary = new(zone) LocationSummary( | 6855 LocationSummary* summary = new (zone) |
| 6914 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6856 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6915 summary->set_in(0, Location::RequiresRegister()); | 6857 summary->set_in(0, Location::RequiresRegister()); |
| 6916 summary->set_out(0, Location::RequiresRegister()); | 6858 summary->set_out(0, Location::RequiresRegister()); |
| 6917 return summary; | 6859 return summary; |
| 6918 } | 6860 } |
| 6919 | 6861 |
| 6920 | 6862 |
| 6921 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6863 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6922 Register left = locs()->in(0).reg(); | 6864 Register left = locs()->in(0).reg(); |
| 6923 Register out = locs()->out(0).reg(); | 6865 Register out = locs()->out(0).reg(); |
| 6924 ASSERT(left != out); | 6866 ASSERT(left != out); |
| 6925 | 6867 |
| 6926 ASSERT(op_kind() == Token::kBIT_NOT); | 6868 ASSERT(op_kind() == Token::kBIT_NOT); |
| 6927 | 6869 |
| 6928 __ mvn(out, Operand(left)); | 6870 __ mvn(out, Operand(left)); |
| 6929 } | 6871 } |
| 6930 | 6872 |
| 6931 | 6873 |
| 6932 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 6874 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |
| 6933 bool opt) const { | 6875 bool opt) const { |
| 6934 const intptr_t kNumInputs = 1; | 6876 const intptr_t kNumInputs = 1; |
| 6935 const intptr_t kNumTemps = 0; | 6877 const intptr_t kNumTemps = 0; |
| 6936 LocationSummary* summary = new(zone) LocationSummary( | 6878 LocationSummary* summary = new (zone) |
| 6937 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6879 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6938 if (from() == kUnboxedMint) { | 6880 if (from() == kUnboxedMint) { |
| 6939 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 6881 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 6940 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6882 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
| 6941 Location::RequiresRegister())); | 6883 Location::RequiresRegister())); |
| 6942 summary->set_out(0, Location::RequiresRegister()); | 6884 summary->set_out(0, Location::RequiresRegister()); |
| 6943 } else if (to() == kUnboxedMint) { | 6885 } else if (to() == kUnboxedMint) { |
| 6944 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 6886 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 6945 summary->set_in(0, Location::RequiresRegister()); | 6887 summary->set_in(0, Location::RequiresRegister()); |
| 6946 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6888 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
| 6947 Location::RequiresRegister())); | 6889 Location::RequiresRegister())); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6998 } else { | 6940 } else { |
| 6999 ASSERT(from() == kUnboxedInt32); | 6941 ASSERT(from() == kUnboxedInt32); |
| 7000 __ mov(out_hi, Operand(in, ASR, kBitsPerWord - 1)); | 6942 __ mov(out_hi, Operand(in, ASR, kBitsPerWord - 1)); |
| 7001 } | 6943 } |
| 7002 } else { | 6944 } else { |
| 7003 UNREACHABLE(); | 6945 UNREACHABLE(); |
| 7004 } | 6946 } |
| 7005 } | 6947 } |
| 7006 | 6948 |
| 7007 | 6949 |
| 7008 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, | 6950 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 7009 bool opt) const { | 6951 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 7010 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
| 7011 } | 6952 } |
| 7012 | 6953 |
| 7013 | 6954 |
| 7014 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6955 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 7015 compiler->GenerateRuntimeCall(token_pos(), | 6956 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, |
| 7016 deopt_id(), | |
| 7017 kThrowRuntimeEntry, | |
| 7018 1, | |
| 7019 locs()); | 6957 locs()); |
| 7020 __ bkpt(0); | 6958 __ bkpt(0); |
| 7021 } | 6959 } |
| 7022 | 6960 |
| 7023 | 6961 |
| 7024 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, | 6962 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 7025 bool opt) const { | 6963 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 7026 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
| 7027 } | 6964 } |
| 7028 | 6965 |
| 7029 | 6966 |
| 7030 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6967 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 7031 compiler->SetNeedsStacktrace(catch_try_index()); | 6968 compiler->SetNeedsStacktrace(catch_try_index()); |
| 7032 compiler->GenerateRuntimeCall(token_pos(), | 6969 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, |
| 7033 deopt_id(), | 6970 2, locs()); |
| 7034 kReThrowRuntimeEntry, | |
| 7035 2, | |
| 7036 locs()); | |
| 7037 __ bkpt(0); | 6971 __ bkpt(0); |
| 7038 } | 6972 } |
| 7039 | 6973 |
| 7040 | 6974 |
| 7041 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, | 6975 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 7042 bool opt) const { | 6976 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 7043 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
| 7044 } | 6977 } |
| 7045 | 6978 |
| 7046 | 6979 |
| 7047 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6980 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 7048 __ Stop(message()); | 6981 __ Stop(message()); |
| 7049 } | 6982 } |
| 7050 | 6983 |
| 7051 | 6984 |
| 7052 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6985 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 7053 if (!compiler->CanFallThroughTo(normal_entry())) { | 6986 if (!compiler->CanFallThroughTo(normal_entry())) { |
| 7054 __ b(compiler->GetJumpLabel(normal_entry())); | 6987 __ b(compiler->GetJumpLabel(normal_entry())); |
| 7055 } | 6988 } |
| 7056 } | 6989 } |
| 7057 | 6990 |
| 7058 | 6991 |
| 7059 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, | 6992 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 7060 bool opt) const { | 6993 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 7061 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
| 7062 } | 6994 } |
| 7063 | 6995 |
| 7064 | 6996 |
| 7065 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6997 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 7066 if (!compiler->is_optimizing()) { | 6998 if (!compiler->is_optimizing()) { |
| 7067 if (FLAG_reorder_basic_blocks) { | 6999 if (FLAG_reorder_basic_blocks) { |
| 7068 compiler->EmitEdgeCounter(block()->preorder_number()); | 7000 compiler->EmitEdgeCounter(block()->preorder_number()); |
| 7069 } | 7001 } |
| 7070 // Add a deoptimization descriptor for deoptimizing instructions that | 7002 // Add a deoptimization descriptor for deoptimizing instructions that |
| 7071 // may be inserted before this instruction. | 7003 // may be inserted before this instruction. |
| 7072 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 7004 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), |
| 7073 GetDeoptId(), | |
| 7074 TokenPosition::kNoSource); | 7005 TokenPosition::kNoSource); |
| 7075 } | 7006 } |
| 7076 if (HasParallelMove()) { | 7007 if (HasParallelMove()) { |
| 7077 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 7008 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 7078 } | 7009 } |
| 7079 | 7010 |
| 7080 // We can fall through if the successor is the next block in the list. | 7011 // We can fall through if the successor is the next block in the list. |
| 7081 // Otherwise, we need a jump. | 7012 // Otherwise, we need a jump. |
| 7082 if (!compiler->CanFallThroughTo(successor())) { | 7013 if (!compiler->CanFallThroughTo(successor())) { |
| 7083 __ b(compiler->GetJumpLabel(successor())); | 7014 __ b(compiler->GetJumpLabel(successor())); |
| 7084 } | 7015 } |
| 7085 } | 7016 } |
| 7086 | 7017 |
| 7087 | 7018 |
| 7088 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 7019 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |
| 7089 bool opt) const { | 7020 bool opt) const { |
| 7090 const intptr_t kNumInputs = 1; | 7021 const intptr_t kNumInputs = 1; |
| 7091 const intptr_t kNumTemps = 1; | 7022 const intptr_t kNumTemps = 1; |
| 7092 | 7023 |
| 7093 LocationSummary* summary = new(zone) LocationSummary( | 7024 LocationSummary* summary = new (zone) |
| 7094 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 7025 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 7095 | 7026 |
| 7096 summary->set_in(0, Location::RequiresRegister()); | 7027 summary->set_in(0, Location::RequiresRegister()); |
| 7097 summary->set_temp(0, Location::RequiresRegister()); | 7028 summary->set_temp(0, Location::RequiresRegister()); |
| 7098 | 7029 |
| 7099 return summary; | 7030 return summary; |
| 7100 } | 7031 } |
| 7101 | 7032 |
| 7102 | 7033 |
| 7103 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 7034 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 7104 Register target_address_reg = locs()->temp_slot(0)->reg(); | 7035 Register target_address_reg = locs()->temp_slot(0)->reg(); |
| 7105 | 7036 |
| 7106 // Offset is relative to entry pc. | 7037 // Offset is relative to entry pc. |
| 7107 const intptr_t entry_to_pc_offset = __ CodeSize() + Instr::kPCReadOffset; | 7038 const intptr_t entry_to_pc_offset = __ CodeSize() + Instr::kPCReadOffset; |
| 7108 __ mov(target_address_reg, Operand(PC)); | 7039 __ mov(target_address_reg, Operand(PC)); |
| 7109 __ AddImmediate(target_address_reg, target_address_reg, -entry_to_pc_offset); | 7040 __ AddImmediate(target_address_reg, target_address_reg, -entry_to_pc_offset); |
| 7110 // Add the offset. | 7041 // Add the offset. |
| 7111 Register offset_reg = locs()->in(0).reg(); | 7042 Register offset_reg = locs()->in(0).reg(); |
| 7112 Operand offset_opr = | 7043 Operand offset_opr = (offset()->definition()->representation() == kTagged) |
| 7113 (offset()->definition()->representation() == kTagged) ? | 7044 ? Operand(offset_reg, ASR, kSmiTagSize) |
| 7114 Operand(offset_reg, ASR, kSmiTagSize) : | 7045 : Operand(offset_reg); |
| 7115 Operand(offset_reg); | |
| 7116 __ add(target_address_reg, target_address_reg, offset_opr); | 7046 __ add(target_address_reg, target_address_reg, offset_opr); |
| 7117 | 7047 |
| 7118 // Jump to the absolute address. | 7048 // Jump to the absolute address. |
| 7119 __ bx(target_address_reg); | 7049 __ bx(target_address_reg); |
| 7120 } | 7050 } |
| 7121 | 7051 |
| 7122 | 7052 |
| 7123 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, | 7053 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, |
| 7124 bool opt) const { | 7054 bool opt) const { |
| 7125 const intptr_t kNumInputs = 2; | 7055 const intptr_t kNumInputs = 2; |
| 7126 const intptr_t kNumTemps = 0; | 7056 const intptr_t kNumTemps = 0; |
| 7127 if (needs_number_check()) { | 7057 if (needs_number_check()) { |
| 7128 LocationSummary* locs = new(zone) LocationSummary( | 7058 LocationSummary* locs = new (zone) |
| 7129 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 7059 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 7130 locs->set_in(0, Location::RegisterLocation(R0)); | 7060 locs->set_in(0, Location::RegisterLocation(R0)); |
| 7131 locs->set_in(1, Location::RegisterLocation(R1)); | 7061 locs->set_in(1, Location::RegisterLocation(R1)); |
| 7132 locs->set_out(0, Location::RegisterLocation(R0)); | 7062 locs->set_out(0, Location::RegisterLocation(R0)); |
| 7133 return locs; | 7063 return locs; |
| 7134 } | 7064 } |
| 7135 LocationSummary* locs = new(zone) LocationSummary( | 7065 LocationSummary* locs = new (zone) |
| 7136 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 7066 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 7137 | 7067 |
| 7138 // If a constant has more than one use, make sure it is loaded in register | 7068 // If a constant has more than one use, make sure it is loaded in register |
| 7139 // so that multiple immediate loads can be avoided. | 7069 // so that multiple immediate loads can be avoided. |
| 7140 ConstantInstr* constant = left()->definition()->AsConstant(); | 7070 ConstantInstr* constant = left()->definition()->AsConstant(); |
| 7141 if ((constant != NULL) && !left()->IsSingleUse()) { | 7071 if ((constant != NULL) && !left()->IsSingleUse()) { |
| 7142 locs->set_in(0, Location::RequiresRegister()); | 7072 locs->set_in(0, Location::RequiresRegister()); |
| 7143 } else { | 7073 } else { |
| 7144 locs->set_in(0, Location::RegisterOrConstant(left())); | 7074 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 7145 } | 7075 } |
| 7146 | 7076 |
| 7147 constant = right()->definition()->AsConstant(); | 7077 constant = right()->definition()->AsConstant(); |
| 7148 if ((constant != NULL) && !right()->IsSingleUse()) { | 7078 if ((constant != NULL) && !right()->IsSingleUse()) { |
| 7149 locs->set_in(1, Location::RequiresRegister()); | 7079 locs->set_in(1, Location::RequiresRegister()); |
| 7150 } else { | 7080 } else { |
| 7151 // Only one of the inputs can be a constant. Choose register if the first | 7081 // Only one of the inputs can be a constant. Choose register if the first |
| 7152 // one is a constant. | 7082 // one is a constant. |
| 7153 locs->set_in(1, locs->in(0).IsConstant() | 7083 locs->set_in(1, locs->in(0).IsConstant() |
| 7154 ? Location::RequiresRegister() | 7084 ? Location::RequiresRegister() |
| 7155 : Location::RegisterOrConstant(right())); | 7085 : Location::RegisterOrConstant(right())); |
| 7156 } | 7086 } |
| 7157 locs->set_out(0, Location::RequiresRegister()); | 7087 locs->set_out(0, Location::RequiresRegister()); |
| 7158 return locs; | 7088 return locs; |
| 7159 } | 7089 } |
| 7160 | 7090 |
| 7161 | 7091 |
| 7162 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 7092 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 7163 BranchLabels labels) { | 7093 BranchLabels labels) { |
| 7164 Location left = locs()->in(0); | 7094 Location left = locs()->in(0); |
| 7165 Location right = locs()->in(1); | 7095 Location right = locs()->in(1); |
| 7166 ASSERT(!left.IsConstant() || !right.IsConstant()); | 7096 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 7167 Condition true_condition; | 7097 Condition true_condition; |
| 7168 if (left.IsConstant()) { | 7098 if (left.IsConstant()) { |
| 7169 true_condition = compiler->EmitEqualityRegConstCompare(right.reg(), | 7099 true_condition = compiler->EmitEqualityRegConstCompare( |
| 7170 left.constant(), | 7100 right.reg(), left.constant(), needs_number_check(), token_pos()); |
| 7171 needs_number_check(), | |
| 7172 token_pos()); | |
| 7173 } else if (right.IsConstant()) { | 7101 } else if (right.IsConstant()) { |
| 7174 true_condition = compiler->EmitEqualityRegConstCompare(left.reg(), | 7102 true_condition = compiler->EmitEqualityRegConstCompare( |
| 7175 right.constant(), | 7103 left.reg(), right.constant(), needs_number_check(), token_pos()); |
| 7176 needs_number_check(), | |
| 7177 token_pos()); | |
| 7178 } else { | 7104 } else { |
| 7179 true_condition = compiler->EmitEqualityRegRegCompare(left.reg(), | 7105 true_condition = compiler->EmitEqualityRegRegCompare( |
| 7180 right.reg(), | 7106 left.reg(), right.reg(), needs_number_check(), token_pos()); |
| 7181 needs_number_check(), | |
| 7182 token_pos()); | |
| 7183 } | 7107 } |
| 7184 if (kind() != Token::kEQ_STRICT) { | 7108 if (kind() != Token::kEQ_STRICT) { |
| 7185 ASSERT(kind() == Token::kNE_STRICT); | 7109 ASSERT(kind() == Token::kNE_STRICT); |
| 7186 true_condition = NegateCondition(true_condition); | 7110 true_condition = NegateCondition(true_condition); |
| 7187 } | 7111 } |
| 7188 return true_condition; | 7112 return true_condition; |
| 7189 } | 7113 } |
| 7190 | 7114 |
| 7191 | 7115 |
| 7192 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 7116 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 7193 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 7117 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 7194 | 7118 |
| 7195 // The ARM code does not use true- and false-labels here. | 7119 // The ARM code does not use true- and false-labels here. |
| 7196 BranchLabels labels = { NULL, NULL, NULL }; | 7120 BranchLabels labels = {NULL, NULL, NULL}; |
| 7197 Condition true_condition = EmitComparisonCode(compiler, labels); | 7121 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 7198 | 7122 |
| 7199 const Register result = locs()->out(0).reg(); | 7123 const Register result = locs()->out(0).reg(); |
| 7200 __ LoadObject(result, Bool::True(), true_condition); | 7124 __ LoadObject(result, Bool::True(), true_condition); |
| 7201 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); | 7125 __ LoadObject(result, Bool::False(), NegateCondition(true_condition)); |
| 7202 } | 7126 } |
| 7203 | 7127 |
| 7204 | 7128 |
| 7205 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 7129 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 7206 BranchInstr* branch) { | 7130 BranchInstr* branch) { |
| 7207 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 7131 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 7208 | 7132 |
| 7209 BranchLabels labels = compiler->CreateBranchLabels(branch); | 7133 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 7210 Condition true_condition = EmitComparisonCode(compiler, labels); | 7134 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 7211 EmitBranchOnCondition(compiler, true_condition, labels); | 7135 EmitBranchOnCondition(compiler, true_condition, labels); |
| 7212 } | 7136 } |
| 7213 | 7137 |
| 7214 | 7138 |
| 7215 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 7139 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
| 7216 bool opt) const { | 7140 bool opt) const { |
| 7217 return LocationSummary::Make(zone, | 7141 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
| 7218 1, | |
| 7219 Location::RequiresRegister(), | |
| 7220 LocationSummary::kNoCall); | 7142 LocationSummary::kNoCall); |
| 7221 } | 7143 } |
| 7222 | 7144 |
| 7223 | 7145 |
| 7224 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 7146 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 7225 const Register value = locs()->in(0).reg(); | 7147 const Register value = locs()->in(0).reg(); |
| 7226 const Register result = locs()->out(0).reg(); | 7148 const Register result = locs()->out(0).reg(); |
| 7227 | 7149 |
| 7228 __ LoadObject(result, Bool::True()); | 7150 __ LoadObject(result, Bool::True()); |
| 7229 __ cmp(result, Operand(value)); | 7151 __ cmp(result, Operand(value)); |
| 7230 __ LoadObject(result, Bool::False(), EQ); | 7152 __ LoadObject(result, Bool::False(), EQ); |
| 7231 } | 7153 } |
| 7232 | 7154 |
| 7233 | 7155 |
| 7234 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 7156 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
| 7235 bool opt) const { | 7157 bool opt) const { |
| 7236 return MakeCallSummary(zone); | 7158 return MakeCallSummary(zone); |
| 7237 } | 7159 } |
| 7238 | 7160 |
| 7239 | 7161 |
| 7240 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 7162 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 7241 const Code& stub = Code::ZoneHandle( | 7163 const Code& stub = Code::ZoneHandle( |
| 7242 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 7164 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |
| 7243 const StubEntry stub_entry(stub); | 7165 const StubEntry stub_entry(stub); |
| 7244 compiler->GenerateCall(token_pos(), | 7166 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, |
| 7245 stub_entry, | |
| 7246 RawPcDescriptors::kOther, | |
| 7247 locs()); | 7167 locs()); |
| 7248 compiler->AddStubCallTarget(stub); | 7168 compiler->AddStubCallTarget(stub); |
| 7249 __ Drop(ArgumentCount()); // Discard arguments. | 7169 __ Drop(ArgumentCount()); // Discard arguments. |
| 7250 } | 7170 } |
| 7251 | 7171 |
| 7252 | 7172 |
| 7253 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 7173 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 7254 ASSERT(!compiler->is_optimizing()); | 7174 ASSERT(!compiler->is_optimizing()); |
| 7255 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); | 7175 __ BranchLinkPatchable(*StubCode::DebugStepCheck_entry()); |
| 7256 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); | 7176 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); |
| 7257 compiler->RecordSafepoint(locs()); | 7177 compiler->RecordSafepoint(locs()); |
| 7258 } | 7178 } |
| 7259 | 7179 |
| 7260 | 7180 |
| 7261 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary( | 7181 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary(Zone* zone, |
| 7262 Zone* zone, bool opt) const { | 7182 bool opt) const { |
| 7263 const intptr_t kNumInputs = 1; | 7183 const intptr_t kNumInputs = 1; |
| 7264 const intptr_t kNumTemps = 0; | 7184 const intptr_t kNumTemps = 0; |
| 7265 LocationSummary* locs = new(zone) LocationSummary( | 7185 LocationSummary* locs = new (zone) |
| 7266 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 7186 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 7267 locs->set_in(0, Location::RegisterLocation(R0)); | 7187 locs->set_in(0, Location::RegisterLocation(R0)); |
| 7268 locs->set_out(0, Location::RegisterLocation(R0)); | 7188 locs->set_out(0, Location::RegisterLocation(R0)); |
| 7269 return locs; | 7189 return locs; |
| 7270 } | 7190 } |
| 7271 | 7191 |
| 7272 | 7192 |
| 7273 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 7193 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 7274 const Register typed_data = locs()->in(0).reg(); | 7194 const Register typed_data = locs()->in(0).reg(); |
| 7275 const Register result = locs()->out(0).reg(); | 7195 const Register result = locs()->out(0).reg(); |
| 7276 __ PushObject(Object::null_object()); | 7196 __ PushObject(Object::null_object()); |
| 7277 __ Push(typed_data); | 7197 __ Push(typed_data); |
| 7278 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, | 7198 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
| 7279 deopt_id(), | 7199 kGrowRegExpStackRuntimeEntry, 1, locs()); |
| 7280 kGrowRegExpStackRuntimeEntry, | |
| 7281 1, | |
| 7282 locs()); | |
| 7283 __ Drop(1); | 7200 __ Drop(1); |
| 7284 __ Pop(result); | 7201 __ Pop(result); |
| 7285 } | 7202 } |
| 7286 | 7203 |
| 7287 | 7204 |
| 7288 } // namespace dart | 7205 } // namespace dart |
| 7289 | 7206 |
| 7290 #endif // defined TARGET_ARCH_ARM | 7207 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |