| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 | 27 |
| 28 // Generic summary for call instructions that have all arguments pushed | 28 // Generic summary for call instructions that have all arguments pushed |
| 29 // on the stack and return the result in a fixed register RAX. | 29 // on the stack and return the result in a fixed register RAX. |
| 30 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { | 30 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { |
| 31 LocationSummary* result = | 31 LocationSummary* result = |
| 32 new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | 32 new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 33 result->set_out(0, Location::RegisterLocation(RAX)); | 33 result->set_out(0, Location::RegisterLocation(RAX)); |
| 34 return result; | 34 return result; |
| 35 } | 35 } |
| 36 | 36 |
| 37 | |
| 38 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, | 37 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, |
| 39 bool opt) const { | 38 bool opt) const { |
| 40 const intptr_t kNumInputs = 1; | 39 const intptr_t kNumInputs = 1; |
| 41 const intptr_t kNumTemps = 0; | 40 const intptr_t kNumTemps = 0; |
| 42 LocationSummary* locs = new (zone) | 41 LocationSummary* locs = new (zone) |
| 43 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 42 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 44 locs->set_in(0, Location::AnyOrConstant(value())); | 43 locs->set_in(0, Location::AnyOrConstant(value())); |
| 45 return locs; | 44 return locs; |
| 46 } | 45 } |
| 47 | 46 |
| 48 | |
| 49 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 47 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 50 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 48 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
| 51 // where PushArgument is handled by BindInstr::EmitNativeCode. | 49 // where PushArgument is handled by BindInstr::EmitNativeCode. |
| 52 if (compiler->is_optimizing()) { | 50 if (compiler->is_optimizing()) { |
| 53 Location value = locs()->in(0); | 51 Location value = locs()->in(0); |
| 54 if (value.IsRegister()) { | 52 if (value.IsRegister()) { |
| 55 __ pushq(value.reg()); | 53 __ pushq(value.reg()); |
| 56 } else if (value.IsConstant()) { | 54 } else if (value.IsConstant()) { |
| 57 __ PushObject(value.constant()); | 55 __ PushObject(value.constant()); |
| 58 } else { | 56 } else { |
| 59 ASSERT(value.IsStackSlot()); | 57 ASSERT(value.IsStackSlot()); |
| 60 __ pushq(value.ToStackSlotAddress()); | 58 __ pushq(value.ToStackSlotAddress()); |
| 61 } | 59 } |
| 62 } | 60 } |
| 63 } | 61 } |
| 64 | 62 |
| 65 | |
| 66 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 63 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 67 const intptr_t kNumInputs = 1; | 64 const intptr_t kNumInputs = 1; |
| 68 const intptr_t kNumTemps = 0; | 65 const intptr_t kNumTemps = 0; |
| 69 LocationSummary* locs = new (zone) | 66 LocationSummary* locs = new (zone) |
| 70 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 67 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 71 locs->set_in(0, Location::RegisterLocation(RAX)); | 68 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 72 return locs; | 69 return locs; |
| 73 } | 70 } |
| 74 | 71 |
| 75 | |
| 76 // Attempt optimized compilation at return instruction instead of at the entry. | 72 // Attempt optimized compilation at return instruction instead of at the entry. |
| 77 // The entry needs to be patchable, no inlined objects are allowed in the area | 73 // The entry needs to be patchable, no inlined objects are allowed in the area |
| 78 // that will be overwritten by the patch instruction: a jump). | 74 // that will be overwritten by the patch instruction: a jump). |
| 79 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 75 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 80 Register result = locs()->in(0).reg(); | 76 Register result = locs()->in(0).reg(); |
| 81 ASSERT(result == RAX); | 77 ASSERT(result == RAX); |
| 82 | 78 |
| 83 if (compiler->intrinsic_mode()) { | 79 if (compiler->intrinsic_mode()) { |
| 84 // Intrinsics don't have a frame. | 80 // Intrinsics don't have a frame. |
| 85 __ ret(); | 81 __ ret(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 100 __ Bind(&done); | 96 __ Bind(&done); |
| 101 #endif | 97 #endif |
| 102 ASSERT(__ constant_pool_allowed()); | 98 ASSERT(__ constant_pool_allowed()); |
| 103 __ LeaveDartFrame(); // Disallows constant pool use. | 99 __ LeaveDartFrame(); // Disallows constant pool use. |
| 104 __ ret(); | 100 __ ret(); |
| 105 // This ReturnInstr may be emitted out of order by the optimizer. The next | 101 // This ReturnInstr may be emitted out of order by the optimizer. The next |
| 106 // block may be a target expecting a properly set constant pool pointer. | 102 // block may be a target expecting a properly set constant pool pointer. |
| 107 __ set_constant_pool_allowed(true); | 103 __ set_constant_pool_allowed(true); |
| 108 } | 104 } |
| 109 | 105 |
| 110 | |
| 111 static Condition NegateCondition(Condition condition) { | 106 static Condition NegateCondition(Condition condition) { |
| 112 switch (condition) { | 107 switch (condition) { |
| 113 case EQUAL: | 108 case EQUAL: |
| 114 return NOT_EQUAL; | 109 return NOT_EQUAL; |
| 115 case NOT_EQUAL: | 110 case NOT_EQUAL: |
| 116 return EQUAL; | 111 return EQUAL; |
| 117 case LESS: | 112 case LESS: |
| 118 return GREATER_EQUAL; | 113 return GREATER_EQUAL; |
| 119 case LESS_EQUAL: | 114 case LESS_EQUAL: |
| 120 return GREATER; | 115 return GREATER; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 133 case PARITY_EVEN: | 128 case PARITY_EVEN: |
| 134 return PARITY_ODD; | 129 return PARITY_ODD; |
| 135 case PARITY_ODD: | 130 case PARITY_ODD: |
| 136 return PARITY_EVEN; | 131 return PARITY_EVEN; |
| 137 default: | 132 default: |
| 138 UNIMPLEMENTED(); | 133 UNIMPLEMENTED(); |
| 139 return EQUAL; | 134 return EQUAL; |
| 140 } | 135 } |
| 141 } | 136 } |
| 142 | 137 |
| 143 | |
| 144 // Detect pattern when one value is zero and another is a power of 2. | 138 // Detect pattern when one value is zero and another is a power of 2. |
| 145 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 139 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 146 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 140 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| 147 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); | 141 (Utils::IsPowerOfTwo(v2) && (v1 == 0)); |
| 148 } | 142 } |
| 149 | 143 |
| 150 | |
| 151 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, | 144 LocationSummary* IfThenElseInstr::MakeLocationSummary(Zone* zone, |
| 152 bool opt) const { | 145 bool opt) const { |
| 153 comparison()->InitializeLocationSummary(zone, opt); | 146 comparison()->InitializeLocationSummary(zone, opt); |
| 154 // TODO(vegorov): support byte register constraints in the register allocator. | 147 // TODO(vegorov): support byte register constraints in the register allocator. |
| 155 comparison()->locs()->set_out(0, Location::RegisterLocation(RDX)); | 148 comparison()->locs()->set_out(0, Location::RegisterLocation(RDX)); |
| 156 return comparison()->locs(); | 149 return comparison()->locs(); |
| 157 } | 150 } |
| 158 | 151 |
| 159 | |
| 160 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 152 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 161 ASSERT(locs()->out(0).reg() == RDX); | 153 ASSERT(locs()->out(0).reg() == RDX); |
| 162 | 154 |
| 163 // Clear upper part of the out register. We are going to use setcc on it | 155 // Clear upper part of the out register. We are going to use setcc on it |
| 164 // which is a byte move. | 156 // which is a byte move. |
| 165 __ xorq(RDX, RDX); | 157 __ xorq(RDX, RDX); |
| 166 | 158 |
| 167 // Emit comparison code. This must not overwrite the result register. | 159 // Emit comparison code. This must not overwrite the result register. |
| 168 // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using | 160 // IfThenElseInstr::Supports() should prevent EmitComparisonCode from using |
| 169 // the labels or returning an invalid condition. | 161 // the labels or returning an invalid condition. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 } else { | 193 } else { |
| 202 __ decq(RDX); | 194 __ decq(RDX); |
| 203 __ AndImmediate( | 195 __ AndImmediate( |
| 204 RDX, Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value))); | 196 RDX, Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value))); |
| 205 if (false_value != 0) { | 197 if (false_value != 0) { |
| 206 __ AddImmediate(RDX, Immediate(Smi::RawValue(false_value))); | 198 __ AddImmediate(RDX, Immediate(Smi::RawValue(false_value))); |
| 207 } | 199 } |
| 208 } | 200 } |
| 209 } | 201 } |
| 210 | 202 |
| 211 | |
| 212 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 203 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
| 213 bool opt) const { | 204 bool opt) const { |
| 214 const intptr_t kNumInputs = 0; | 205 const intptr_t kNumInputs = 0; |
| 215 const intptr_t stack_index = (local().index() < 0) | 206 const intptr_t stack_index = (local().index() < 0) |
| 216 ? kFirstLocalSlotFromFp - local().index() | 207 ? kFirstLocalSlotFromFp - local().index() |
| 217 : kParamEndSlotFromFp - local().index(); | 208 : kParamEndSlotFromFp - local().index(); |
| 218 return LocationSummary::Make(zone, kNumInputs, | 209 return LocationSummary::Make(zone, kNumInputs, |
| 219 Location::StackSlot(stack_index), | 210 Location::StackSlot(stack_index), |
| 220 LocationSummary::kNoCall); | 211 LocationSummary::kNoCall); |
| 221 } | 212 } |
| 222 | 213 |
| 223 | |
| 224 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 214 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 225 ASSERT(!compiler->is_optimizing()); | 215 ASSERT(!compiler->is_optimizing()); |
| 226 // Nothing to do. | 216 // Nothing to do. |
| 227 } | 217 } |
| 228 | 218 |
| 229 | |
| 230 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 219 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |
| 231 bool opt) const { | 220 bool opt) const { |
| 232 const intptr_t kNumInputs = 1; | 221 const intptr_t kNumInputs = 1; |
| 233 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), | 222 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
| 234 LocationSummary::kNoCall); | 223 LocationSummary::kNoCall); |
| 235 } | 224 } |
| 236 | 225 |
| 237 | |
| 238 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 226 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 239 Register value = locs()->in(0).reg(); | 227 Register value = locs()->in(0).reg(); |
| 240 Register result = locs()->out(0).reg(); | 228 Register result = locs()->out(0).reg(); |
| 241 ASSERT(result == value); // Assert that register assignment is correct. | 229 ASSERT(result == value); // Assert that register assignment is correct. |
| 242 __ movq(Address(RBP, local().index() * kWordSize), value); | 230 __ movq(Address(RBP, local().index() * kWordSize), value); |
| 243 } | 231 } |
| 244 | 232 |
| 245 | |
| 246 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 233 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |
| 247 bool opt) const { | 234 bool opt) const { |
| 248 const intptr_t kNumInputs = 0; | 235 const intptr_t kNumInputs = 0; |
| 249 return LocationSummary::Make(zone, kNumInputs, | 236 return LocationSummary::Make(zone, kNumInputs, |
| 250 Assembler::IsSafe(value()) | 237 Assembler::IsSafe(value()) |
| 251 ? Location::Constant(this) | 238 ? Location::Constant(this) |
| 252 : Location::RequiresRegister(), | 239 : Location::RequiresRegister(), |
| 253 LocationSummary::kNoCall); | 240 LocationSummary::kNoCall); |
| 254 } | 241 } |
| 255 | 242 |
| 256 | |
| 257 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 243 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 258 // The register allocator drops constant definitions that have no uses. | 244 // The register allocator drops constant definitions that have no uses. |
| 259 Location out = locs()->out(0); | 245 Location out = locs()->out(0); |
| 260 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); | 246 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); |
| 261 if (out.IsRegister()) { | 247 if (out.IsRegister()) { |
| 262 Register result = out.reg(); | 248 Register result = out.reg(); |
| 263 __ LoadObject(result, value()); | 249 __ LoadObject(result, value()); |
| 264 } | 250 } |
| 265 } | 251 } |
| 266 | 252 |
| 267 | |
| 268 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 253 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
| 269 bool opt) const { | 254 bool opt) const { |
| 270 const intptr_t kNumInputs = 0; | 255 const intptr_t kNumInputs = 0; |
| 271 const intptr_t kNumTemps = 0; | 256 const intptr_t kNumTemps = 0; |
| 272 LocationSummary* locs = new (zone) | 257 LocationSummary* locs = new (zone) |
| 273 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 258 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 274 switch (representation()) { | 259 switch (representation()) { |
| 275 case kUnboxedDouble: | 260 case kUnboxedDouble: |
| 276 locs->set_out(0, Location::RequiresFpuRegister()); | 261 locs->set_out(0, Location::RequiresFpuRegister()); |
| 277 break; | 262 break; |
| 278 case kUnboxedInt32: | 263 case kUnboxedInt32: |
| 279 locs->set_out(0, Location::RequiresRegister()); | 264 locs->set_out(0, Location::RequiresRegister()); |
| 280 break; | 265 break; |
| 281 default: | 266 default: |
| 282 UNREACHABLE(); | 267 UNREACHABLE(); |
| 283 break; | 268 break; |
| 284 } | 269 } |
| 285 return locs; | 270 return locs; |
| 286 } | 271 } |
| 287 | 272 |
| 288 | |
| 289 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 273 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 290 // The register allocator drops constant definitions that have no uses. | 274 // The register allocator drops constant definitions that have no uses. |
| 291 if (!locs()->out(0).IsInvalid()) { | 275 if (!locs()->out(0).IsInvalid()) { |
| 292 switch (representation()) { | 276 switch (representation()) { |
| 293 case kUnboxedDouble: { | 277 case kUnboxedDouble: { |
| 294 XmmRegister result = locs()->out(0).fpu_reg(); | 278 XmmRegister result = locs()->out(0).fpu_reg(); |
| 295 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { | 279 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { |
| 296 __ xorps(result, result); | 280 __ xorps(result, result); |
| 297 } else { | 281 } else { |
| 298 __ LoadObject(TMP, value()); | 282 __ LoadObject(TMP, value()); |
| 299 __ movsd(result, FieldAddress(TMP, Double::value_offset())); | 283 __ movsd(result, FieldAddress(TMP, Double::value_offset())); |
| 300 } | 284 } |
| 301 break; | 285 break; |
| 302 } | 286 } |
| 303 case kUnboxedInt32: | 287 case kUnboxedInt32: |
| 304 __ movl(locs()->out(0).reg(), | 288 __ movl(locs()->out(0).reg(), |
| 305 Immediate(static_cast<int32_t>(Smi::Cast(value()).Value()))); | 289 Immediate(static_cast<int32_t>(Smi::Cast(value()).Value()))); |
| 306 break; | 290 break; |
| 307 default: | 291 default: |
| 308 UNREACHABLE(); | 292 UNREACHABLE(); |
| 309 } | 293 } |
| 310 } | 294 } |
| 311 } | 295 } |
| 312 | 296 |
| 313 | |
| 314 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 297 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
| 315 bool opt) const { | 298 bool opt) const { |
| 316 const intptr_t kNumInputs = 3; | 299 const intptr_t kNumInputs = 3; |
| 317 const intptr_t kNumTemps = 0; | 300 const intptr_t kNumTemps = 0; |
| 318 LocationSummary* summary = new (zone) | 301 LocationSummary* summary = new (zone) |
| 319 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 302 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 320 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. | 303 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. |
| 321 summary->set_in(1, Location::RegisterLocation(RDX)); // Instant. type args. | 304 summary->set_in(1, Location::RegisterLocation(RDX)); // Instant. type args. |
| 322 summary->set_in(2, Location::RegisterLocation(RCX)); // Function type args. | 305 summary->set_in(2, Location::RegisterLocation(RCX)); // Function type args. |
| 323 summary->set_out(0, Location::RegisterLocation(RAX)); | 306 summary->set_out(0, Location::RegisterLocation(RAX)); |
| 324 return summary; | 307 return summary; |
| 325 } | 308 } |
| 326 | 309 |
| 327 | |
| 328 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 310 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
| 329 bool opt) const { | 311 bool opt) const { |
| 330 const intptr_t kNumInputs = 1; | 312 const intptr_t kNumInputs = 1; |
| 331 const intptr_t kNumTemps = 0; | 313 const intptr_t kNumTemps = 0; |
| 332 LocationSummary* locs = new (zone) | 314 LocationSummary* locs = new (zone) |
| 333 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 315 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 334 locs->set_in(0, Location::RegisterLocation(RAX)); | 316 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 335 locs->set_out(0, Location::RegisterLocation(RAX)); | 317 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 336 return locs; | 318 return locs; |
| 337 } | 319 } |
| 338 | 320 |
| 339 | |
| 340 static void EmitAssertBoolean(Register reg, | 321 static void EmitAssertBoolean(Register reg, |
| 341 TokenPosition token_pos, | 322 TokenPosition token_pos, |
| 342 intptr_t deopt_id, | 323 intptr_t deopt_id, |
| 343 LocationSummary* locs, | 324 LocationSummary* locs, |
| 344 FlowGraphCompiler* compiler) { | 325 FlowGraphCompiler* compiler) { |
| 345 // Check that the type of the value is allowed in conditional context. | 326 // Check that the type of the value is allowed in conditional context. |
| 346 // Call the runtime if the object is not bool::true or bool::false. | 327 // Call the runtime if the object is not bool::true or bool::false. |
| 347 ASSERT(locs->always_calls()); | 328 ASSERT(locs->always_calls()); |
| 348 Label done; | 329 Label done; |
| 349 | 330 |
| 350 if (Isolate::Current()->type_checks()) { | 331 if (Isolate::Current()->type_checks()) { |
| 351 __ CompareObject(reg, Bool::True()); | 332 __ CompareObject(reg, Bool::True()); |
| 352 __ j(EQUAL, &done, Assembler::kNearJump); | 333 __ j(EQUAL, &done, Assembler::kNearJump); |
| 353 __ CompareObject(reg, Bool::False()); | 334 __ CompareObject(reg, Bool::False()); |
| 354 __ j(EQUAL, &done, Assembler::kNearJump); | 335 __ j(EQUAL, &done, Assembler::kNearJump); |
| 355 } else { | 336 } else { |
| 356 ASSERT(Isolate::Current()->asserts()); | 337 ASSERT(Isolate::Current()->asserts()); |
| 357 __ CompareObject(reg, Object::null_instance()); | 338 __ CompareObject(reg, Object::null_instance()); |
| 358 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 339 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 359 } | 340 } |
| 360 | 341 |
| 361 __ pushq(reg); // Push the source object. | 342 __ pushq(reg); // Push the source object. |
| 362 compiler->GenerateRuntimeCall(token_pos, deopt_id, | 343 compiler->GenerateRuntimeCall(token_pos, deopt_id, |
| 363 kNonBoolTypeErrorRuntimeEntry, 1, locs); | 344 kNonBoolTypeErrorRuntimeEntry, 1, locs); |
| 364 // We should never return here. | 345 // We should never return here. |
| 365 __ int3(); | 346 __ int3(); |
| 366 __ Bind(&done); | 347 __ Bind(&done); |
| 367 } | 348 } |
| 368 | 349 |
| 369 | |
| 370 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 350 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 371 Register obj = locs()->in(0).reg(); | 351 Register obj = locs()->in(0).reg(); |
| 372 Register result = locs()->out(0).reg(); | 352 Register result = locs()->out(0).reg(); |
| 373 | 353 |
| 374 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 354 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 375 ASSERT(obj == result); | 355 ASSERT(obj == result); |
| 376 } | 356 } |
| 377 | 357 |
| 378 | |
| 379 static Condition TokenKindToIntCondition(Token::Kind kind) { | 358 static Condition TokenKindToIntCondition(Token::Kind kind) { |
| 380 switch (kind) { | 359 switch (kind) { |
| 381 case Token::kEQ: | 360 case Token::kEQ: |
| 382 return EQUAL; | 361 return EQUAL; |
| 383 case Token::kNE: | 362 case Token::kNE: |
| 384 return NOT_EQUAL; | 363 return NOT_EQUAL; |
| 385 case Token::kLT: | 364 case Token::kLT: |
| 386 return LESS; | 365 return LESS; |
| 387 case Token::kGT: | 366 case Token::kGT: |
| 388 return GREATER; | 367 return GREATER; |
| 389 case Token::kLTE: | 368 case Token::kLTE: |
| 390 return LESS_EQUAL; | 369 return LESS_EQUAL; |
| 391 case Token::kGTE: | 370 case Token::kGTE: |
| 392 return GREATER_EQUAL; | 371 return GREATER_EQUAL; |
| 393 default: | 372 default: |
| 394 UNREACHABLE(); | 373 UNREACHABLE(); |
| 395 return OVERFLOW; | 374 return OVERFLOW; |
| 396 } | 375 } |
| 397 } | 376 } |
| 398 | 377 |
| 399 | |
| 400 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 378 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |
| 401 bool opt) const { | 379 bool opt) const { |
| 402 const intptr_t kNumInputs = 2; | 380 const intptr_t kNumInputs = 2; |
| 403 if (operation_cid() == kMintCid) { | 381 if (operation_cid() == kMintCid) { |
| 404 const intptr_t kNumTemps = 0; | 382 const intptr_t kNumTemps = 0; |
| 405 LocationSummary* locs = new (zone) | 383 LocationSummary* locs = new (zone) |
| 406 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 384 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 407 locs->set_in(0, Location::RequiresRegister()); | 385 locs->set_in(0, Location::RequiresRegister()); |
| 408 locs->set_in(1, Location::RequiresRegister()); | 386 locs->set_in(1, Location::RequiresRegister()); |
| 409 locs->set_out(0, Location::RequiresRegister()); | 387 locs->set_out(0, Location::RequiresRegister()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 429 locs->set_in(1, locs->in(0).IsConstant() | 407 locs->set_in(1, locs->in(0).IsConstant() |
| 430 ? Location::RequiresRegister() | 408 ? Location::RequiresRegister() |
| 431 : Location::RegisterOrConstant(right())); | 409 : Location::RegisterOrConstant(right())); |
| 432 locs->set_out(0, Location::RequiresRegister()); | 410 locs->set_out(0, Location::RequiresRegister()); |
| 433 return locs; | 411 return locs; |
| 434 } | 412 } |
| 435 UNREACHABLE(); | 413 UNREACHABLE(); |
| 436 return NULL; | 414 return NULL; |
| 437 } | 415 } |
| 438 | 416 |
| 439 | |
| 440 static void LoadValueCid(FlowGraphCompiler* compiler, | 417 static void LoadValueCid(FlowGraphCompiler* compiler, |
| 441 Register value_cid_reg, | 418 Register value_cid_reg, |
| 442 Register value_reg, | 419 Register value_reg, |
| 443 Label* value_is_smi = NULL) { | 420 Label* value_is_smi = NULL) { |
| 444 Label done; | 421 Label done; |
| 445 if (value_is_smi == NULL) { | 422 if (value_is_smi == NULL) { |
| 446 __ LoadImmediate(value_cid_reg, Immediate(kSmiCid)); | 423 __ LoadImmediate(value_cid_reg, Immediate(kSmiCid)); |
| 447 } | 424 } |
| 448 __ testq(value_reg, Immediate(kSmiTagMask)); | 425 __ testq(value_reg, Immediate(kSmiTagMask)); |
| 449 if (value_is_smi == NULL) { | 426 if (value_is_smi == NULL) { |
| 450 __ j(ZERO, &done, Assembler::kNearJump); | 427 __ j(ZERO, &done, Assembler::kNearJump); |
| 451 } else { | 428 } else { |
| 452 __ j(ZERO, value_is_smi); | 429 __ j(ZERO, value_is_smi); |
| 453 } | 430 } |
| 454 __ LoadClassId(value_cid_reg, value_reg); | 431 __ LoadClassId(value_cid_reg, value_reg); |
| 455 __ Bind(&done); | 432 __ Bind(&done); |
| 456 } | 433 } |
| 457 | 434 |
| 458 | |
| 459 static Condition FlipCondition(Condition condition) { | 435 static Condition FlipCondition(Condition condition) { |
| 460 switch (condition) { | 436 switch (condition) { |
| 461 case EQUAL: | 437 case EQUAL: |
| 462 return EQUAL; | 438 return EQUAL; |
| 463 case NOT_EQUAL: | 439 case NOT_EQUAL: |
| 464 return NOT_EQUAL; | 440 return NOT_EQUAL; |
| 465 case LESS: | 441 case LESS: |
| 466 return GREATER; | 442 return GREATER; |
| 467 case LESS_EQUAL: | 443 case LESS_EQUAL: |
| 468 return GREATER_EQUAL; | 444 return GREATER_EQUAL; |
| 469 case GREATER: | 445 case GREATER: |
| 470 return LESS; | 446 return LESS; |
| 471 case GREATER_EQUAL: | 447 case GREATER_EQUAL: |
| 472 return LESS_EQUAL; | 448 return LESS_EQUAL; |
| 473 case BELOW: | 449 case BELOW: |
| 474 return ABOVE; | 450 return ABOVE; |
| 475 case BELOW_EQUAL: | 451 case BELOW_EQUAL: |
| 476 return ABOVE_EQUAL; | 452 return ABOVE_EQUAL; |
| 477 case ABOVE: | 453 case ABOVE: |
| 478 return BELOW; | 454 return BELOW; |
| 479 case ABOVE_EQUAL: | 455 case ABOVE_EQUAL: |
| 480 return BELOW_EQUAL; | 456 return BELOW_EQUAL; |
| 481 default: | 457 default: |
| 482 UNIMPLEMENTED(); | 458 UNIMPLEMENTED(); |
| 483 return EQUAL; | 459 return EQUAL; |
| 484 } | 460 } |
| 485 } | 461 } |
| 486 | 462 |
| 487 | |
| 488 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 463 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 489 Condition true_condition, | 464 Condition true_condition, |
| 490 BranchLabels labels) { | 465 BranchLabels labels) { |
| 491 if (labels.fall_through == labels.false_label) { | 466 if (labels.fall_through == labels.false_label) { |
| 492 // If the next block is the false successor, fall through to it. | 467 // If the next block is the false successor, fall through to it. |
| 493 __ j(true_condition, labels.true_label); | 468 __ j(true_condition, labels.true_label); |
| 494 } else { | 469 } else { |
| 495 // If the next block is not the false successor, branch to it. | 470 // If the next block is not the false successor, branch to it. |
| 496 Condition false_condition = NegateCondition(true_condition); | 471 Condition false_condition = NegateCondition(true_condition); |
| 497 __ j(false_condition, labels.false_label); | 472 __ j(false_condition, labels.false_label); |
| 498 | 473 |
| 499 // Fall through or jump to the true successor. | 474 // Fall through or jump to the true successor. |
| 500 if (labels.fall_through != labels.true_label) { | 475 if (labels.fall_through != labels.true_label) { |
| 501 __ jmp(labels.true_label); | 476 __ jmp(labels.true_label); |
| 502 } | 477 } |
| 503 } | 478 } |
| 504 } | 479 } |
| 505 | 480 |
| 506 | |
| 507 static Condition EmitInt64ComparisonOp(FlowGraphCompiler* compiler, | 481 static Condition EmitInt64ComparisonOp(FlowGraphCompiler* compiler, |
| 508 const LocationSummary& locs, | 482 const LocationSummary& locs, |
| 509 Token::Kind kind) { | 483 Token::Kind kind) { |
| 510 Location left = locs.in(0); | 484 Location left = locs.in(0); |
| 511 Location right = locs.in(1); | 485 Location right = locs.in(1); |
| 512 ASSERT(!left.IsConstant() || !right.IsConstant()); | 486 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 513 | 487 |
| 514 Condition true_condition = TokenKindToIntCondition(kind); | 488 Condition true_condition = TokenKindToIntCondition(kind); |
| 515 | 489 |
| 516 if (left.IsConstant()) { | 490 if (left.IsConstant()) { |
| 517 __ CompareObject(right.reg(), left.constant()); | 491 __ CompareObject(right.reg(), left.constant()); |
| 518 true_condition = FlipCondition(true_condition); | 492 true_condition = FlipCondition(true_condition); |
| 519 } else if (right.IsConstant()) { | 493 } else if (right.IsConstant()) { |
| 520 __ CompareObject(left.reg(), right.constant()); | 494 __ CompareObject(left.reg(), right.constant()); |
| 521 } else if (right.IsStackSlot()) { | 495 } else if (right.IsStackSlot()) { |
| 522 __ cmpq(left.reg(), right.ToStackSlotAddress()); | 496 __ cmpq(left.reg(), right.ToStackSlotAddress()); |
| 523 } else { | 497 } else { |
| 524 __ cmpq(left.reg(), right.reg()); | 498 __ cmpq(left.reg(), right.reg()); |
| 525 } | 499 } |
| 526 return true_condition; | 500 return true_condition; |
| 527 } | 501 } |
| 528 | 502 |
| 529 | |
| 530 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 503 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 531 switch (kind) { | 504 switch (kind) { |
| 532 case Token::kEQ: | 505 case Token::kEQ: |
| 533 return EQUAL; | 506 return EQUAL; |
| 534 case Token::kNE: | 507 case Token::kNE: |
| 535 return NOT_EQUAL; | 508 return NOT_EQUAL; |
| 536 case Token::kLT: | 509 case Token::kLT: |
| 537 return BELOW; | 510 return BELOW; |
| 538 case Token::kGT: | 511 case Token::kGT: |
| 539 return ABOVE; | 512 return ABOVE; |
| 540 case Token::kLTE: | 513 case Token::kLTE: |
| 541 return BELOW_EQUAL; | 514 return BELOW_EQUAL; |
| 542 case Token::kGTE: | 515 case Token::kGTE: |
| 543 return ABOVE_EQUAL; | 516 return ABOVE_EQUAL; |
| 544 default: | 517 default: |
| 545 UNREACHABLE(); | 518 UNREACHABLE(); |
| 546 return OVERFLOW; | 519 return OVERFLOW; |
| 547 } | 520 } |
| 548 } | 521 } |
| 549 | 522 |
| 550 | |
| 551 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 523 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 552 const LocationSummary& locs, | 524 const LocationSummary& locs, |
| 553 Token::Kind kind, | 525 Token::Kind kind, |
| 554 BranchLabels labels) { | 526 BranchLabels labels) { |
| 555 XmmRegister left = locs.in(0).fpu_reg(); | 527 XmmRegister left = locs.in(0).fpu_reg(); |
| 556 XmmRegister right = locs.in(1).fpu_reg(); | 528 XmmRegister right = locs.in(1).fpu_reg(); |
| 557 | 529 |
| 558 __ comisd(left, right); | 530 __ comisd(left, right); |
| 559 | 531 |
| 560 Condition true_condition = TokenKindToDoubleCondition(kind); | 532 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 561 Label* nan_result = | 533 Label* nan_result = |
| 562 (true_condition == NOT_EQUAL) ? labels.true_label : labels.false_label; | 534 (true_condition == NOT_EQUAL) ? labels.true_label : labels.false_label; |
| 563 __ j(PARITY_EVEN, nan_result); | 535 __ j(PARITY_EVEN, nan_result); |
| 564 return true_condition; | 536 return true_condition; |
| 565 } | 537 } |
| 566 | 538 |
| 567 | |
| 568 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 539 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 569 BranchLabels labels) { | 540 BranchLabels labels) { |
| 570 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { | 541 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
| 571 return EmitInt64ComparisonOp(compiler, *locs(), kind()); | 542 return EmitInt64ComparisonOp(compiler, *locs(), kind()); |
| 572 } else { | 543 } else { |
| 573 ASSERT(operation_cid() == kDoubleCid); | 544 ASSERT(operation_cid() == kDoubleCid); |
| 574 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 545 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 575 } | 546 } |
| 576 } | 547 } |
| 577 | 548 |
| 578 | |
| 579 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 549 void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 580 Label is_true, is_false; | 550 Label is_true, is_false; |
| 581 BranchLabels labels = {&is_true, &is_false, &is_false}; | 551 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 582 Condition true_condition = EmitComparisonCode(compiler, labels); | 552 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 583 if (true_condition != INVALID_CONDITION) { | 553 if (true_condition != INVALID_CONDITION) { |
| 584 EmitBranchOnCondition(compiler, true_condition, labels); | 554 EmitBranchOnCondition(compiler, true_condition, labels); |
| 585 } | 555 } |
| 586 | 556 |
| 587 Register result = locs()->out(0).reg(); | 557 Register result = locs()->out(0).reg(); |
| 588 Label done; | 558 Label done; |
| 589 __ Bind(&is_false); | 559 __ Bind(&is_false); |
| 590 __ LoadObject(result, Bool::False()); | 560 __ LoadObject(result, Bool::False()); |
| 591 __ jmp(&done); | 561 __ jmp(&done); |
| 592 __ Bind(&is_true); | 562 __ Bind(&is_true); |
| 593 __ LoadObject(result, Bool::True()); | 563 __ LoadObject(result, Bool::True()); |
| 594 __ Bind(&done); | 564 __ Bind(&done); |
| 595 } | 565 } |
| 596 | 566 |
| 597 | |
| 598 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 567 void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 599 BranchInstr* branch) { | 568 BranchInstr* branch) { |
| 600 BranchLabels labels = compiler->CreateBranchLabels(branch); | 569 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 601 Condition true_condition = EmitComparisonCode(compiler, labels); | 570 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 602 if (true_condition != INVALID_CONDITION) { | 571 if (true_condition != INVALID_CONDITION) { |
| 603 EmitBranchOnCondition(compiler, true_condition, labels); | 572 EmitBranchOnCondition(compiler, true_condition, labels); |
| 604 } | 573 } |
| 605 } | 574 } |
| 606 | 575 |
| 607 | |
| 608 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 576 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 609 const intptr_t kNumInputs = 2; | 577 const intptr_t kNumInputs = 2; |
| 610 const intptr_t kNumTemps = 0; | 578 const intptr_t kNumTemps = 0; |
| 611 LocationSummary* locs = new (zone) | 579 LocationSummary* locs = new (zone) |
| 612 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 580 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 613 locs->set_in(0, Location::RequiresRegister()); | 581 locs->set_in(0, Location::RequiresRegister()); |
| 614 // Only one input can be a constant operand. The case of two constant | 582 // Only one input can be a constant operand. The case of two constant |
| 615 // operands should be handled by constant propagation. | 583 // operands should be handled by constant propagation. |
| 616 locs->set_in(1, Location::RegisterOrConstant(right())); | 584 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 617 return locs; | 585 return locs; |
| 618 } | 586 } |
| 619 | 587 |
| 620 | |
| 621 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 588 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 622 BranchLabels labels) { | 589 BranchLabels labels) { |
| 623 Register left_reg = locs()->in(0).reg(); | 590 Register left_reg = locs()->in(0).reg(); |
| 624 Location right = locs()->in(1); | 591 Location right = locs()->in(1); |
| 625 if (right.IsConstant()) { | 592 if (right.IsConstant()) { |
| 626 ASSERT(right.constant().IsSmi()); | 593 ASSERT(right.constant().IsSmi()); |
| 627 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); | 594 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); |
| 628 __ TestImmediate(left_reg, Immediate(imm)); | 595 __ TestImmediate(left_reg, Immediate(imm)); |
| 629 } else { | 596 } else { |
| 630 __ testq(left_reg, right.reg()); | 597 __ testq(left_reg, right.reg()); |
| 631 } | 598 } |
| 632 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; | 599 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; |
| 633 return true_condition; | 600 return true_condition; |
| 634 } | 601 } |
| 635 | 602 |
| 636 | |
| 637 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 603 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
| 638 bool opt) const { | 604 bool opt) const { |
| 639 const intptr_t kNumInputs = 1; | 605 const intptr_t kNumInputs = 1; |
| 640 const intptr_t kNumTemps = 1; | 606 const intptr_t kNumTemps = 1; |
| 641 LocationSummary* locs = new (zone) | 607 LocationSummary* locs = new (zone) |
| 642 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 608 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 643 locs->set_in(0, Location::RequiresRegister()); | 609 locs->set_in(0, Location::RequiresRegister()); |
| 644 locs->set_temp(0, Location::RequiresRegister()); | 610 locs->set_temp(0, Location::RequiresRegister()); |
| 645 locs->set_out(0, Location::RequiresRegister()); | 611 locs->set_out(0, Location::RequiresRegister()); |
| 646 return locs; | 612 return locs; |
| 647 } | 613 } |
| 648 | 614 |
| 649 | |
| 650 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 615 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 651 BranchLabels labels) { | 616 BranchLabels labels) { |
| 652 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 617 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
| 653 Register val_reg = locs()->in(0).reg(); | 618 Register val_reg = locs()->in(0).reg(); |
| 654 Register cid_reg = locs()->temp(0).reg(); | 619 Register cid_reg = locs()->temp(0).reg(); |
| 655 | 620 |
| 656 Label* deopt = | 621 Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub( |
| 657 CanDeoptimize() | 622 deopt_id(), ICData::kDeoptTestCids, |
| 658 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, | 623 licm_hoisted_ ? ICData::kHoisted : 0) |
| 659 licm_hoisted_ ? ICData::kHoisted : 0) | 624 : NULL; |
| 660 : NULL; | |
| 661 | 625 |
| 662 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 626 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
| 663 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 627 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
| 664 ASSERT(data[0] == kSmiCid); | 628 ASSERT(data[0] == kSmiCid); |
| 665 bool result = data[1] == true_result; | 629 bool result = data[1] == true_result; |
| 666 __ testq(val_reg, Immediate(kSmiTagMask)); | 630 __ testq(val_reg, Immediate(kSmiTagMask)); |
| 667 __ j(ZERO, result ? labels.true_label : labels.false_label); | 631 __ j(ZERO, result ? labels.true_label : labels.false_label); |
| 668 __ LoadClassId(cid_reg, val_reg); | 632 __ LoadClassId(cid_reg, val_reg); |
| 669 for (intptr_t i = 2; i < data.length(); i += 2) { | 633 for (intptr_t i = 2; i < data.length(); i += 2) { |
| 670 const intptr_t test_cid = data[i]; | 634 const intptr_t test_cid = data[i]; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 683 __ jmp(target); | 647 __ jmp(target); |
| 684 } | 648 } |
| 685 } else { | 649 } else { |
| 686 __ jmp(deopt); | 650 __ jmp(deopt); |
| 687 } | 651 } |
| 688 // Dummy result as this method already did the jump, there's no need | 652 // Dummy result as this method already did the jump, there's no need |
| 689 // for the caller to branch on a condition. | 653 // for the caller to branch on a condition. |
| 690 return INVALID_CONDITION; | 654 return INVALID_CONDITION; |
| 691 } | 655 } |
| 692 | 656 |
| 693 | |
| 694 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 657 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
| 695 bool opt) const { | 658 bool opt) const { |
| 696 const intptr_t kNumInputs = 2; | 659 const intptr_t kNumInputs = 2; |
| 697 const intptr_t kNumTemps = 0; | 660 const intptr_t kNumTemps = 0; |
| 698 if (operation_cid() == kDoubleCid) { | 661 if (operation_cid() == kDoubleCid) { |
| 699 LocationSummary* summary = new (zone) | 662 LocationSummary* summary = new (zone) |
| 700 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 663 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 701 summary->set_in(0, Location::RequiresFpuRegister()); | 664 summary->set_in(0, Location::RequiresFpuRegister()); |
| 702 summary->set_in(1, Location::RequiresFpuRegister()); | 665 summary->set_in(1, Location::RequiresFpuRegister()); |
| 703 summary->set_out(0, Location::RequiresRegister()); | 666 summary->set_out(0, Location::RequiresRegister()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 716 summary->set_in(0, Location::RegisterOrConstant(left())); | 679 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 717 // Only one input can be a constant operand. The case of two constant | 680 // Only one input can be a constant operand. The case of two constant |
| 718 // operands should be handled by constant propagation. | 681 // operands should be handled by constant propagation. |
| 719 summary->set_in(1, summary->in(0).IsConstant() | 682 summary->set_in(1, summary->in(0).IsConstant() |
| 720 ? Location::RequiresRegister() | 683 ? Location::RequiresRegister() |
| 721 : Location::RegisterOrConstant(right())); | 684 : Location::RegisterOrConstant(right())); |
| 722 summary->set_out(0, Location::RequiresRegister()); | 685 summary->set_out(0, Location::RequiresRegister()); |
| 723 return summary; | 686 return summary; |
| 724 } | 687 } |
| 725 | 688 |
| 726 | |
| 727 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 689 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 728 BranchLabels labels) { | 690 BranchLabels labels) { |
| 729 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { | 691 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
| 730 return EmitInt64ComparisonOp(compiler, *locs(), kind()); | 692 return EmitInt64ComparisonOp(compiler, *locs(), kind()); |
| 731 } else { | 693 } else { |
| 732 ASSERT(operation_cid() == kDoubleCid); | 694 ASSERT(operation_cid() == kDoubleCid); |
| 733 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 695 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 734 } | 696 } |
| 735 } | 697 } |
| 736 | 698 |
| 737 | |
| 738 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, | 699 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, |
| 739 bool opt) const { | 700 bool opt) const { |
| 740 return MakeCallSummary(zone); | 701 return MakeCallSummary(zone); |
| 741 } | 702 } |
| 742 | 703 |
| 743 | |
| 744 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 704 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 745 SetupNative(); | 705 SetupNative(); |
| 746 Register result = locs()->out(0).reg(); | 706 Register result = locs()->out(0).reg(); |
| 747 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 707 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
| 748 | 708 |
| 749 // Push the result place holder initialized to NULL. | 709 // Push the result place holder initialized to NULL. |
| 750 __ PushObject(Object::null_object()); | 710 __ PushObject(Object::null_object()); |
| 751 // Pass a pointer to the first argument in RAX. | 711 // Pass a pointer to the first argument in RAX. |
| 752 if (!function().HasOptionalParameters()) { | 712 if (!function().HasOptionalParameters()) { |
| 753 __ leaq(RAX, | 713 __ leaq(RAX, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 773 stub_entry = StubCode::CallNoScopeNative_entry(); | 733 stub_entry = StubCode::CallNoScopeNative_entry(); |
| 774 } | 734 } |
| 775 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); | 735 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); |
| 776 __ LoadNativeEntry(RBX, &label, kNotPatchable); | 736 __ LoadNativeEntry(RBX, &label, kNotPatchable); |
| 777 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, | 737 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, |
| 778 locs()); | 738 locs()); |
| 779 } | 739 } |
| 780 __ popq(result); | 740 __ popq(result); |
| 781 } | 741 } |
| 782 | 742 |
| 783 | |
| 784 static bool CanBeImmediateIndex(Value* index, intptr_t cid) { | 743 static bool CanBeImmediateIndex(Value* index, intptr_t cid) { |
| 785 if (!index->definition()->IsConstant()) return false; | 744 if (!index->definition()->IsConstant()) return false; |
| 786 const Object& constant = index->definition()->AsConstant()->value(); | 745 const Object& constant = index->definition()->AsConstant()->value(); |
| 787 if (!constant.IsSmi()) return false; | 746 if (!constant.IsSmi()) return false; |
| 788 const Smi& smi_const = Smi::Cast(constant); | 747 const Smi& smi_const = Smi::Cast(constant); |
| 789 const intptr_t scale = Instance::ElementSizeFor(cid); | 748 const intptr_t scale = Instance::ElementSizeFor(cid); |
| 790 const intptr_t data_offset = Instance::DataOffsetFor(cid); | 749 const intptr_t data_offset = Instance::DataOffsetFor(cid); |
| 791 const int64_t disp = smi_const.AsInt64Value() * scale + data_offset; | 750 const int64_t disp = smi_const.AsInt64Value() * scale + data_offset; |
| 792 return Utils::IsInt(32, disp); | 751 return Utils::IsInt(32, disp); |
| 793 } | 752 } |
| 794 | 753 |
| 795 | |
| 796 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 754 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |
| 797 Zone* zone, | 755 Zone* zone, |
| 798 bool opt) const { | 756 bool opt) const { |
| 799 const intptr_t kNumInputs = 1; | 757 const intptr_t kNumInputs = 1; |
| 800 // TODO(fschneider): Allow immediate operands for the char code. | 758 // TODO(fschneider): Allow immediate operands for the char code. |
| 801 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 759 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 802 LocationSummary::kNoCall); | 760 LocationSummary::kNoCall); |
| 803 } | 761 } |
| 804 | 762 |
| 805 | |
| 806 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 763 void OneByteStringFromCharCodeInstr::EmitNativeCode( |
| 807 FlowGraphCompiler* compiler) { | 764 FlowGraphCompiler* compiler) { |
| 808 ASSERT(compiler->is_optimizing()); | 765 ASSERT(compiler->is_optimizing()); |
| 809 Register char_code = locs()->in(0).reg(); | 766 Register char_code = locs()->in(0).reg(); |
| 810 Register result = locs()->out(0).reg(); | 767 Register result = locs()->out(0).reg(); |
| 811 | 768 |
| 812 __ movq(result, Address(THR, Thread::predefined_symbols_address_offset())); | 769 __ movq(result, Address(THR, Thread::predefined_symbols_address_offset())); |
| 813 __ movq(result, Address(result, char_code, | 770 __ movq(result, Address(result, char_code, |
| 814 TIMES_HALF_WORD_SIZE, // Char code is a smi. | 771 TIMES_HALF_WORD_SIZE, // Char code is a smi. |
| 815 Symbols::kNullCharCodeSymbolOffset * kWordSize)); | 772 Symbols::kNullCharCodeSymbolOffset * kWordSize)); |
| 816 } | 773 } |
| 817 | 774 |
| 818 | |
| 819 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 775 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
| 820 bool opt) const { | 776 bool opt) const { |
| 821 const intptr_t kNumInputs = 1; | 777 const intptr_t kNumInputs = 1; |
| 822 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 778 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 823 LocationSummary::kNoCall); | 779 LocationSummary::kNoCall); |
| 824 } | 780 } |
| 825 | 781 |
| 826 | |
| 827 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 782 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 828 ASSERT(cid_ == kOneByteStringCid); | 783 ASSERT(cid_ == kOneByteStringCid); |
| 829 Register str = locs()->in(0).reg(); | 784 Register str = locs()->in(0).reg(); |
| 830 Register result = locs()->out(0).reg(); | 785 Register result = locs()->out(0).reg(); |
| 831 Label is_one, done; | 786 Label is_one, done; |
| 832 __ movq(result, FieldAddress(str, String::length_offset())); | 787 __ movq(result, FieldAddress(str, String::length_offset())); |
| 833 __ cmpq(result, Immediate(Smi::RawValue(1))); | 788 __ cmpq(result, Immediate(Smi::RawValue(1))); |
| 834 __ j(EQUAL, &is_one, Assembler::kNearJump); | 789 __ j(EQUAL, &is_one, Assembler::kNearJump); |
| 835 __ movq(result, Immediate(Smi::RawValue(-1))); | 790 __ movq(result, Immediate(Smi::RawValue(-1))); |
| 836 __ jmp(&done); | 791 __ jmp(&done); |
| 837 __ Bind(&is_one); | 792 __ Bind(&is_one); |
| 838 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); | 793 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); |
| 839 __ SmiTag(result); | 794 __ SmiTag(result); |
| 840 __ Bind(&done); | 795 __ Bind(&done); |
| 841 } | 796 } |
| 842 | 797 |
| 843 | |
| 844 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 798 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |
| 845 bool opt) const { | 799 bool opt) const { |
| 846 const intptr_t kNumInputs = 1; | 800 const intptr_t kNumInputs = 1; |
| 847 const intptr_t kNumTemps = 0; | 801 const intptr_t kNumTemps = 0; |
| 848 LocationSummary* summary = new (zone) | 802 LocationSummary* summary = new (zone) |
| 849 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 803 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 850 summary->set_in(0, Location::RegisterLocation(RAX)); | 804 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 851 summary->set_out(0, Location::RegisterLocation(RAX)); | 805 summary->set_out(0, Location::RegisterLocation(RAX)); |
| 852 return summary; | 806 return summary; |
| 853 } | 807 } |
| 854 | 808 |
| 855 | |
| 856 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 809 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 857 Register array = locs()->in(0).reg(); | 810 Register array = locs()->in(0).reg(); |
| 858 __ pushq(array); | 811 __ pushq(array); |
| 859 const int kTypeArgsLen = 0; | 812 const int kTypeArgsLen = 0; |
| 860 const int kNumberOfArguments = 1; | 813 const int kNumberOfArguments = 1; |
| 861 const Array& kNoArgumentNames = Object::null_array(); | 814 const Array& kNoArgumentNames = Object::null_array(); |
| 862 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); | 815 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); |
| 863 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), | 816 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), |
| 864 args_info, locs(), ICData::Handle()); | 817 args_info, locs(), ICData::Handle()); |
| 865 ASSERT(locs()->out(0).reg() == RAX); | 818 ASSERT(locs()->out(0).reg() == RAX); |
| 866 } | 819 } |
| 867 | 820 |
| 868 | |
| 869 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 821 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |
| 870 bool opt) const { | 822 bool opt) const { |
| 871 const intptr_t kNumInputs = 1; | 823 const intptr_t kNumInputs = 1; |
| 872 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 824 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 873 LocationSummary::kNoCall); | 825 LocationSummary::kNoCall); |
| 874 } | 826 } |
| 875 | 827 |
| 876 | |
| 877 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 828 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 878 Register obj = locs()->in(0).reg(); | 829 Register obj = locs()->in(0).reg(); |
| 879 Register result = locs()->out(0).reg(); | 830 Register result = locs()->out(0).reg(); |
| 880 if (object()->definition()->representation() == kUntagged) { | 831 if (object()->definition()->representation() == kUntagged) { |
| 881 __ movq(result, Address(obj, offset())); | 832 __ movq(result, Address(obj, offset())); |
| 882 } else { | 833 } else { |
| 883 ASSERT(object()->definition()->representation() == kTagged); | 834 ASSERT(object()->definition()->representation() == kTagged); |
| 884 __ movq(result, FieldAddress(obj, offset())); | 835 __ movq(result, FieldAddress(obj, offset())); |
| 885 } | 836 } |
| 886 } | 837 } |
| 887 | 838 |
| 888 | |
| 889 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 839 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |
| 890 bool opt) const { | 840 bool opt) const { |
| 891 const intptr_t kNumInputs = 1; | 841 const intptr_t kNumInputs = 1; |
| 892 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), | 842 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 893 LocationSummary::kNoCall); | 843 LocationSummary::kNoCall); |
| 894 } | 844 } |
| 895 | 845 |
| 896 | |
| 897 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 846 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 898 const Register object = locs()->in(0).reg(); | 847 const Register object = locs()->in(0).reg(); |
| 899 const Register result = locs()->out(0).reg(); | 848 const Register result = locs()->out(0).reg(); |
| 900 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 849 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |
| 901 if (CompileType::Smi().IsAssignableTo(value_type) || | 850 if (CompileType::Smi().IsAssignableTo(value_type) || |
| 902 value_type.IsTypeParameter()) { | 851 value_type.IsTypeParameter()) { |
| 903 // We don't use Assembler::LoadTaggedClassIdMayBeSmi() here---which uses | 852 // We don't use Assembler::LoadTaggedClassIdMayBeSmi() here---which uses |
| 904 // a conditional move instead---because it is slower, probably due to | 853 // a conditional move instead---because it is slower, probably due to |
| 905 // branch prediction usually working just fine in this case. | 854 // branch prediction usually working just fine in this case. |
| 906 Label load, done; | 855 Label load, done; |
| 907 __ testq(object, Immediate(kSmiTagMask)); | 856 __ testq(object, Immediate(kSmiTagMask)); |
| 908 __ j(NOT_ZERO, &load, Assembler::kNearJump); | 857 __ j(NOT_ZERO, &load, Assembler::kNearJump); |
| 909 __ LoadImmediate(result, Immediate(Smi::RawValue(kSmiCid))); | 858 __ LoadImmediate(result, Immediate(Smi::RawValue(kSmiCid))); |
| 910 __ jmp(&done); | 859 __ jmp(&done); |
| 911 __ Bind(&load); | 860 __ Bind(&load); |
| 912 __ LoadClassId(result, object); | 861 __ LoadClassId(result, object); |
| 913 __ SmiTag(result); | 862 __ SmiTag(result); |
| 914 __ Bind(&done); | 863 __ Bind(&done); |
| 915 } else { | 864 } else { |
| 916 __ LoadClassId(result, object); | 865 __ LoadClassId(result, object); |
| 917 __ SmiTag(result); | 866 __ SmiTag(result); |
| 918 } | 867 } |
| 919 } | 868 } |
| 920 | 869 |
| 921 | |
| 922 CompileType LoadIndexedInstr::ComputeType() const { | 870 CompileType LoadIndexedInstr::ComputeType() const { |
| 923 switch (class_id_) { | 871 switch (class_id_) { |
| 924 case kArrayCid: | 872 case kArrayCid: |
| 925 case kImmutableArrayCid: | 873 case kImmutableArrayCid: |
| 926 return CompileType::Dynamic(); | 874 return CompileType::Dynamic(); |
| 927 | 875 |
| 928 case kTypedDataFloat32ArrayCid: | 876 case kTypedDataFloat32ArrayCid: |
| 929 case kTypedDataFloat64ArrayCid: | 877 case kTypedDataFloat64ArrayCid: |
| 930 return CompileType::FromCid(kDoubleCid); | 878 return CompileType::FromCid(kDoubleCid); |
| 931 case kTypedDataFloat32x4ArrayCid: | 879 case kTypedDataFloat32x4ArrayCid: |
| (...skipping 20 matching lines...) Expand all Loading... |
| 952 | 900 |
| 953 case kTypedDataInt64ArrayCid: | 901 case kTypedDataInt64ArrayCid: |
| 954 return CompileType::Int(); | 902 return CompileType::Int(); |
| 955 | 903 |
| 956 default: | 904 default: |
| 957 UNIMPLEMENTED(); | 905 UNIMPLEMENTED(); |
| 958 return CompileType::Dynamic(); | 906 return CompileType::Dynamic(); |
| 959 } | 907 } |
| 960 } | 908 } |
| 961 | 909 |
| 962 | |
| 963 Representation LoadIndexedInstr::representation() const { | 910 Representation LoadIndexedInstr::representation() const { |
| 964 switch (class_id_) { | 911 switch (class_id_) { |
| 965 case kArrayCid: | 912 case kArrayCid: |
| 966 case kImmutableArrayCid: | 913 case kImmutableArrayCid: |
| 967 case kTypedDataInt8ArrayCid: | 914 case kTypedDataInt8ArrayCid: |
| 968 case kTypedDataUint8ArrayCid: | 915 case kTypedDataUint8ArrayCid: |
| 969 case kTypedDataUint8ClampedArrayCid: | 916 case kTypedDataUint8ClampedArrayCid: |
| 970 case kExternalTypedDataUint8ArrayCid: | 917 case kExternalTypedDataUint8ArrayCid: |
| 971 case kExternalTypedDataUint8ClampedArrayCid: | 918 case kExternalTypedDataUint8ClampedArrayCid: |
| 972 case kTypedDataInt16ArrayCid: | 919 case kTypedDataInt16ArrayCid: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 990 case kTypedDataFloat32x4ArrayCid: | 937 case kTypedDataFloat32x4ArrayCid: |
| 991 return kUnboxedFloat32x4; | 938 return kUnboxedFloat32x4; |
| 992 case kTypedDataFloat64x2ArrayCid: | 939 case kTypedDataFloat64x2ArrayCid: |
| 993 return kUnboxedFloat64x2; | 940 return kUnboxedFloat64x2; |
| 994 default: | 941 default: |
| 995 UNIMPLEMENTED(); | 942 UNIMPLEMENTED(); |
| 996 return kTagged; | 943 return kTagged; |
| 997 } | 944 } |
| 998 } | 945 } |
| 999 | 946 |
| 1000 | |
| 1001 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 947 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1002 bool opt) const { | 948 bool opt) const { |
| 1003 const intptr_t kNumInputs = 2; | 949 const intptr_t kNumInputs = 2; |
| 1004 const intptr_t kNumTemps = 0; | 950 const intptr_t kNumTemps = 0; |
| 1005 LocationSummary* locs = new (zone) | 951 LocationSummary* locs = new (zone) |
| 1006 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 952 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1007 locs->set_in(0, Location::RequiresRegister()); | 953 locs->set_in(0, Location::RequiresRegister()); |
| 1008 // The smi index is either untagged (element size == 1), or it is left smi | 954 // The smi index is either untagged (element size == 1), or it is left smi |
| 1009 // tagged (for all element sizes > 1). | 955 // tagged (for all element sizes > 1). |
| 1010 if (index_scale() == 1) { | 956 if (index_scale() == 1) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1022 (representation() == kUnboxedFloat32x4) || | 968 (representation() == kUnboxedFloat32x4) || |
| 1023 (representation() == kUnboxedInt32x4) || | 969 (representation() == kUnboxedInt32x4) || |
| 1024 (representation() == kUnboxedFloat64x2)) { | 970 (representation() == kUnboxedFloat64x2)) { |
| 1025 locs->set_out(0, Location::RequiresFpuRegister()); | 971 locs->set_out(0, Location::RequiresFpuRegister()); |
| 1026 } else { | 972 } else { |
| 1027 locs->set_out(0, Location::RequiresRegister()); | 973 locs->set_out(0, Location::RequiresRegister()); |
| 1028 } | 974 } |
| 1029 return locs; | 975 return locs; |
| 1030 } | 976 } |
| 1031 | 977 |
| 1032 | |
| 1033 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 978 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1034 // The array register points to the backing store for external arrays. | 979 // The array register points to the backing store for external arrays. |
| 1035 const Register array = locs()->in(0).reg(); | 980 const Register array = locs()->in(0).reg(); |
| 1036 const Location index = locs()->in(1); | 981 const Location index = locs()->in(1); |
| 1037 | 982 |
| 1038 Address element_address = | 983 Address element_address = |
| 1039 index.IsRegister() | 984 index.IsRegister() |
| 1040 ? Assembler::ElementAddressForRegIndex( | 985 ? Assembler::ElementAddressForRegIndex( |
| 1041 IsExternal(), class_id(), index_scale(), array, index.reg()) | 986 IsExternal(), class_id(), index_scale(), array, index.reg()) |
| 1042 : Assembler::ElementAddressForIntIndex( | 987 : Assembler::ElementAddressForIntIndex( |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1127 __ movzxw(result, element_address); | 1072 __ movzxw(result, element_address); |
| 1128 __ SmiTag(result); | 1073 __ SmiTag(result); |
| 1129 break; | 1074 break; |
| 1130 default: | 1075 default: |
| 1131 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); | 1076 ASSERT((class_id() == kArrayCid) || (class_id() == kImmutableArrayCid)); |
| 1132 __ movq(result, element_address); | 1077 __ movq(result, element_address); |
| 1133 break; | 1078 break; |
| 1134 } | 1079 } |
| 1135 } | 1080 } |
| 1136 | 1081 |
| 1137 | |
| 1138 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 1082 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |
| 1139 bool opt) const { | 1083 bool opt) const { |
| 1140 const intptr_t kNumInputs = 2; | 1084 const intptr_t kNumInputs = 2; |
| 1141 const intptr_t kNumTemps = 0; | 1085 const intptr_t kNumTemps = 0; |
| 1142 LocationSummary* summary = new (zone) | 1086 LocationSummary* summary = new (zone) |
| 1143 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1087 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1144 summary->set_in(0, Location::RequiresRegister()); | 1088 summary->set_in(0, Location::RequiresRegister()); |
| 1145 // The smi index is either untagged (element size == 1), or it is left smi | 1089 // The smi index is either untagged (element size == 1), or it is left smi |
| 1146 // tagged (for all element sizes > 1). | 1090 // tagged (for all element sizes > 1). |
| 1147 summary->set_in(1, index_scale() == 1 ? Location::WritableRegister() | 1091 summary->set_in(1, index_scale() == 1 ? Location::WritableRegister() |
| 1148 : Location::RequiresRegister()); | 1092 : Location::RequiresRegister()); |
| 1149 summary->set_out(0, Location::RequiresRegister()); | 1093 summary->set_out(0, Location::RequiresRegister()); |
| 1150 return summary; | 1094 return summary; |
| 1151 } | 1095 } |
| 1152 | 1096 |
| 1153 | |
| 1154 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1097 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1155 // The string register points to the backing store for external strings. | 1098 // The string register points to the backing store for external strings. |
| 1156 const Register str = locs()->in(0).reg(); | 1099 const Register str = locs()->in(0).reg(); |
| 1157 const Location index = locs()->in(1); | 1100 const Location index = locs()->in(1); |
| 1158 | 1101 |
| 1159 Address element_address = Assembler::ElementAddressForRegIndex( | 1102 Address element_address = Assembler::ElementAddressForRegIndex( |
| 1160 IsExternal(), class_id(), index_scale(), str, index.reg()); | 1103 IsExternal(), class_id(), index_scale(), str, index.reg()); |
| 1161 | 1104 |
| 1162 if ((index_scale() == 1)) { | 1105 if ((index_scale() == 1)) { |
| 1163 __ SmiUntag(index.reg()); | 1106 __ SmiUntag(index.reg()); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1194 UNREACHABLE(); | 1137 UNREACHABLE(); |
| 1195 } | 1138 } |
| 1196 __ SmiTag(result); | 1139 __ SmiTag(result); |
| 1197 break; | 1140 break; |
| 1198 default: | 1141 default: |
| 1199 UNREACHABLE(); | 1142 UNREACHABLE(); |
| 1200 break; | 1143 break; |
| 1201 } | 1144 } |
| 1202 } | 1145 } |
| 1203 | 1146 |
| 1204 | |
| 1205 Representation StoreIndexedInstr::RequiredInputRepresentation( | 1147 Representation StoreIndexedInstr::RequiredInputRepresentation( |
| 1206 intptr_t idx) const { | 1148 intptr_t idx) const { |
| 1207 if (idx == 0) return kNoRepresentation; | 1149 if (idx == 0) return kNoRepresentation; |
| 1208 if (idx == 1) return kTagged; | 1150 if (idx == 1) return kTagged; |
| 1209 ASSERT(idx == 2); | 1151 ASSERT(idx == 2); |
| 1210 switch (class_id_) { | 1152 switch (class_id_) { |
| 1211 case kArrayCid: | 1153 case kArrayCid: |
| 1212 case kOneByteStringCid: | 1154 case kOneByteStringCid: |
| 1213 case kTypedDataInt8ArrayCid: | 1155 case kTypedDataInt8ArrayCid: |
| 1214 case kTypedDataUint8ArrayCid: | 1156 case kTypedDataUint8ArrayCid: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1232 case kTypedDataInt32x4ArrayCid: | 1174 case kTypedDataInt32x4ArrayCid: |
| 1233 return kUnboxedInt32x4; | 1175 return kUnboxedInt32x4; |
| 1234 case kTypedDataFloat64x2ArrayCid: | 1176 case kTypedDataFloat64x2ArrayCid: |
| 1235 return kUnboxedFloat64x2; | 1177 return kUnboxedFloat64x2; |
| 1236 default: | 1178 default: |
| 1237 UNIMPLEMENTED(); | 1179 UNIMPLEMENTED(); |
| 1238 return kTagged; | 1180 return kTagged; |
| 1239 } | 1181 } |
| 1240 } | 1182 } |
| 1241 | 1183 |
| 1242 | |
| 1243 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1184 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1244 bool opt) const { | 1185 bool opt) const { |
| 1245 const intptr_t kNumInputs = 3; | 1186 const intptr_t kNumInputs = 3; |
| 1246 const intptr_t kNumTemps = 0; | 1187 const intptr_t kNumTemps = 0; |
| 1247 LocationSummary* locs = new (zone) | 1188 LocationSummary* locs = new (zone) |
| 1248 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1189 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1249 locs->set_in(0, Location::RequiresRegister()); | 1190 locs->set_in(0, Location::RequiresRegister()); |
| 1250 // The smi index is either untagged (element size == 1), or it is left smi | 1191 // The smi index is either untagged (element size == 1), or it is left smi |
| 1251 // tagged (for all element sizes > 1). | 1192 // tagged (for all element sizes > 1). |
| 1252 if (index_scale() == 1) { | 1193 if (index_scale() == 1) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1296 case kTypedDataFloat32x4ArrayCid: | 1237 case kTypedDataFloat32x4ArrayCid: |
| 1297 locs->set_in(2, Location::RequiresFpuRegister()); | 1238 locs->set_in(2, Location::RequiresFpuRegister()); |
| 1298 break; | 1239 break; |
| 1299 default: | 1240 default: |
| 1300 UNREACHABLE(); | 1241 UNREACHABLE(); |
| 1301 return NULL; | 1242 return NULL; |
| 1302 } | 1243 } |
| 1303 return locs; | 1244 return locs; |
| 1304 } | 1245 } |
| 1305 | 1246 |
| 1306 | |
| 1307 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1247 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1308 // The array register points to the backing store for external arrays. | 1248 // The array register points to the backing store for external arrays. |
| 1309 const Register array = locs()->in(0).reg(); | 1249 const Register array = locs()->in(0).reg(); |
| 1310 const Location index = locs()->in(1); | 1250 const Location index = locs()->in(1); |
| 1311 | 1251 |
| 1312 Address element_address = | 1252 Address element_address = |
| 1313 index.IsRegister() | 1253 index.IsRegister() |
| 1314 ? Assembler::ElementAddressForRegIndex( | 1254 ? Assembler::ElementAddressForRegIndex( |
| 1315 IsExternal(), class_id(), index_scale(), array, index.reg()) | 1255 IsExternal(), class_id(), index_scale(), array, index.reg()) |
| 1316 : Assembler::ElementAddressForIntIndex( | 1256 : Assembler::ElementAddressForIntIndex( |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1403 case kTypedDataInt32x4ArrayCid: | 1343 case kTypedDataInt32x4ArrayCid: |
| 1404 case kTypedDataFloat64x2ArrayCid: | 1344 case kTypedDataFloat64x2ArrayCid: |
| 1405 case kTypedDataFloat32x4ArrayCid: | 1345 case kTypedDataFloat32x4ArrayCid: |
| 1406 __ movups(element_address, locs()->in(2).fpu_reg()); | 1346 __ movups(element_address, locs()->in(2).fpu_reg()); |
| 1407 break; | 1347 break; |
| 1408 default: | 1348 default: |
| 1409 UNREACHABLE(); | 1349 UNREACHABLE(); |
| 1410 } | 1350 } |
| 1411 } | 1351 } |
| 1412 | 1352 |
| 1413 | |
| 1414 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 1353 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |
| 1415 bool opt) const { | 1354 bool opt) const { |
| 1416 const intptr_t kNumInputs = 1; | 1355 const intptr_t kNumInputs = 1; |
| 1417 | 1356 |
| 1418 const intptr_t value_cid = value()->Type()->ToCid(); | 1357 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1419 const intptr_t field_cid = field().guarded_cid(); | 1358 const intptr_t field_cid = field().guarded_cid(); |
| 1420 | 1359 |
| 1421 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); | 1360 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); |
| 1422 const bool needs_value_cid_temp_reg = | 1361 const bool needs_value_cid_temp_reg = |
| 1423 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); | 1362 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); |
| 1424 const bool needs_field_temp_reg = emit_full_guard; | 1363 const bool needs_field_temp_reg = emit_full_guard; |
| 1425 | 1364 |
| 1426 intptr_t num_temps = 0; | 1365 intptr_t num_temps = 0; |
| 1427 if (needs_value_cid_temp_reg) { | 1366 if (needs_value_cid_temp_reg) { |
| 1428 num_temps++; | 1367 num_temps++; |
| 1429 } | 1368 } |
| 1430 if (needs_field_temp_reg) { | 1369 if (needs_field_temp_reg) { |
| 1431 num_temps++; | 1370 num_temps++; |
| 1432 } | 1371 } |
| 1433 | 1372 |
| 1434 LocationSummary* summary = new (zone) | 1373 LocationSummary* summary = new (zone) |
| 1435 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 1374 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
| 1436 summary->set_in(0, Location::RequiresRegister()); | 1375 summary->set_in(0, Location::RequiresRegister()); |
| 1437 | 1376 |
| 1438 for (intptr_t i = 0; i < num_temps; i++) { | 1377 for (intptr_t i = 0; i < num_temps; i++) { |
| 1439 summary->set_temp(i, Location::RequiresRegister()); | 1378 summary->set_temp(i, Location::RequiresRegister()); |
| 1440 } | 1379 } |
| 1441 | 1380 |
| 1442 | |
| 1443 return summary; | 1381 return summary; |
| 1444 } | 1382 } |
| 1445 | 1383 |
| 1446 | |
| 1447 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1384 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1448 ASSERT(sizeof(classid_t) == kInt16Size); | 1385 ASSERT(sizeof(classid_t) == kInt16Size); |
| 1449 const intptr_t value_cid = value()->Type()->ToCid(); | 1386 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1450 const intptr_t field_cid = field().guarded_cid(); | 1387 const intptr_t field_cid = field().guarded_cid(); |
| 1451 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1388 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
| 1452 | 1389 |
| 1453 if (field_cid == kDynamicCid) { | 1390 if (field_cid == kDynamicCid) { |
| 1454 if (Compiler::IsBackgroundCompilation()) { | 1391 if (Compiler::IsBackgroundCompilation()) { |
| 1455 // Field state changed while compiling. | 1392 // Field state changed while compiling. |
| 1456 Compiler::AbortBackgroundCompilation( | 1393 Compiler::AbortBackgroundCompilation( |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1568 __ j(NOT_EQUAL, fail); | 1505 __ j(NOT_EQUAL, fail); |
| 1569 } else { | 1506 } else { |
| 1570 // Both value's and field's class id is known. | 1507 // Both value's and field's class id is known. |
| 1571 ASSERT((value_cid != field_cid) && (value_cid != nullability)); | 1508 ASSERT((value_cid != field_cid) && (value_cid != nullability)); |
| 1572 __ jmp(fail); | 1509 __ jmp(fail); |
| 1573 } | 1510 } |
| 1574 } | 1511 } |
| 1575 __ Bind(&ok); | 1512 __ Bind(&ok); |
| 1576 } | 1513 } |
| 1577 | 1514 |
| 1578 | |
| 1579 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 1515 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |
| 1580 bool opt) const { | 1516 bool opt) const { |
| 1581 const intptr_t kNumInputs = 1; | 1517 const intptr_t kNumInputs = 1; |
| 1582 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1518 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
| 1583 const intptr_t kNumTemps = 3; | 1519 const intptr_t kNumTemps = 3; |
| 1584 LocationSummary* summary = new (zone) | 1520 LocationSummary* summary = new (zone) |
| 1585 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1521 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1586 summary->set_in(0, Location::RequiresRegister()); | 1522 summary->set_in(0, Location::RequiresRegister()); |
| 1587 // We need temporaries for field object, length offset and expected length. | 1523 // We need temporaries for field object, length offset and expected length. |
| 1588 summary->set_temp(0, Location::RequiresRegister()); | 1524 summary->set_temp(0, Location::RequiresRegister()); |
| 1589 summary->set_temp(1, Location::RequiresRegister()); | 1525 summary->set_temp(1, Location::RequiresRegister()); |
| 1590 summary->set_temp(2, Location::RequiresRegister()); | 1526 summary->set_temp(2, Location::RequiresRegister()); |
| 1591 return summary; | 1527 return summary; |
| 1592 } else { | 1528 } else { |
| 1593 LocationSummary* summary = new (zone) | 1529 LocationSummary* summary = new (zone) |
| 1594 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); | 1530 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 1595 summary->set_in(0, Location::RequiresRegister()); | 1531 summary->set_in(0, Location::RequiresRegister()); |
| 1596 return summary; | 1532 return summary; |
| 1597 } | 1533 } |
| 1598 UNREACHABLE(); | 1534 UNREACHABLE(); |
| 1599 } | 1535 } |
| 1600 | 1536 |
| 1601 | |
| 1602 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1537 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1603 if (field().guarded_list_length() == Field::kNoFixedLength) { | 1538 if (field().guarded_list_length() == Field::kNoFixedLength) { |
| 1604 if (Compiler::IsBackgroundCompilation()) { | 1539 if (Compiler::IsBackgroundCompilation()) { |
| 1605 // Field state changed while compiling. | 1540 // Field state changed while compiling. |
| 1606 Compiler::AbortBackgroundCompilation( | 1541 Compiler::AbortBackgroundCompilation( |
| 1607 deopt_id(), | 1542 deopt_id(), |
| 1608 "GuardFieldLengthInstr: field state changed while compiling"); | 1543 "GuardFieldLengthInstr: field state changed while compiling"); |
| 1609 } | 1544 } |
| 1610 ASSERT(!compiler->is_optimizing()); | 1545 ASSERT(!compiler->is_optimizing()); |
| 1611 return; // Nothing to emit. | 1546 return; // Nothing to emit. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1662 ASSERT(field().guarded_list_length_in_object_offset() != | 1597 ASSERT(field().guarded_list_length_in_object_offset() != |
| 1663 Field::kUnknownLengthOffset); | 1598 Field::kUnknownLengthOffset); |
| 1664 | 1599 |
| 1665 __ CompareImmediate( | 1600 __ CompareImmediate( |
| 1666 FieldAddress(value_reg, field().guarded_list_length_in_object_offset()), | 1601 FieldAddress(value_reg, field().guarded_list_length_in_object_offset()), |
| 1667 Immediate(Smi::RawValue(field().guarded_list_length()))); | 1602 Immediate(Smi::RawValue(field().guarded_list_length()))); |
| 1668 __ j(NOT_EQUAL, deopt); | 1603 __ j(NOT_EQUAL, deopt); |
| 1669 } | 1604 } |
| 1670 } | 1605 } |
| 1671 | 1606 |
| 1672 | |
| 1673 class BoxAllocationSlowPath : public SlowPathCode { | 1607 class BoxAllocationSlowPath : public SlowPathCode { |
| 1674 public: | 1608 public: |
| 1675 BoxAllocationSlowPath(Instruction* instruction, | 1609 BoxAllocationSlowPath(Instruction* instruction, |
| 1676 const Class& cls, | 1610 const Class& cls, |
| 1677 Register result) | 1611 Register result) |
| 1678 : instruction_(instruction), cls_(cls), result_(result) {} | 1612 : instruction_(instruction), cls_(cls), result_(result) {} |
| 1679 | 1613 |
| 1680 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1614 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1681 if (Assembler::EmittingComments()) { | 1615 if (Assembler::EmittingComments()) { |
| 1682 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), | 1616 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1718 __ Bind(slow_path->exit_label()); | 1652 __ Bind(slow_path->exit_label()); |
| 1719 } | 1653 } |
| 1720 } | 1654 } |
| 1721 | 1655 |
| 1722 private: | 1656 private: |
| 1723 Instruction* instruction_; | 1657 Instruction* instruction_; |
| 1724 const Class& cls_; | 1658 const Class& cls_; |
| 1725 const Register result_; | 1659 const Register result_; |
| 1726 }; | 1660 }; |
| 1727 | 1661 |
| 1728 | |
| 1729 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 1662 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |
| 1730 bool opt) const { | 1663 bool opt) const { |
| 1731 const intptr_t kNumInputs = 2; | 1664 const intptr_t kNumInputs = 2; |
| 1732 const intptr_t kNumTemps = | 1665 const intptr_t kNumTemps = |
| 1733 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); | 1666 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); |
| 1734 LocationSummary* summary = new (zone) | 1667 LocationSummary* summary = new (zone) |
| 1735 LocationSummary(zone, kNumInputs, kNumTemps, | 1668 LocationSummary(zone, kNumInputs, kNumTemps, |
| 1736 ((IsUnboxedStore() && opt && is_initialization()) || | 1669 ((IsUnboxedStore() && opt && is_initialization()) || |
| 1737 IsPotentialUnboxedStore()) | 1670 IsPotentialUnboxedStore()) |
| 1738 ? LocationSummary::kCallOnSlowPath | 1671 ? LocationSummary::kCallOnSlowPath |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1751 summary->set_temp(2, opt ? Location::RequiresFpuRegister() | 1684 summary->set_temp(2, opt ? Location::RequiresFpuRegister() |
| 1752 : Location::FpuRegisterLocation(XMM1)); | 1685 : Location::FpuRegisterLocation(XMM1)); |
| 1753 } else { | 1686 } else { |
| 1754 summary->set_in(1, ShouldEmitStoreBarrier() | 1687 summary->set_in(1, ShouldEmitStoreBarrier() |
| 1755 ? Location::WritableRegister() | 1688 ? Location::WritableRegister() |
| 1756 : Location::RegisterOrConstant(value())); | 1689 : Location::RegisterOrConstant(value())); |
| 1757 } | 1690 } |
| 1758 return summary; | 1691 return summary; |
| 1759 } | 1692 } |
| 1760 | 1693 |
| 1761 | |
| 1762 static void EnsureMutableBox(FlowGraphCompiler* compiler, | 1694 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
| 1763 StoreInstanceFieldInstr* instruction, | 1695 StoreInstanceFieldInstr* instruction, |
| 1764 Register box_reg, | 1696 Register box_reg, |
| 1765 const Class& cls, | 1697 const Class& cls, |
| 1766 Register instance_reg, | 1698 Register instance_reg, |
| 1767 intptr_t offset, | 1699 intptr_t offset, |
| 1768 Register temp) { | 1700 Register temp) { |
| 1769 Label done; | 1701 Label done; |
| 1770 __ movq(box_reg, FieldAddress(instance_reg, offset)); | 1702 __ movq(box_reg, FieldAddress(instance_reg, offset)); |
| 1771 __ CompareObject(box_reg, Object::null_object()); | 1703 __ CompareObject(box_reg, Object::null_object()); |
| 1772 __ j(NOT_EQUAL, &done); | 1704 __ j(NOT_EQUAL, &done); |
| 1773 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); | 1705 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); |
| 1774 __ movq(temp, box_reg); | 1706 __ movq(temp, box_reg); |
| 1775 __ StoreIntoObject(instance_reg, FieldAddress(instance_reg, offset), temp); | 1707 __ StoreIntoObject(instance_reg, FieldAddress(instance_reg, offset), temp); |
| 1776 | 1708 |
| 1777 __ Bind(&done); | 1709 __ Bind(&done); |
| 1778 } | 1710 } |
| 1779 | 1711 |
| 1780 | |
| 1781 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1712 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1782 ASSERT(sizeof(classid_t) == kInt16Size); | 1713 ASSERT(sizeof(classid_t) == kInt16Size); |
| 1783 Label skip_store; | 1714 Label skip_store; |
| 1784 | 1715 |
| 1785 Register instance_reg = locs()->in(0).reg(); | 1716 Register instance_reg = locs()->in(0).reg(); |
| 1786 | 1717 |
| 1787 if (IsUnboxedStore() && compiler->is_optimizing()) { | 1718 if (IsUnboxedStore() && compiler->is_optimizing()) { |
| 1788 XmmRegister value = locs()->in(1).fpu_reg(); | 1719 XmmRegister value = locs()->in(1).fpu_reg(); |
| 1789 Register temp = locs()->temp(0).reg(); | 1720 Register temp = locs()->temp(0).reg(); |
| 1790 Register temp2 = locs()->temp(1).reg(); | 1721 Register temp2 = locs()->temp(1).reg(); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1922 } else { | 1853 } else { |
| 1923 Register value_reg = locs()->in(1).reg(); | 1854 Register value_reg = locs()->in(1).reg(); |
| 1924 __ StoreIntoObjectNoBarrier(instance_reg, | 1855 __ StoreIntoObjectNoBarrier(instance_reg, |
| 1925 FieldAddress(instance_reg, offset_in_bytes_), | 1856 FieldAddress(instance_reg, offset_in_bytes_), |
| 1926 value_reg); | 1857 value_reg); |
| 1927 } | 1858 } |
| 1928 } | 1859 } |
| 1929 __ Bind(&skip_store); | 1860 __ Bind(&skip_store); |
| 1930 } | 1861 } |
| 1931 | 1862 |
| 1932 | |
| 1933 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 1863 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 1934 bool opt) const { | 1864 bool opt) const { |
| 1935 const intptr_t kNumInputs = 1; | 1865 const intptr_t kNumInputs = 1; |
| 1936 const intptr_t kNumTemps = 0; | 1866 const intptr_t kNumTemps = 0; |
| 1937 LocationSummary* summary = new (zone) | 1867 LocationSummary* summary = new (zone) |
| 1938 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1868 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1939 summary->set_in(0, Location::RequiresRegister()); | 1869 summary->set_in(0, Location::RequiresRegister()); |
| 1940 summary->set_out(0, Location::RequiresRegister()); | 1870 summary->set_out(0, Location::RequiresRegister()); |
| 1941 return summary; | 1871 return summary; |
| 1942 } | 1872 } |
| 1943 | 1873 |
| 1944 | |
| 1945 // When the parser is building an implicit static getter for optimization, | 1874 // When the parser is building an implicit static getter for optimization, |
| 1946 // it can generate a function body where deoptimization ids do not line up | 1875 // it can generate a function body where deoptimization ids do not line up |
| 1947 // with the unoptimized code. | 1876 // with the unoptimized code. |
| 1948 // | 1877 // |
| 1949 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 1878 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
| 1950 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1879 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1951 Register field = locs()->in(0).reg(); | 1880 Register field = locs()->in(0).reg(); |
| 1952 Register result = locs()->out(0).reg(); | 1881 Register result = locs()->out(0).reg(); |
| 1953 __ movq(result, FieldAddress(field, Field::static_value_offset())); | 1882 __ movq(result, FieldAddress(field, Field::static_value_offset())); |
| 1954 } | 1883 } |
| 1955 | 1884 |
| 1956 | |
| 1957 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 1885 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 1958 bool opt) const { | 1886 bool opt) const { |
| 1959 LocationSummary* locs = | 1887 LocationSummary* locs = |
| 1960 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); | 1888 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); |
| 1961 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 1889 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 1962 : Location::RequiresRegister()); | 1890 : Location::RequiresRegister()); |
| 1963 locs->set_temp(0, Location::RequiresRegister()); | 1891 locs->set_temp(0, Location::RequiresRegister()); |
| 1964 return locs; | 1892 return locs; |
| 1965 } | 1893 } |
| 1966 | 1894 |
| 1967 | |
| 1968 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1895 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1969 Register value = locs()->in(0).reg(); | 1896 Register value = locs()->in(0).reg(); |
| 1970 Register temp = locs()->temp(0).reg(); | 1897 Register temp = locs()->temp(0).reg(); |
| 1971 | 1898 |
| 1972 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 1899 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
| 1973 if (this->value()->NeedsStoreBuffer()) { | 1900 if (this->value()->NeedsStoreBuffer()) { |
| 1974 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), | 1901 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), |
| 1975 value, CanValueBeSmi()); | 1902 value, CanValueBeSmi()); |
| 1976 } else { | 1903 } else { |
| 1977 __ StoreIntoObjectNoBarrier( | 1904 __ StoreIntoObjectNoBarrier( |
| 1978 temp, FieldAddress(temp, Field::static_value_offset()), value); | 1905 temp, FieldAddress(temp, Field::static_value_offset()), value); |
| 1979 } | 1906 } |
| 1980 } | 1907 } |
| 1981 | 1908 |
| 1982 | |
| 1983 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 1909 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
| 1984 bool opt) const { | 1910 bool opt) const { |
| 1985 const intptr_t kNumInputs = 3; | 1911 const intptr_t kNumInputs = 3; |
| 1986 const intptr_t kNumTemps = 0; | 1912 const intptr_t kNumTemps = 0; |
| 1987 LocationSummary* summary = new (zone) | 1913 LocationSummary* summary = new (zone) |
| 1988 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 1914 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1989 summary->set_in(0, Location::RegisterLocation(RAX)); // Instance. | 1915 summary->set_in(0, Location::RegisterLocation(RAX)); // Instance. |
| 1990 summary->set_in(1, Location::RegisterLocation(RDX)); // Instant. type args. | 1916 summary->set_in(1, Location::RegisterLocation(RDX)); // Instant. type args. |
| 1991 summary->set_in(2, Location::RegisterLocation(RCX)); // Function type args. | 1917 summary->set_in(2, Location::RegisterLocation(RCX)); // Function type args. |
| 1992 summary->set_out(0, Location::RegisterLocation(RAX)); | 1918 summary->set_out(0, Location::RegisterLocation(RAX)); |
| 1993 return summary; | 1919 return summary; |
| 1994 } | 1920 } |
| 1995 | 1921 |
| 1996 | |
| 1997 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1922 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1998 ASSERT(locs()->in(0).reg() == RAX); // Value. | 1923 ASSERT(locs()->in(0).reg() == RAX); // Value. |
| 1999 ASSERT(locs()->in(1).reg() == RDX); // Instantiator type arguments. | 1924 ASSERT(locs()->in(1).reg() == RDX); // Instantiator type arguments. |
| 2000 ASSERT(locs()->in(2).reg() == RCX); // Function type arguments. | 1925 ASSERT(locs()->in(2).reg() == RCX); // Function type arguments. |
| 2001 | 1926 |
| 2002 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs()); | 1927 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs()); |
| 2003 ASSERT(locs()->out(0).reg() == RAX); | 1928 ASSERT(locs()->out(0).reg() == RAX); |
| 2004 } | 1929 } |
| 2005 | 1930 |
| 2006 | |
| 2007 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and | 1931 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and |
| 2008 // use slow path stub. | 1932 // use slow path stub. |
| 2009 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 1933 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
| 2010 bool opt) const { | 1934 bool opt) const { |
| 2011 const intptr_t kNumInputs = 2; | 1935 const intptr_t kNumInputs = 2; |
| 2012 const intptr_t kNumTemps = 0; | 1936 const intptr_t kNumTemps = 0; |
| 2013 LocationSummary* locs = new (zone) | 1937 LocationSummary* locs = new (zone) |
| 2014 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 1938 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2015 locs->set_in(0, Location::RegisterLocation(RBX)); | 1939 locs->set_in(0, Location::RegisterLocation(RBX)); |
| 2016 locs->set_in(1, Location::RegisterLocation(R10)); | 1940 locs->set_in(1, Location::RegisterLocation(R10)); |
| 2017 locs->set_out(0, Location::RegisterLocation(RAX)); | 1941 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2018 return locs; | 1942 return locs; |
| 2019 } | 1943 } |
| 2020 | 1944 |
| 2021 | |
| 2022 // Inlines array allocation for known constant values. | 1945 // Inlines array allocation for known constant values. |
| 2023 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 1946 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
| 2024 intptr_t num_elements, | 1947 intptr_t num_elements, |
| 2025 Label* slow_path, | 1948 Label* slow_path, |
| 2026 Label* done) { | 1949 Label* done) { |
| 2027 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. | 1950 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. |
| 2028 const Register kLengthReg = R10; | 1951 const Register kLengthReg = R10; |
| 2029 const Register kElemTypeReg = RBX; | 1952 const Register kElemTypeReg = RBX; |
| 2030 const intptr_t instance_size = Array::InstanceSize(num_elements); | 1953 const intptr_t instance_size = Array::InstanceSize(num_elements); |
| 2031 | 1954 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2063 __ Bind(&init_loop); | 1986 __ Bind(&init_loop); |
| 2064 __ StoreIntoObjectNoBarrier(RAX, Address(RDI, 0), R12); | 1987 __ StoreIntoObjectNoBarrier(RAX, Address(RDI, 0), R12); |
| 2065 __ addq(RDI, Immediate(kWordSize)); | 1988 __ addq(RDI, Immediate(kWordSize)); |
| 2066 __ cmpq(RDI, RCX); | 1989 __ cmpq(RDI, RCX); |
| 2067 __ j(BELOW, &init_loop, Assembler::kNearJump); | 1990 __ j(BELOW, &init_loop, Assembler::kNearJump); |
| 2068 } | 1991 } |
| 2069 } | 1992 } |
| 2070 __ jmp(done, Assembler::kNearJump); | 1993 __ jmp(done, Assembler::kNearJump); |
| 2071 } | 1994 } |
| 2072 | 1995 |
| 2073 | |
| 2074 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1996 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2075 // Allocate the array. R10 = length, RBX = element type. | 1997 // Allocate the array. R10 = length, RBX = element type. |
| 2076 const Register kLengthReg = R10; | 1998 const Register kLengthReg = R10; |
| 2077 const Register kElemTypeReg = RBX; | 1999 const Register kElemTypeReg = RBX; |
| 2078 const Register kResultReg = RAX; | 2000 const Register kResultReg = RAX; |
| 2079 ASSERT(locs()->in(0).reg() == kElemTypeReg); | 2001 ASSERT(locs()->in(0).reg() == kElemTypeReg); |
| 2080 ASSERT(locs()->in(1).reg() == kLengthReg); | 2002 ASSERT(locs()->in(1).reg() == kLengthReg); |
| 2081 | 2003 |
| 2082 Label slow_path, done; | 2004 Label slow_path, done; |
| 2083 if (compiler->is_optimizing() && !FLAG_precompiled_mode && | 2005 if (compiler->is_optimizing() && !FLAG_precompiled_mode && |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2104 const Code& stub = Code::ZoneHandle(compiler->zone(), | 2026 const Code& stub = Code::ZoneHandle(compiler->zone(), |
| 2105 StubCode::AllocateArray_entry()->code()); | 2027 StubCode::AllocateArray_entry()->code()); |
| 2106 compiler->AddStubCallTarget(stub); | 2028 compiler->AddStubCallTarget(stub); |
| 2107 compiler->GenerateCallWithDeopt(token_pos(), deopt_id(), | 2029 compiler->GenerateCallWithDeopt(token_pos(), deopt_id(), |
| 2108 *StubCode::AllocateArray_entry(), | 2030 *StubCode::AllocateArray_entry(), |
| 2109 RawPcDescriptors::kOther, locs()); | 2031 RawPcDescriptors::kOther, locs()); |
| 2110 __ Bind(&done); | 2032 __ Bind(&done); |
| 2111 ASSERT(locs()->out(0).reg() == kResultReg); | 2033 ASSERT(locs()->out(0).reg() == kResultReg); |
| 2112 } | 2034 } |
| 2113 | 2035 |
| 2114 | |
| 2115 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 2036 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |
| 2116 bool opt) const { | 2037 bool opt) const { |
| 2117 const intptr_t kNumInputs = 1; | 2038 const intptr_t kNumInputs = 1; |
| 2118 const intptr_t kNumTemps = | 2039 const intptr_t kNumTemps = |
| 2119 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0); | 2040 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0); |
| 2120 LocationSummary* locs = new (zone) LocationSummary( | 2041 LocationSummary* locs = new (zone) LocationSummary( |
| 2121 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) | 2042 zone, kNumInputs, kNumTemps, |
| 2122 ? LocationSummary::kNoCall | 2043 (opt && !IsPotentialUnboxedLoad()) ? LocationSummary::kNoCall |
| 2123 : LocationSummary::kCallOnSlowPath); | 2044 : LocationSummary::kCallOnSlowPath); |
| 2124 | 2045 |
| 2125 locs->set_in(0, Location::RequiresRegister()); | 2046 locs->set_in(0, Location::RequiresRegister()); |
| 2126 | 2047 |
| 2127 if (IsUnboxedLoad() && opt) { | 2048 if (IsUnboxedLoad() && opt) { |
| 2128 locs->set_temp(0, Location::RequiresRegister()); | 2049 locs->set_temp(0, Location::RequiresRegister()); |
| 2129 } else if (IsPotentialUnboxedLoad()) { | 2050 } else if (IsPotentialUnboxedLoad()) { |
| 2130 locs->set_temp(0, opt ? Location::RequiresFpuRegister() | 2051 locs->set_temp(0, opt ? Location::RequiresFpuRegister() |
| 2131 : Location::FpuRegisterLocation(XMM1)); | 2052 : Location::FpuRegisterLocation(XMM1)); |
| 2132 locs->set_temp(1, Location::RequiresRegister()); | 2053 locs->set_temp(1, Location::RequiresRegister()); |
| 2133 } | 2054 } |
| 2134 locs->set_out(0, Location::RequiresRegister()); | 2055 locs->set_out(0, Location::RequiresRegister()); |
| 2135 return locs; | 2056 return locs; |
| 2136 } | 2057 } |
| 2137 | 2058 |
| 2138 | |
| 2139 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2059 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2140 ASSERT(sizeof(classid_t) == kInt16Size); | 2060 ASSERT(sizeof(classid_t) == kInt16Size); |
| 2141 Register instance_reg = locs()->in(0).reg(); | 2061 Register instance_reg = locs()->in(0).reg(); |
| 2142 if (IsUnboxedLoad() && compiler->is_optimizing()) { | 2062 if (IsUnboxedLoad() && compiler->is_optimizing()) { |
| 2143 XmmRegister result = locs()->out(0).fpu_reg(); | 2063 XmmRegister result = locs()->out(0).fpu_reg(); |
| 2144 Register temp = locs()->temp(0).reg(); | 2064 Register temp = locs()->temp(0).reg(); |
| 2145 __ movq(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2065 __ movq(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 2146 intptr_t cid = field()->UnboxedFieldCid(); | 2066 intptr_t cid = field()->UnboxedFieldCid(); |
| 2147 switch (cid) { | 2067 switch (cid) { |
| 2148 case kDoubleCid: | 2068 case kDoubleCid: |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2227 __ movups(FieldAddress(result, Float64x2::value_offset()), value); | 2147 __ movups(FieldAddress(result, Float64x2::value_offset()), value); |
| 2228 __ jmp(&done); | 2148 __ jmp(&done); |
| 2229 } | 2149 } |
| 2230 | 2150 |
| 2231 __ Bind(&load_pointer); | 2151 __ Bind(&load_pointer); |
| 2232 } | 2152 } |
| 2233 __ movq(result, FieldAddress(instance_reg, offset_in_bytes())); | 2153 __ movq(result, FieldAddress(instance_reg, offset_in_bytes())); |
| 2234 __ Bind(&done); | 2154 __ Bind(&done); |
| 2235 } | 2155 } |
| 2236 | 2156 |
| 2237 | |
| 2238 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2157 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
| 2239 bool opt) const { | 2158 bool opt) const { |
| 2240 const intptr_t kNumInputs = 2; | 2159 const intptr_t kNumInputs = 2; |
| 2241 const intptr_t kNumTemps = 0; | 2160 const intptr_t kNumTemps = 0; |
| 2242 LocationSummary* locs = new (zone) | 2161 LocationSummary* locs = new (zone) |
| 2243 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2162 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2244 locs->set_in(0, Location::RegisterLocation(RAX)); // Instant. type args. | 2163 locs->set_in(0, Location::RegisterLocation(RAX)); // Instant. type args. |
| 2245 locs->set_in(1, Location::RegisterLocation(RDX)); // Function type args. | 2164 locs->set_in(1, Location::RegisterLocation(RDX)); // Function type args. |
| 2246 locs->set_out(0, Location::RegisterLocation(RAX)); | 2165 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2247 return locs; | 2166 return locs; |
| 2248 } | 2167 } |
| 2249 | 2168 |
| 2250 | |
| 2251 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2169 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2252 Register instantiator_type_args_reg = locs()->in(0).reg(); | 2170 Register instantiator_type_args_reg = locs()->in(0).reg(); |
| 2253 Register function_type_args_reg = locs()->in(1).reg(); | 2171 Register function_type_args_reg = locs()->in(1).reg(); |
| 2254 Register result_reg = locs()->out(0).reg(); | 2172 Register result_reg = locs()->out(0).reg(); |
| 2255 | 2173 |
| 2256 // 'instantiator_type_args_reg' is a TypeArguments object (or null). | 2174 // 'instantiator_type_args_reg' is a TypeArguments object (or null). |
| 2257 // 'function_type_args_reg' is a TypeArguments object (or null). | 2175 // 'function_type_args_reg' is a TypeArguments object (or null). |
| 2258 // A runtime call to instantiate the type is required. | 2176 // A runtime call to instantiate the type is required. |
| 2259 __ PushObject(Object::null_object()); // Make room for the result. | 2177 __ PushObject(Object::null_object()); // Make room for the result. |
| 2260 __ PushObject(type()); | 2178 __ PushObject(type()); |
| 2261 __ pushq(instantiator_type_args_reg); // Push instantiator type arguments. | 2179 __ pushq(instantiator_type_args_reg); // Push instantiator type arguments. |
| 2262 __ pushq(function_type_args_reg); // Push function type arguments. | 2180 __ pushq(function_type_args_reg); // Push function type arguments. |
| 2263 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2181 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2264 kInstantiateTypeRuntimeEntry, 3, locs()); | 2182 kInstantiateTypeRuntimeEntry, 3, locs()); |
| 2265 __ Drop(3); // Drop 2 type argument vectors and uninstantiated type. | 2183 __ Drop(3); // Drop 2 type argument vectors and uninstantiated type. |
| 2266 __ popq(result_reg); // Pop instantiated type. | 2184 __ popq(result_reg); // Pop instantiated type. |
| 2267 } | 2185 } |
| 2268 | 2186 |
| 2269 | |
| 2270 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2187 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
| 2271 Zone* zone, | 2188 Zone* zone, |
| 2272 bool opt) const { | 2189 bool opt) const { |
| 2273 const intptr_t kNumInputs = 2; | 2190 const intptr_t kNumInputs = 2; |
| 2274 const intptr_t kNumTemps = 0; | 2191 const intptr_t kNumTemps = 0; |
| 2275 LocationSummary* locs = new (zone) | 2192 LocationSummary* locs = new (zone) |
| 2276 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2193 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2277 locs->set_in(0, Location::RegisterLocation(RAX)); // Instant. type args. | 2194 locs->set_in(0, Location::RegisterLocation(RAX)); // Instant. type args. |
| 2278 locs->set_in(1, Location::RegisterLocation(RCX)); // Function type args. | 2195 locs->set_in(1, Location::RegisterLocation(RCX)); // Function type args. |
| 2279 locs->set_out(0, Location::RegisterLocation(RAX)); | 2196 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2280 return locs; | 2197 return locs; |
| 2281 } | 2198 } |
| 2282 | 2199 |
| 2283 | |
| 2284 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2200 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
| 2285 FlowGraphCompiler* compiler) { | 2201 FlowGraphCompiler* compiler) { |
| 2286 Register instantiator_type_args_reg = locs()->in(0).reg(); | 2202 Register instantiator_type_args_reg = locs()->in(0).reg(); |
| 2287 Register function_type_args_reg = locs()->in(1).reg(); | 2203 Register function_type_args_reg = locs()->in(1).reg(); |
| 2288 Register result_reg = locs()->out(0).reg(); | 2204 Register result_reg = locs()->out(0).reg(); |
| 2289 ASSERT(instantiator_type_args_reg == RAX); | 2205 ASSERT(instantiator_type_args_reg == RAX); |
| 2290 ASSERT(instantiator_type_args_reg == result_reg); | 2206 ASSERT(instantiator_type_args_reg == result_reg); |
| 2291 | 2207 |
| 2292 // 'instantiator_type_args_reg' is a TypeArguments object (or null). | 2208 // 'instantiator_type_args_reg' is a TypeArguments object (or null). |
| 2293 // 'function_type_args_reg' is a TypeArguments object (or null). | 2209 // 'function_type_args_reg' is a TypeArguments object (or null). |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2341 __ pushq(instantiator_type_args_reg); // Push instantiator type arguments. | 2257 __ pushq(instantiator_type_args_reg); // Push instantiator type arguments. |
| 2342 __ pushq(function_type_args_reg); // Push function type arguments. | 2258 __ pushq(function_type_args_reg); // Push function type arguments. |
| 2343 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2259 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2344 kInstantiateTypeArgumentsRuntimeEntry, 3, | 2260 kInstantiateTypeArgumentsRuntimeEntry, 3, |
| 2345 locs()); | 2261 locs()); |
| 2346 __ Drop(3); // Drop 2 type argument vectors and uninstantiated args. | 2262 __ Drop(3); // Drop 2 type argument vectors and uninstantiated args. |
| 2347 __ popq(result_reg); // Pop instantiated type arguments. | 2263 __ popq(result_reg); // Pop instantiated type arguments. |
| 2348 __ Bind(&type_arguments_instantiated); | 2264 __ Bind(&type_arguments_instantiated); |
| 2349 } | 2265 } |
| 2350 | 2266 |
| 2351 | |
| 2352 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2267 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
| 2353 Zone* zone, | 2268 Zone* zone, |
| 2354 bool opt) const { | 2269 bool opt) const { |
| 2355 ASSERT(opt); | 2270 ASSERT(opt); |
| 2356 const intptr_t kNumInputs = 0; | 2271 const intptr_t kNumInputs = 0; |
| 2357 const intptr_t kNumTemps = 2; | 2272 const intptr_t kNumTemps = 2; |
| 2358 LocationSummary* locs = new (zone) LocationSummary( | 2273 LocationSummary* locs = new (zone) LocationSummary( |
| 2359 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2274 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2360 locs->set_temp(0, Location::RegisterLocation(R10)); | 2275 locs->set_temp(0, Location::RegisterLocation(R10)); |
| 2361 locs->set_temp(1, Location::RegisterLocation(R13)); | 2276 locs->set_temp(1, Location::RegisterLocation(R13)); |
| 2362 locs->set_out(0, Location::RegisterLocation(RAX)); | 2277 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2363 return locs; | 2278 return locs; |
| 2364 } | 2279 } |
| 2365 | 2280 |
| 2366 | |
| 2367 class AllocateContextSlowPath : public SlowPathCode { | 2281 class AllocateContextSlowPath : public SlowPathCode { |
| 2368 public: | 2282 public: |
| 2369 explicit AllocateContextSlowPath( | 2283 explicit AllocateContextSlowPath( |
| 2370 AllocateUninitializedContextInstr* instruction) | 2284 AllocateUninitializedContextInstr* instruction) |
| 2371 : instruction_(instruction) {} | 2285 : instruction_(instruction) {} |
| 2372 | 2286 |
| 2373 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2287 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2374 __ Comment("AllocateContextSlowPath"); | 2288 __ Comment("AllocateContextSlowPath"); |
| 2375 __ Bind(entry_label()); | 2289 __ Bind(entry_label()); |
| 2376 | 2290 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2388 RawPcDescriptors::kOther, locs); | 2302 RawPcDescriptors::kOther, locs); |
| 2389 ASSERT(instruction_->locs()->out(0).reg() == RAX); | 2303 ASSERT(instruction_->locs()->out(0).reg() == RAX); |
| 2390 compiler->RestoreLiveRegisters(instruction_->locs()); | 2304 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2391 __ jmp(exit_label()); | 2305 __ jmp(exit_label()); |
| 2392 } | 2306 } |
| 2393 | 2307 |
| 2394 private: | 2308 private: |
| 2395 AllocateUninitializedContextInstr* instruction_; | 2309 AllocateUninitializedContextInstr* instruction_; |
| 2396 }; | 2310 }; |
| 2397 | 2311 |
| 2398 | |
| 2399 void AllocateUninitializedContextInstr::EmitNativeCode( | 2312 void AllocateUninitializedContextInstr::EmitNativeCode( |
| 2400 FlowGraphCompiler* compiler) { | 2313 FlowGraphCompiler* compiler) { |
| 2401 ASSERT(compiler->is_optimizing()); | 2314 ASSERT(compiler->is_optimizing()); |
| 2402 Register temp = locs()->temp(0).reg(); | 2315 Register temp = locs()->temp(0).reg(); |
| 2403 Register result = locs()->out(0).reg(); | 2316 Register result = locs()->out(0).reg(); |
| 2404 // Try allocate the object. | 2317 // Try allocate the object. |
| 2405 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2318 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
| 2406 compiler->AddSlowPathCode(slow_path); | 2319 compiler->AddSlowPathCode(slow_path); |
| 2407 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2320 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
| 2408 | 2321 |
| 2409 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 2322 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
| 2410 Assembler::kFarJump, | 2323 Assembler::kFarJump, |
| 2411 result, // instance | 2324 result, // instance |
| 2412 temp, // end address | 2325 temp, // end address |
| 2413 locs()->temp(1).reg()); | 2326 locs()->temp(1).reg()); |
| 2414 | 2327 |
| 2415 // Setup up number of context variables field. | 2328 // Setup up number of context variables field. |
| 2416 __ movq(FieldAddress(result, Context::num_variables_offset()), | 2329 __ movq(FieldAddress(result, Context::num_variables_offset()), |
| 2417 Immediate(num_context_variables())); | 2330 Immediate(num_context_variables())); |
| 2418 | 2331 |
| 2419 __ Bind(slow_path->exit_label()); | 2332 __ Bind(slow_path->exit_label()); |
| 2420 } | 2333 } |
| 2421 | 2334 |
| 2422 | |
| 2423 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 2335 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |
| 2424 bool opt) const { | 2336 bool opt) const { |
| 2425 const intptr_t kNumInputs = 0; | 2337 const intptr_t kNumInputs = 0; |
| 2426 const intptr_t kNumTemps = 1; | 2338 const intptr_t kNumTemps = 1; |
| 2427 LocationSummary* locs = new (zone) | 2339 LocationSummary* locs = new (zone) |
| 2428 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2340 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2429 locs->set_temp(0, Location::RegisterLocation(R10)); | 2341 locs->set_temp(0, Location::RegisterLocation(R10)); |
| 2430 locs->set_out(0, Location::RegisterLocation(RAX)); | 2342 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2431 return locs; | 2343 return locs; |
| 2432 } | 2344 } |
| 2433 | 2345 |
| 2434 | |
| 2435 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2346 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2436 ASSERT(locs()->temp(0).reg() == R10); | 2347 ASSERT(locs()->temp(0).reg() == R10); |
| 2437 ASSERT(locs()->out(0).reg() == RAX); | 2348 ASSERT(locs()->out(0).reg() == RAX); |
| 2438 | 2349 |
| 2439 __ LoadImmediate(R10, Immediate(num_context_variables())); | 2350 __ LoadImmediate(R10, Immediate(num_context_variables())); |
| 2440 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), | 2351 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), |
| 2441 RawPcDescriptors::kOther, locs()); | 2352 RawPcDescriptors::kOther, locs()); |
| 2442 } | 2353 } |
| 2443 | 2354 |
| 2444 | |
| 2445 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2355 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2446 bool opt) const { | 2356 bool opt) const { |
| 2447 const intptr_t kNumInputs = 1; | 2357 const intptr_t kNumInputs = 1; |
| 2448 const intptr_t kNumTemps = 1; | 2358 const intptr_t kNumTemps = 1; |
| 2449 LocationSummary* locs = new (zone) | 2359 LocationSummary* locs = new (zone) |
| 2450 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2360 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2451 locs->set_in(0, Location::RegisterLocation(RAX)); | 2361 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 2452 locs->set_temp(0, Location::RegisterLocation(RCX)); | 2362 locs->set_temp(0, Location::RegisterLocation(RCX)); |
| 2453 return locs; | 2363 return locs; |
| 2454 } | 2364 } |
| 2455 | 2365 |
| 2456 | |
| 2457 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2366 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2458 Register field = locs()->in(0).reg(); | 2367 Register field = locs()->in(0).reg(); |
| 2459 Register temp = locs()->temp(0).reg(); | 2368 Register temp = locs()->temp(0).reg(); |
| 2460 | 2369 |
| 2461 Label call_runtime, no_call; | 2370 Label call_runtime, no_call; |
| 2462 | 2371 |
| 2463 __ movq(temp, FieldAddress(field, Field::static_value_offset())); | 2372 __ movq(temp, FieldAddress(field, Field::static_value_offset())); |
| 2464 __ CompareObject(temp, Object::sentinel()); | 2373 __ CompareObject(temp, Object::sentinel()); |
| 2465 __ j(EQUAL, &call_runtime); | 2374 __ j(EQUAL, &call_runtime); |
| 2466 | 2375 |
| 2467 __ CompareObject(temp, Object::transition_sentinel()); | 2376 __ CompareObject(temp, Object::transition_sentinel()); |
| 2468 __ j(NOT_EQUAL, &no_call); | 2377 __ j(NOT_EQUAL, &no_call); |
| 2469 | 2378 |
| 2470 __ Bind(&call_runtime); | 2379 __ Bind(&call_runtime); |
| 2471 __ PushObject(Object::null_object()); // Make room for (unused) result. | 2380 __ PushObject(Object::null_object()); // Make room for (unused) result. |
| 2472 __ pushq(field); | 2381 __ pushq(field); |
| 2473 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2382 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2474 kInitStaticFieldRuntimeEntry, 1, locs()); | 2383 kInitStaticFieldRuntimeEntry, 1, locs()); |
| 2475 __ Drop(2); // Remove argument and unused result. | 2384 __ Drop(2); // Remove argument and unused result. |
| 2476 __ Bind(&no_call); | 2385 __ Bind(&no_call); |
| 2477 } | 2386 } |
| 2478 | 2387 |
| 2479 | |
| 2480 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2388 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
| 2481 bool opt) const { | 2389 bool opt) const { |
| 2482 const intptr_t kNumInputs = 1; | 2390 const intptr_t kNumInputs = 1; |
| 2483 const intptr_t kNumTemps = 0; | 2391 const intptr_t kNumTemps = 0; |
| 2484 LocationSummary* locs = new (zone) | 2392 LocationSummary* locs = new (zone) |
| 2485 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2393 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2486 locs->set_in(0, Location::RegisterLocation(RAX)); | 2394 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 2487 locs->set_out(0, Location::RegisterLocation(RAX)); | 2395 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2488 return locs; | 2396 return locs; |
| 2489 } | 2397 } |
| 2490 | 2398 |
| 2491 | |
| 2492 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2399 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2493 Register context_value = locs()->in(0).reg(); | 2400 Register context_value = locs()->in(0).reg(); |
| 2494 Register result = locs()->out(0).reg(); | 2401 Register result = locs()->out(0).reg(); |
| 2495 | 2402 |
| 2496 __ PushObject(Object::null_object()); // Make room for the result. | 2403 __ PushObject(Object::null_object()); // Make room for the result. |
| 2497 __ pushq(context_value); | 2404 __ pushq(context_value); |
| 2498 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), | 2405 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2499 kCloneContextRuntimeEntry, 1, locs()); | 2406 kCloneContextRuntimeEntry, 1, locs()); |
| 2500 __ popq(result); // Remove argument. | 2407 __ popq(result); // Remove argument. |
| 2501 __ popq(result); // Get result (cloned context). | 2408 __ popq(result); // Get result (cloned context). |
| 2502 } | 2409 } |
| 2503 | 2410 |
| 2504 | |
| 2505 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2411 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
| 2506 bool opt) const { | 2412 bool opt) const { |
| 2507 UNREACHABLE(); | 2413 UNREACHABLE(); |
| 2508 return NULL; | 2414 return NULL; |
| 2509 } | 2415 } |
| 2510 | 2416 |
| 2511 | |
| 2512 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2417 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2513 __ Bind(compiler->GetJumpLabel(this)); | 2418 __ Bind(compiler->GetJumpLabel(this)); |
| 2514 compiler->AddExceptionHandler(catch_try_index(), try_index(), | 2419 compiler->AddExceptionHandler(catch_try_index(), try_index(), |
| 2515 compiler->assembler()->CodeSize(), | 2420 compiler->assembler()->CodeSize(), |
| 2516 handler_token_pos(), is_generated(), | 2421 handler_token_pos(), is_generated(), |
| 2517 catch_handler_types_, needs_stacktrace()); | 2422 catch_handler_types_, needs_stacktrace()); |
| 2518 // On lazy deoptimization we patch the optimized code here to enter the | 2423 // On lazy deoptimization we patch the optimized code here to enter the |
| 2519 // deoptimization stub. | 2424 // deoptimization stub. |
| 2520 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 2425 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |
| 2521 if (compiler->is_optimizing()) { | 2426 if (compiler->is_optimizing()) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2574 FieldAddress(CTX, Context::variable_offset(stacktrace_var().index())), | 2479 FieldAddress(CTX, Context::variable_offset(stacktrace_var().index())), |
| 2575 kStackTraceObjectReg); | 2480 kStackTraceObjectReg); |
| 2576 } else { | 2481 } else { |
| 2577 __ movq(Address(RBP, exception_var().index() * kWordSize), | 2482 __ movq(Address(RBP, exception_var().index() * kWordSize), |
| 2578 kExceptionObjectReg); | 2483 kExceptionObjectReg); |
| 2579 __ movq(Address(RBP, stacktrace_var().index() * kWordSize), | 2484 __ movq(Address(RBP, stacktrace_var().index() * kWordSize), |
| 2580 kStackTraceObjectReg); | 2485 kStackTraceObjectReg); |
| 2581 } | 2486 } |
| 2582 } | 2487 } |
| 2583 | 2488 |
| 2584 | |
| 2585 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 2489 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |
| 2586 bool opt) const { | 2490 bool opt) const { |
| 2587 const intptr_t kNumInputs = 0; | 2491 const intptr_t kNumInputs = 0; |
| 2588 const intptr_t kNumTemps = 1; | 2492 const intptr_t kNumTemps = 1; |
| 2589 LocationSummary* summary = new (zone) LocationSummary( | 2493 LocationSummary* summary = new (zone) LocationSummary( |
| 2590 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2494 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2591 summary->set_temp(0, Location::RequiresRegister()); | 2495 summary->set_temp(0, Location::RequiresRegister()); |
| 2592 return summary; | 2496 return summary; |
| 2593 } | 2497 } |
| 2594 | 2498 |
| 2595 | |
| 2596 class CheckStackOverflowSlowPath : public SlowPathCode { | 2499 class CheckStackOverflowSlowPath : public SlowPathCode { |
| 2597 public: | 2500 public: |
| 2598 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2501 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
| 2599 : instruction_(instruction) {} | 2502 : instruction_(instruction) {} |
| 2600 | 2503 |
| 2601 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2504 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2602 if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) { | 2505 if (compiler->isolate()->use_osr() && osr_entry_label()->IsLinked()) { |
| 2603 __ Comment("CheckStackOverflowSlowPathOsr"); | 2506 __ Comment("CheckStackOverflowSlowPathOsr"); |
| 2604 __ Bind(osr_entry_label()); | 2507 __ Bind(osr_entry_label()); |
| 2605 __ movq(Address(THR, Thread::stack_overflow_flags_offset()), | 2508 __ movq(Address(THR, Thread::stack_overflow_flags_offset()), |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2622 // In unoptimized code, record loop stack checks as possible OSR entries. | 2525 // In unoptimized code, record loop stack checks as possible OSR entries. |
| 2623 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, | 2526 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, |
| 2624 instruction_->deopt_id(), | 2527 instruction_->deopt_id(), |
| 2625 TokenPosition::kNoSource); | 2528 TokenPosition::kNoSource); |
| 2626 } | 2529 } |
| 2627 compiler->pending_deoptimization_env_ = NULL; | 2530 compiler->pending_deoptimization_env_ = NULL; |
| 2628 compiler->RestoreLiveRegisters(instruction_->locs()); | 2531 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2629 __ jmp(exit_label()); | 2532 __ jmp(exit_label()); |
| 2630 } | 2533 } |
| 2631 | 2534 |
| 2632 | |
| 2633 Label* osr_entry_label() { | 2535 Label* osr_entry_label() { |
| 2634 ASSERT(Isolate::Current()->use_osr()); | 2536 ASSERT(Isolate::Current()->use_osr()); |
| 2635 return &osr_entry_label_; | 2537 return &osr_entry_label_; |
| 2636 } | 2538 } |
| 2637 | 2539 |
| 2638 private: | 2540 private: |
| 2639 CheckStackOverflowInstr* instruction_; | 2541 CheckStackOverflowInstr* instruction_; |
| 2640 Label osr_entry_label_; | 2542 Label osr_entry_label_; |
| 2641 }; | 2543 }; |
| 2642 | 2544 |
| 2643 | |
| 2644 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2545 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2645 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); | 2546 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); |
| 2646 compiler->AddSlowPathCode(slow_path); | 2547 compiler->AddSlowPathCode(slow_path); |
| 2647 | 2548 |
| 2648 Register temp = locs()->temp(0).reg(); | 2549 Register temp = locs()->temp(0).reg(); |
| 2649 // Generate stack overflow check. | 2550 // Generate stack overflow check. |
| 2650 __ cmpq(RSP, Address(THR, Thread::stack_limit_offset())); | 2551 __ cmpq(RSP, Address(THR, Thread::stack_limit_offset())); |
| 2651 __ j(BELOW_EQUAL, slow_path->entry_label()); | 2552 __ j(BELOW_EQUAL, slow_path->entry_label()); |
| 2652 if (compiler->CanOSRFunction() && in_loop()) { | 2553 if (compiler->CanOSRFunction() && in_loop()) { |
| 2653 // In unoptimized code check the usage counter to trigger OSR at loop | 2554 // In unoptimized code check the usage counter to trigger OSR at loop |
| 2654 // stack checks. Use progressively higher thresholds for more deeply | 2555 // stack checks. Use progressively higher thresholds for more deeply |
| 2655 // nested loops to attempt to hit outer loops with OSR when possible. | 2556 // nested loops to attempt to hit outer loops with OSR when possible. |
| 2656 __ LoadObject(temp, compiler->parsed_function().function()); | 2557 __ LoadObject(temp, compiler->parsed_function().function()); |
| 2657 int32_t threshold = | 2558 int32_t threshold = |
| 2658 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2559 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
| 2659 __ cmpl(FieldAddress(temp, Function::usage_counter_offset()), | 2560 __ cmpl(FieldAddress(temp, Function::usage_counter_offset()), |
| 2660 Immediate(threshold)); | 2561 Immediate(threshold)); |
| 2661 __ j(GREATER_EQUAL, slow_path->osr_entry_label()); | 2562 __ j(GREATER_EQUAL, slow_path->osr_entry_label()); |
| 2662 } | 2563 } |
| 2663 if (compiler->ForceSlowPathForStackOverflow()) { | 2564 if (compiler->ForceSlowPathForStackOverflow()) { |
| 2664 __ jmp(slow_path->entry_label()); | 2565 __ jmp(slow_path->entry_label()); |
| 2665 } | 2566 } |
| 2666 __ Bind(slow_path->exit_label()); | 2567 __ Bind(slow_path->exit_label()); |
| 2667 } | 2568 } |
| 2668 | 2569 |
| 2669 | |
| 2670 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2570 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
| 2671 BinarySmiOpInstr* shift_left) { | 2571 BinarySmiOpInstr* shift_left) { |
| 2672 const LocationSummary& locs = *shift_left->locs(); | 2572 const LocationSummary& locs = *shift_left->locs(); |
| 2673 Register left = locs.in(0).reg(); | 2573 Register left = locs.in(0).reg(); |
| 2674 Register result = locs.out(0).reg(); | 2574 Register result = locs.out(0).reg(); |
| 2675 ASSERT(left == result); | 2575 ASSERT(left == result); |
| 2676 Label* deopt = shift_left->CanDeoptimize() | 2576 Label* deopt = shift_left->CanDeoptimize() |
| 2677 ? compiler->AddDeoptStub(shift_left->deopt_id(), | 2577 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
| 2678 ICData::kDeoptBinarySmiOp) | 2578 ICData::kDeoptBinarySmiOp) |
| 2679 : NULL; | 2579 : NULL; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2773 // Overflow test (preserve temp and right); | 2673 // Overflow test (preserve temp and right); |
| 2774 __ shlq(left, right); | 2674 __ shlq(left, right); |
| 2775 __ sarq(left, right); | 2675 __ sarq(left, right); |
| 2776 __ cmpq(left, temp); | 2676 __ cmpq(left, temp); |
| 2777 __ j(NOT_EQUAL, deopt); // Overflow. | 2677 __ j(NOT_EQUAL, deopt); // Overflow. |
| 2778 // Shift for result now we know there is no overflow. | 2678 // Shift for result now we know there is no overflow. |
| 2779 __ shlq(left, right); | 2679 __ shlq(left, right); |
| 2780 } | 2680 } |
| 2781 } | 2681 } |
| 2782 | 2682 |
| 2783 | |
| 2784 class CheckedSmiSlowPath : public SlowPathCode { | 2683 class CheckedSmiSlowPath : public SlowPathCode { |
| 2785 public: | 2684 public: |
| 2786 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) | 2685 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) |
| 2787 : instruction_(instruction), try_index_(try_index) {} | 2686 : instruction_(instruction), try_index_(try_index) {} |
| 2788 | 2687 |
| 2789 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2688 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2790 if (Assembler::EmittingComments()) { | 2689 if (Assembler::EmittingComments()) { |
| 2791 __ Comment("slow path smi operation"); | 2690 __ Comment("slow path smi operation"); |
| 2792 } | 2691 } |
| 2793 __ Bind(entry_label()); | 2692 __ Bind(entry_label()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2815 compiler->RestoreLiveRegisters(locs); | 2714 compiler->RestoreLiveRegisters(locs); |
| 2816 __ jmp(exit_label()); | 2715 __ jmp(exit_label()); |
| 2817 compiler->pending_deoptimization_env_ = NULL; | 2716 compiler->pending_deoptimization_env_ = NULL; |
| 2818 } | 2717 } |
| 2819 | 2718 |
| 2820 private: | 2719 private: |
| 2821 CheckedSmiOpInstr* instruction_; | 2720 CheckedSmiOpInstr* instruction_; |
| 2822 intptr_t try_index_; | 2721 intptr_t try_index_; |
| 2823 }; | 2722 }; |
| 2824 | 2723 |
| 2825 | |
| 2826 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 2724 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
| 2827 bool opt) const { | 2725 bool opt) const { |
| 2828 bool is_shift = (op_kind() == Token::kSHL) || (op_kind() == Token::kSHR); | 2726 bool is_shift = (op_kind() == Token::kSHL) || (op_kind() == Token::kSHR); |
| 2829 const intptr_t kNumInputs = 2; | 2727 const intptr_t kNumInputs = 2; |
| 2830 const intptr_t kNumTemps = is_shift ? 1 : 0; | 2728 const intptr_t kNumTemps = is_shift ? 1 : 0; |
| 2831 LocationSummary* summary = new (zone) LocationSummary( | 2729 LocationSummary* summary = new (zone) LocationSummary( |
| 2832 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2730 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2833 summary->set_in(0, Location::RequiresRegister()); | 2731 summary->set_in(0, Location::RequiresRegister()); |
| 2834 summary->set_in(1, Location::RequiresRegister()); | 2732 summary->set_in(1, Location::RequiresRegister()); |
| 2835 switch (op_kind()) { | 2733 switch (op_kind()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2847 break; | 2745 break; |
| 2848 default: | 2746 default: |
| 2849 UNIMPLEMENTED(); | 2747 UNIMPLEMENTED(); |
| 2850 } | 2748 } |
| 2851 if (is_shift) { | 2749 if (is_shift) { |
| 2852 summary->set_temp(0, Location::RegisterLocation(RCX)); | 2750 summary->set_temp(0, Location::RegisterLocation(RCX)); |
| 2853 } | 2751 } |
| 2854 return summary; | 2752 return summary; |
| 2855 } | 2753 } |
| 2856 | 2754 |
| 2857 | |
| 2858 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2755 void CheckedSmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2859 CheckedSmiSlowPath* slow_path = | 2756 CheckedSmiSlowPath* slow_path = |
| 2860 new CheckedSmiSlowPath(this, compiler->CurrentTryIndex()); | 2757 new CheckedSmiSlowPath(this, compiler->CurrentTryIndex()); |
| 2861 compiler->AddSlowPathCode(slow_path); | 2758 compiler->AddSlowPathCode(slow_path); |
| 2862 // Test operands if necessary. | 2759 // Test operands if necessary. |
| 2863 | 2760 |
| 2864 intptr_t left_cid = left()->Type()->ToCid(); | 2761 intptr_t left_cid = left()->Type()->ToCid(); |
| 2865 intptr_t right_cid = right()->Type()->ToCid(); | 2762 intptr_t right_cid = right()->Type()->ToCid(); |
| 2866 Register left = locs()->in(0).reg(); | 2763 Register left = locs()->in(0).reg(); |
| 2867 Register right = locs()->in(1).reg(); | 2764 Register right = locs()->in(1).reg(); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2936 __ sarq(result, RCX); | 2833 __ sarq(result, RCX); |
| 2937 __ SmiTag(result); | 2834 __ SmiTag(result); |
| 2938 break; | 2835 break; |
| 2939 } | 2836 } |
| 2940 default: | 2837 default: |
| 2941 UNIMPLEMENTED(); | 2838 UNIMPLEMENTED(); |
| 2942 } | 2839 } |
| 2943 __ Bind(slow_path->exit_label()); | 2840 __ Bind(slow_path->exit_label()); |
| 2944 } | 2841 } |
| 2945 | 2842 |
| 2946 | |
| 2947 class CheckedSmiComparisonSlowPath : public SlowPathCode { | 2843 class CheckedSmiComparisonSlowPath : public SlowPathCode { |
| 2948 public: | 2844 public: |
| 2949 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, | 2845 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, |
| 2950 intptr_t try_index, | 2846 intptr_t try_index, |
| 2951 BranchLabels labels, | 2847 BranchLabels labels, |
| 2952 bool merged = false) | 2848 bool merged = false) |
| 2953 : instruction_(instruction), | 2849 : instruction_(instruction), |
| 2954 try_index_(try_index), | 2850 try_index_(try_index), |
| 2955 labels_(labels), | 2851 labels_(labels), |
| 2956 merged_(merged) {} | 2852 merged_(merged) {} |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2994 } | 2890 } |
| 2995 } | 2891 } |
| 2996 | 2892 |
| 2997 private: | 2893 private: |
| 2998 CheckedSmiComparisonInstr* instruction_; | 2894 CheckedSmiComparisonInstr* instruction_; |
| 2999 intptr_t try_index_; | 2895 intptr_t try_index_; |
| 3000 BranchLabels labels_; | 2896 BranchLabels labels_; |
| 3001 bool merged_; | 2897 bool merged_; |
| 3002 }; | 2898 }; |
| 3003 | 2899 |
| 3004 | |
| 3005 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 2900 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
| 3006 Zone* zone, | 2901 Zone* zone, |
| 3007 bool opt) const { | 2902 bool opt) const { |
| 3008 const intptr_t kNumInputs = 2; | 2903 const intptr_t kNumInputs = 2; |
| 3009 const intptr_t kNumTemps = 1; | 2904 const intptr_t kNumTemps = 1; |
| 3010 LocationSummary* summary = new (zone) LocationSummary( | 2905 LocationSummary* summary = new (zone) LocationSummary( |
| 3011 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2906 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3012 summary->set_in(0, Location::RequiresRegister()); | 2907 summary->set_in(0, Location::RequiresRegister()); |
| 3013 summary->set_in(1, Location::RequiresRegister()); | 2908 summary->set_in(1, Location::RequiresRegister()); |
| 3014 summary->set_temp(0, Location::RequiresRegister()); | 2909 summary->set_temp(0, Location::RequiresRegister()); |
| 3015 summary->set_out(0, Location::RequiresRegister()); | 2910 summary->set_out(0, Location::RequiresRegister()); |
| 3016 return summary; | 2911 return summary; |
| 3017 } | 2912 } |
| 3018 | 2913 |
| 3019 | |
| 3020 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 2914 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
| 3021 FlowGraphCompiler* compiler, | 2915 FlowGraphCompiler* compiler, |
| 3022 BranchLabels labels) { | 2916 BranchLabels labels) { |
| 3023 return EmitInt64ComparisonOp(compiler, *locs(), kind()); | 2917 return EmitInt64ComparisonOp(compiler, *locs(), kind()); |
| 3024 } | 2918 } |
| 3025 | 2919 |
| 3026 | |
| 3027 #define EMIT_SMI_CHECK \ | 2920 #define EMIT_SMI_CHECK \ |
| 3028 intptr_t left_cid = left()->Type()->ToCid(); \ | 2921 intptr_t left_cid = left()->Type()->ToCid(); \ |
| 3029 intptr_t right_cid = right()->Type()->ToCid(); \ | 2922 intptr_t right_cid = right()->Type()->ToCid(); \ |
| 3030 Register left = locs()->in(0).reg(); \ | 2923 Register left = locs()->in(0).reg(); \ |
| 3031 Register right = locs()->in(1).reg(); \ | 2924 Register right = locs()->in(1).reg(); \ |
| 3032 if (this->left()->definition() == this->right()->definition()) { \ | 2925 if (this->left()->definition() == this->right()->definition()) { \ |
| 3033 __ testq(left, Immediate(kSmiTagMask)); \ | 2926 __ testq(left, Immediate(kSmiTagMask)); \ |
| 3034 } else if (left_cid == kSmiCid) { \ | 2927 } else if (left_cid == kSmiCid) { \ |
| 3035 __ testq(right, Immediate(kSmiTagMask)); \ | 2928 __ testq(right, Immediate(kSmiTagMask)); \ |
| 3036 } else if (right_cid == kSmiCid) { \ | 2929 } else if (right_cid == kSmiCid) { \ |
| 3037 __ testq(left, Immediate(kSmiTagMask)); \ | 2930 __ testq(left, Immediate(kSmiTagMask)); \ |
| 3038 } else { \ | 2931 } else { \ |
| 3039 __ movq(TMP, left); \ | 2932 __ movq(TMP, left); \ |
| 3040 __ orq(TMP, right); \ | 2933 __ orq(TMP, right); \ |
| 3041 __ testq(TMP, Immediate(kSmiTagMask)); \ | 2934 __ testq(TMP, Immediate(kSmiTagMask)); \ |
| 3042 } \ | 2935 } \ |
| 3043 __ j(NOT_ZERO, slow_path->entry_label()) | 2936 __ j(NOT_ZERO, slow_path->entry_label()) |
| 3044 | 2937 |
| 3045 | |
| 3046 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 2938 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 3047 BranchInstr* branch) { | 2939 BranchInstr* branch) { |
| 3048 BranchLabels labels = compiler->CreateBranchLabels(branch); | 2940 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 3049 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 2941 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
| 3050 this, compiler->CurrentTryIndex(), labels, | 2942 this, compiler->CurrentTryIndex(), labels, |
| 3051 /* merged = */ true); | 2943 /* merged = */ true); |
| 3052 compiler->AddSlowPathCode(slow_path); | 2944 compiler->AddSlowPathCode(slow_path); |
| 3053 EMIT_SMI_CHECK; | 2945 EMIT_SMI_CHECK; |
| 3054 Condition true_condition = EmitComparisonCode(compiler, labels); | 2946 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3055 ASSERT(true_condition != INVALID_CONDITION); | 2947 ASSERT(true_condition != INVALID_CONDITION); |
| 3056 EmitBranchOnCondition(compiler, true_condition, labels); | 2948 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3057 __ Bind(slow_path->exit_label()); | 2949 __ Bind(slow_path->exit_label()); |
| 3058 } | 2950 } |
| 3059 | 2951 |
| 3060 | |
| 3061 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2952 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3062 Label true_label, false_label, done; | 2953 Label true_label, false_label, done; |
| 3063 BranchLabels labels = {&true_label, &false_label, &false_label}; | 2954 BranchLabels labels = {&true_label, &false_label, &false_label}; |
| 3064 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( | 2955 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
| 3065 this, compiler->CurrentTryIndex(), labels, | 2956 this, compiler->CurrentTryIndex(), labels, |
| 3066 /* merged = */ false); | 2957 /* merged = */ false); |
| 3067 compiler->AddSlowPathCode(slow_path); | 2958 compiler->AddSlowPathCode(slow_path); |
| 3068 EMIT_SMI_CHECK; | 2959 EMIT_SMI_CHECK; |
| 3069 Condition true_condition = EmitComparisonCode(compiler, labels); | 2960 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3070 ASSERT(true_condition != INVALID_CONDITION); | 2961 ASSERT(true_condition != INVALID_CONDITION); |
| 3071 EmitBranchOnCondition(compiler, true_condition, labels); | 2962 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3072 Register result = locs()->out(0).reg(); | 2963 Register result = locs()->out(0).reg(); |
| 3073 __ Bind(&false_label); | 2964 __ Bind(&false_label); |
| 3074 __ LoadObject(result, Bool::False()); | 2965 __ LoadObject(result, Bool::False()); |
| 3075 __ jmp(&done); | 2966 __ jmp(&done); |
| 3076 __ Bind(&true_label); | 2967 __ Bind(&true_label); |
| 3077 __ LoadObject(result, Bool::True()); | 2968 __ LoadObject(result, Bool::True()); |
| 3078 __ Bind(&done); | 2969 __ Bind(&done); |
| 3079 __ Bind(slow_path->exit_label()); | 2970 __ Bind(slow_path->exit_label()); |
| 3080 } | 2971 } |
| 3081 | 2972 |
| 3082 | |
| 3083 static bool CanBeImmediate(const Object& constant) { | 2973 static bool CanBeImmediate(const Object& constant) { |
| 3084 return constant.IsSmi() && | 2974 return constant.IsSmi() && |
| 3085 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); | 2975 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); |
| 3086 } | 2976 } |
| 3087 | 2977 |
| 3088 static bool IsSmiValue(const Object& constant, intptr_t value) { | 2978 static bool IsSmiValue(const Object& constant, intptr_t value) { |
| 3089 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); | 2979 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); |
| 3090 } | 2980 } |
| 3091 | 2981 |
| 3092 | |
| 3093 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 2982 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 3094 bool opt) const { | 2983 bool opt) const { |
| 3095 const intptr_t kNumInputs = 2; | 2984 const intptr_t kNumInputs = 2; |
| 3096 | 2985 |
| 3097 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 2986 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
| 3098 if ((right_constant != NULL) && (op_kind() != Token::kTRUNCDIV) && | 2987 if ((right_constant != NULL) && (op_kind() != Token::kTRUNCDIV) && |
| 3099 (op_kind() != Token::kSHL) && (op_kind() != Token::kMUL) && | 2988 (op_kind() != Token::kSHL) && (op_kind() != Token::kMUL) && |
| 3100 (op_kind() != Token::kMOD) && CanBeImmediate(right_constant->value())) { | 2989 (op_kind() != Token::kMOD) && CanBeImmediate(right_constant->value())) { |
| 3101 const intptr_t kNumTemps = 0; | 2990 const intptr_t kNumTemps = 0; |
| 3102 LocationSummary* summary = new (zone) | 2991 LocationSummary* summary = new (zone) |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3257 break; | 3146 break; |
| 3258 } | 3147 } |
| 3259 | 3148 |
| 3260 default: | 3149 default: |
| 3261 UNREACHABLE(); | 3150 UNREACHABLE(); |
| 3262 break; | 3151 break; |
| 3263 } | 3152 } |
| 3264 return; | 3153 return; |
| 3265 } // locs()->in(1).IsConstant(). | 3154 } // locs()->in(1).IsConstant(). |
| 3266 | 3155 |
| 3267 | |
| 3268 if (locs()->in(1).IsStackSlot()) { | 3156 if (locs()->in(1).IsStackSlot()) { |
| 3269 const Address& right = locs()->in(1).ToStackSlotAddress(); | 3157 const Address& right = locs()->in(1).ToStackSlotAddress(); |
| 3270 switch (op_kind()) { | 3158 switch (op_kind()) { |
| 3271 case Token::kADD: { | 3159 case Token::kADD: { |
| 3272 __ addq(left, right); | 3160 __ addq(left, right); |
| 3273 if (deopt != NULL) __ j(OVERFLOW, deopt); | 3161 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 3274 break; | 3162 break; |
| 3275 } | 3163 } |
| 3276 case Token::kSUB: { | 3164 case Token::kSUB: { |
| 3277 __ subq(left, right); | 3165 __ subq(left, right); |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3492 // behavior (short-circuit evaluation). | 3380 // behavior (short-circuit evaluation). |
| 3493 UNREACHABLE(); | 3381 UNREACHABLE(); |
| 3494 break; | 3382 break; |
| 3495 } | 3383 } |
| 3496 default: | 3384 default: |
| 3497 UNREACHABLE(); | 3385 UNREACHABLE(); |
| 3498 break; | 3386 break; |
| 3499 } | 3387 } |
| 3500 } | 3388 } |
| 3501 | 3389 |
| 3502 | |
| 3503 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3390 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
| 3504 bool opt) const { | 3391 bool opt) const { |
| 3505 intptr_t left_cid = left()->Type()->ToCid(); | 3392 intptr_t left_cid = left()->Type()->ToCid(); |
| 3506 intptr_t right_cid = right()->Type()->ToCid(); | 3393 intptr_t right_cid = right()->Type()->ToCid(); |
| 3507 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3394 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
| 3508 const intptr_t kNumInputs = 2; | 3395 const intptr_t kNumInputs = 2; |
| 3509 const bool need_temp = (left()->definition() != right()->definition()) && | 3396 const bool need_temp = (left()->definition() != right()->definition()) && |
| 3510 (left_cid != kSmiCid) && (right_cid != kSmiCid); | 3397 (left_cid != kSmiCid) && (right_cid != kSmiCid); |
| 3511 const intptr_t kNumTemps = need_temp ? 1 : 0; | 3398 const intptr_t kNumTemps = need_temp ? 1 : 0; |
| 3512 LocationSummary* summary = new (zone) | 3399 LocationSummary* summary = new (zone) |
| 3513 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3400 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3514 summary->set_in(0, Location::RequiresRegister()); | 3401 summary->set_in(0, Location::RequiresRegister()); |
| 3515 summary->set_in(1, Location::RequiresRegister()); | 3402 summary->set_in(1, Location::RequiresRegister()); |
| 3516 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); | 3403 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); |
| 3517 return summary; | 3404 return summary; |
| 3518 } | 3405 } |
| 3519 | 3406 |
| 3520 | |
| 3521 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3407 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3522 Label* deopt = | 3408 Label* deopt = |
| 3523 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, | 3409 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
| 3524 licm_hoisted_ ? ICData::kHoisted : 0); | 3410 licm_hoisted_ ? ICData::kHoisted : 0); |
| 3525 intptr_t left_cid = left()->Type()->ToCid(); | 3411 intptr_t left_cid = left()->Type()->ToCid(); |
| 3526 intptr_t right_cid = right()->Type()->ToCid(); | 3412 intptr_t right_cid = right()->Type()->ToCid(); |
| 3527 Register left = locs()->in(0).reg(); | 3413 Register left = locs()->in(0).reg(); |
| 3528 Register right = locs()->in(1).reg(); | 3414 Register right = locs()->in(1).reg(); |
| 3529 if (this->left()->definition() == this->right()->definition()) { | 3415 if (this->left()->definition() == this->right()->definition()) { |
| 3530 __ testq(left, Immediate(kSmiTagMask)); | 3416 __ testq(left, Immediate(kSmiTagMask)); |
| 3531 } else if (left_cid == kSmiCid) { | 3417 } else if (left_cid == kSmiCid) { |
| 3532 __ testq(right, Immediate(kSmiTagMask)); | 3418 __ testq(right, Immediate(kSmiTagMask)); |
| 3533 } else if (right_cid == kSmiCid) { | 3419 } else if (right_cid == kSmiCid) { |
| 3534 __ testq(left, Immediate(kSmiTagMask)); | 3420 __ testq(left, Immediate(kSmiTagMask)); |
| 3535 } else { | 3421 } else { |
| 3536 Register temp = locs()->temp(0).reg(); | 3422 Register temp = locs()->temp(0).reg(); |
| 3537 __ movq(temp, left); | 3423 __ movq(temp, left); |
| 3538 __ orq(temp, right); | 3424 __ orq(temp, right); |
| 3539 __ testq(temp, Immediate(kSmiTagMask)); | 3425 __ testq(temp, Immediate(kSmiTagMask)); |
| 3540 } | 3426 } |
| 3541 __ j(ZERO, deopt); | 3427 __ j(ZERO, deopt); |
| 3542 } | 3428 } |
| 3543 | 3429 |
| 3544 | |
| 3545 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 3430 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3546 const intptr_t kNumInputs = 1; | 3431 const intptr_t kNumInputs = 1; |
| 3547 const intptr_t kNumTemps = 1; | 3432 const intptr_t kNumTemps = 1; |
| 3548 LocationSummary* summary = new (zone) LocationSummary( | 3433 LocationSummary* summary = new (zone) LocationSummary( |
| 3549 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3434 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3550 summary->set_in(0, Location::RequiresFpuRegister()); | 3435 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3551 summary->set_temp(0, Location::RequiresRegister()); | 3436 summary->set_temp(0, Location::RequiresRegister()); |
| 3552 summary->set_out(0, Location::RequiresRegister()); | 3437 summary->set_out(0, Location::RequiresRegister()); |
| 3553 return summary; | 3438 return summary; |
| 3554 } | 3439 } |
| 3555 | 3440 |
| 3556 | |
| 3557 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3441 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3558 Register out_reg = locs()->out(0).reg(); | 3442 Register out_reg = locs()->out(0).reg(); |
| 3559 Register temp = locs()->temp(0).reg(); | 3443 Register temp = locs()->temp(0).reg(); |
| 3560 XmmRegister value = locs()->in(0).fpu_reg(); | 3444 XmmRegister value = locs()->in(0).fpu_reg(); |
| 3561 | 3445 |
| 3562 BoxAllocationSlowPath::Allocate(compiler, this, | 3446 BoxAllocationSlowPath::Allocate(compiler, this, |
| 3563 compiler->BoxClassFor(from_representation()), | 3447 compiler->BoxClassFor(from_representation()), |
| 3564 out_reg, temp); | 3448 out_reg, temp); |
| 3565 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); | 3449 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); |
| 3566 switch (from_representation()) { | 3450 switch (from_representation()) { |
| 3567 case kUnboxedDouble: | 3451 case kUnboxedDouble: |
| 3568 __ movsd(FieldAddress(out_reg, ValueOffset()), value); | 3452 __ movsd(FieldAddress(out_reg, ValueOffset()), value); |
| 3569 break; | 3453 break; |
| 3570 case kUnboxedFloat32x4: | 3454 case kUnboxedFloat32x4: |
| 3571 case kUnboxedFloat64x2: | 3455 case kUnboxedFloat64x2: |
| 3572 case kUnboxedInt32x4: | 3456 case kUnboxedInt32x4: |
| 3573 __ movups(FieldAddress(out_reg, ValueOffset()), value); | 3457 __ movups(FieldAddress(out_reg, ValueOffset()), value); |
| 3574 break; | 3458 break; |
| 3575 default: | 3459 default: |
| 3576 UNREACHABLE(); | 3460 UNREACHABLE(); |
| 3577 break; | 3461 break; |
| 3578 } | 3462 } |
| 3579 } | 3463 } |
| 3580 | 3464 |
| 3581 | |
| 3582 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 3465 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3583 const intptr_t kNumInputs = 1; | 3466 const intptr_t kNumInputs = 1; |
| 3584 const intptr_t kNumTemps = 0; | 3467 const intptr_t kNumTemps = 0; |
| 3585 const bool needs_writable_input = | 3468 const bool needs_writable_input = |
| 3586 (representation() != kUnboxedMint) && | 3469 (representation() != kUnboxedMint) && |
| 3587 (value()->Type()->ToNullableCid() != BoxCid()); | 3470 (value()->Type()->ToNullableCid() != BoxCid()); |
| 3588 LocationSummary* summary = new (zone) | 3471 LocationSummary* summary = new (zone) |
| 3589 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3472 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3590 summary->set_in(0, needs_writable_input ? Location::WritableRegister() | 3473 summary->set_in(0, needs_writable_input ? Location::WritableRegister() |
| 3591 : Location::RequiresRegister()); | 3474 : Location::RequiresRegister()); |
| 3592 if (representation() == kUnboxedMint) { | 3475 if (representation() == kUnboxedMint) { |
| 3593 summary->set_out(0, Location::SameAsFirstInput()); | 3476 summary->set_out(0, Location::SameAsFirstInput()); |
| 3594 } else { | 3477 } else { |
| 3595 summary->set_out(0, Location::RequiresFpuRegister()); | 3478 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3596 } | 3479 } |
| 3597 return summary; | 3480 return summary; |
| 3598 } | 3481 } |
| 3599 | 3482 |
| 3600 | |
| 3601 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { | 3483 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) { |
| 3602 const Register box = locs()->in(0).reg(); | 3484 const Register box = locs()->in(0).reg(); |
| 3603 | 3485 |
| 3604 switch (representation()) { | 3486 switch (representation()) { |
| 3605 case kUnboxedMint: { | 3487 case kUnboxedMint: { |
| 3606 const Register result = locs()->out(0).reg(); | 3488 const Register result = locs()->out(0).reg(); |
| 3607 __ movq(result, FieldAddress(box, ValueOffset())); | 3489 __ movq(result, FieldAddress(box, ValueOffset())); |
| 3608 break; | 3490 break; |
| 3609 } | 3491 } |
| 3610 | 3492 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3621 __ movups(result, FieldAddress(box, ValueOffset())); | 3503 __ movups(result, FieldAddress(box, ValueOffset())); |
| 3622 break; | 3504 break; |
| 3623 } | 3505 } |
| 3624 | 3506 |
| 3625 default: | 3507 default: |
| 3626 UNREACHABLE(); | 3508 UNREACHABLE(); |
| 3627 break; | 3509 break; |
| 3628 } | 3510 } |
| 3629 } | 3511 } |
| 3630 | 3512 |
| 3631 | |
| 3632 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { | 3513 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) { |
| 3633 const Register box = locs()->in(0).reg(); | 3514 const Register box = locs()->in(0).reg(); |
| 3634 | 3515 |
| 3635 switch (representation()) { | 3516 switch (representation()) { |
| 3636 case kUnboxedMint: { | 3517 case kUnboxedMint: { |
| 3637 const Register result = locs()->out(0).reg(); | 3518 const Register result = locs()->out(0).reg(); |
| 3638 ASSERT(result == box); | 3519 ASSERT(result == box); |
| 3639 __ SmiUntag(box); | 3520 __ SmiUntag(box); |
| 3640 break; | 3521 break; |
| 3641 } | 3522 } |
| 3642 | 3523 |
| 3643 case kUnboxedDouble: { | 3524 case kUnboxedDouble: { |
| 3644 const FpuRegister result = locs()->out(0).fpu_reg(); | 3525 const FpuRegister result = locs()->out(0).fpu_reg(); |
| 3645 __ SmiUntag(box); | 3526 __ SmiUntag(box); |
| 3646 __ cvtsi2sdq(result, box); | 3527 __ cvtsi2sdq(result, box); |
| 3647 break; | 3528 break; |
| 3648 } | 3529 } |
| 3649 | 3530 |
| 3650 default: | 3531 default: |
| 3651 UNREACHABLE(); | 3532 UNREACHABLE(); |
| 3652 break; | 3533 break; |
| 3653 } | 3534 } |
| 3654 } | 3535 } |
| 3655 | 3536 |
| 3656 | |
| 3657 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3537 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3658 const intptr_t value_cid = value()->Type()->ToCid(); | 3538 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3659 const intptr_t box_cid = BoxCid(); | 3539 const intptr_t box_cid = BoxCid(); |
| 3660 | 3540 |
| 3661 if (value_cid == box_cid) { | 3541 if (value_cid == box_cid) { |
| 3662 EmitLoadFromBox(compiler); | 3542 EmitLoadFromBox(compiler); |
| 3663 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 3543 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
| 3664 EmitSmiConversion(compiler); | 3544 EmitSmiConversion(compiler); |
| 3665 } else { | 3545 } else { |
| 3666 const Register box = locs()->in(0).reg(); | 3546 const Register box = locs()->in(0).reg(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3684 if (is_smi.IsLinked()) { | 3564 if (is_smi.IsLinked()) { |
| 3685 Label done; | 3565 Label done; |
| 3686 __ jmp(&done); | 3566 __ jmp(&done); |
| 3687 __ Bind(&is_smi); | 3567 __ Bind(&is_smi); |
| 3688 EmitSmiConversion(compiler); | 3568 EmitSmiConversion(compiler); |
| 3689 __ Bind(&done); | 3569 __ Bind(&done); |
| 3690 } | 3570 } |
| 3691 } | 3571 } |
| 3692 } | 3572 } |
| 3693 | 3573 |
| 3694 | |
| 3695 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 3574 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 3696 bool opt) const { | 3575 bool opt) const { |
| 3697 const intptr_t kNumInputs = 1; | 3576 const intptr_t kNumInputs = 1; |
| 3698 const intptr_t kNumTemps = (!is_truncating() && CanDeoptimize()) ? 1 : 0; | 3577 const intptr_t kNumTemps = (!is_truncating() && CanDeoptimize()) ? 1 : 0; |
| 3699 LocationSummary* summary = new (zone) | 3578 LocationSummary* summary = new (zone) |
| 3700 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3579 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3701 summary->set_in(0, Location::RequiresRegister()); | 3580 summary->set_in(0, Location::RequiresRegister()); |
| 3702 summary->set_out(0, Location::SameAsFirstInput()); | 3581 summary->set_out(0, Location::SameAsFirstInput()); |
| 3703 if (kNumTemps > 0) { | 3582 if (kNumTemps > 0) { |
| 3704 summary->set_temp(0, Location::RequiresRegister()); | 3583 summary->set_temp(0, Location::RequiresRegister()); |
| 3705 } | 3584 } |
| 3706 return summary; | 3585 return summary; |
| 3707 } | 3586 } |
| 3708 | 3587 |
| 3709 | |
| 3710 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3588 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3711 const intptr_t value_cid = value()->Type()->ToCid(); | 3589 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3712 const Register value = locs()->in(0).reg(); | 3590 const Register value = locs()->in(0).reg(); |
| 3713 Label* deopt = | 3591 Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub( |
| 3714 CanDeoptimize() | 3592 GetDeoptId(), ICData::kDeoptUnboxInteger) |
| 3715 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) | 3593 : NULL; |
| 3716 : NULL; | |
| 3717 ASSERT(value == locs()->out(0).reg()); | 3594 ASSERT(value == locs()->out(0).reg()); |
| 3718 | 3595 |
| 3719 if (value_cid == kSmiCid) { | 3596 if (value_cid == kSmiCid) { |
| 3720 __ SmiUntag(value); | 3597 __ SmiUntag(value); |
| 3721 } else if (value_cid == kMintCid) { | 3598 } else if (value_cid == kMintCid) { |
| 3722 __ movq(value, FieldAddress(value, Mint::value_offset())); | 3599 __ movq(value, FieldAddress(value, Mint::value_offset())); |
| 3723 } else if (!CanDeoptimize()) { | 3600 } else if (!CanDeoptimize()) { |
| 3724 // Type information is not conclusive, but range analysis found | 3601 // Type information is not conclusive, but range analysis found |
| 3725 // the value to be in int64 range. Therefore it must be a smi | 3602 // the value to be in int64 range. Therefore it must be a smi |
| 3726 // or mint value. | 3603 // or mint value. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3745 // leave "garbage" in the higher word. | 3622 // leave "garbage" in the higher word. |
| 3746 if (!is_truncating() && (deopt != NULL)) { | 3623 if (!is_truncating() && (deopt != NULL)) { |
| 3747 ASSERT(representation() == kUnboxedInt32); | 3624 ASSERT(representation() == kUnboxedInt32); |
| 3748 Register temp = locs()->temp(0).reg(); | 3625 Register temp = locs()->temp(0).reg(); |
| 3749 __ movsxd(temp, value); | 3626 __ movsxd(temp, value); |
| 3750 __ cmpq(temp, value); | 3627 __ cmpq(temp, value); |
| 3751 __ j(NOT_EQUAL, deopt); | 3628 __ j(NOT_EQUAL, deopt); |
| 3752 } | 3629 } |
| 3753 } | 3630 } |
| 3754 | 3631 |
| 3755 | |
| 3756 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 3632 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 3757 bool opt) const { | 3633 bool opt) const { |
| 3758 ASSERT((from_representation() == kUnboxedInt32) || | 3634 ASSERT((from_representation() == kUnboxedInt32) || |
| 3759 (from_representation() == kUnboxedUint32)); | 3635 (from_representation() == kUnboxedUint32)); |
| 3760 const intptr_t kNumInputs = 1; | 3636 const intptr_t kNumInputs = 1; |
| 3761 const intptr_t kNumTemps = 0; | 3637 const intptr_t kNumTemps = 0; |
| 3762 LocationSummary* summary = new (zone) | 3638 LocationSummary* summary = new (zone) |
| 3763 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3639 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3764 summary->set_in(0, Location::RequiresRegister()); | 3640 summary->set_in(0, Location::RequiresRegister()); |
| 3765 summary->set_out(0, Location::RequiresRegister()); | 3641 summary->set_out(0, Location::RequiresRegister()); |
| 3766 return summary; | 3642 return summary; |
| 3767 } | 3643 } |
| 3768 | 3644 |
| 3769 | |
| 3770 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3645 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3771 const Register value = locs()->in(0).reg(); | 3646 const Register value = locs()->in(0).reg(); |
| 3772 const Register out = locs()->out(0).reg(); | 3647 const Register out = locs()->out(0).reg(); |
| 3773 ASSERT(value != out); | 3648 ASSERT(value != out); |
| 3774 | 3649 |
| 3775 ASSERT(kSmiTagSize == 1); | 3650 ASSERT(kSmiTagSize == 1); |
| 3776 if (from_representation() == kUnboxedInt32) { | 3651 if (from_representation() == kUnboxedInt32) { |
| 3777 __ movsxd(out, value); | 3652 __ movsxd(out, value); |
| 3778 } else { | 3653 } else { |
| 3779 ASSERT(from_representation() == kUnboxedUint32); | 3654 ASSERT(from_representation() == kUnboxedUint32); |
| 3780 __ movl(out, value); | 3655 __ movl(out, value); |
| 3781 } | 3656 } |
| 3782 __ SmiTag(out); | 3657 __ SmiTag(out); |
| 3783 } | 3658 } |
| 3784 | 3659 |
| 3785 | |
| 3786 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, | 3660 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, |
| 3787 bool opt) const { | 3661 bool opt) const { |
| 3788 const intptr_t kNumInputs = 1; | 3662 const intptr_t kNumInputs = 1; |
| 3789 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 3663 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
| 3790 LocationSummary* summary = new (zone) | 3664 LocationSummary* summary = new (zone) |
| 3791 LocationSummary(zone, kNumInputs, kNumTemps, | 3665 LocationSummary(zone, kNumInputs, kNumTemps, |
| 3792 ValueFitsSmi() ? LocationSummary::kNoCall | 3666 ValueFitsSmi() ? LocationSummary::kNoCall |
| 3793 : LocationSummary::kCallOnSlowPath); | 3667 : LocationSummary::kCallOnSlowPath); |
| 3794 summary->set_in(0, Location::RequiresRegister()); | 3668 summary->set_in(0, Location::RequiresRegister()); |
| 3795 if (!ValueFitsSmi()) { | 3669 if (!ValueFitsSmi()) { |
| 3796 summary->set_temp(0, Location::RequiresRegister()); | 3670 summary->set_temp(0, Location::RequiresRegister()); |
| 3797 } | 3671 } |
| 3798 summary->set_out(0, Location::RequiresRegister()); | 3672 summary->set_out(0, Location::RequiresRegister()); |
| 3799 return summary; | 3673 return summary; |
| 3800 } | 3674 } |
| 3801 | 3675 |
| 3802 | |
| 3803 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3676 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3804 const Register out = locs()->out(0).reg(); | 3677 const Register out = locs()->out(0).reg(); |
| 3805 const Register value = locs()->in(0).reg(); | 3678 const Register value = locs()->in(0).reg(); |
| 3806 __ MoveRegister(out, value); | 3679 __ MoveRegister(out, value); |
| 3807 __ SmiTag(out); | 3680 __ SmiTag(out); |
| 3808 if (!ValueFitsSmi()) { | 3681 if (!ValueFitsSmi()) { |
| 3809 const Register temp = locs()->temp(0).reg(); | 3682 const Register temp = locs()->temp(0).reg(); |
| 3810 Label done; | 3683 Label done; |
| 3811 __ j(NO_OVERFLOW, &done); | 3684 __ j(NO_OVERFLOW, &done); |
| 3812 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out, | 3685 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out, |
| 3813 temp); | 3686 temp); |
| 3814 __ movq(FieldAddress(out, Mint::value_offset()), value); | 3687 __ movq(FieldAddress(out, Mint::value_offset()), value); |
| 3815 __ Bind(&done); | 3688 __ Bind(&done); |
| 3816 } | 3689 } |
| 3817 } | 3690 } |
| 3818 | 3691 |
| 3819 | |
| 3820 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 3692 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 3821 bool opt) const { | 3693 bool opt) const { |
| 3822 const intptr_t kNumInputs = 2; | 3694 const intptr_t kNumInputs = 2; |
| 3823 const intptr_t kNumTemps = 0; | 3695 const intptr_t kNumTemps = 0; |
| 3824 LocationSummary* summary = new (zone) | 3696 LocationSummary* summary = new (zone) |
| 3825 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3697 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3826 summary->set_in(0, Location::RequiresFpuRegister()); | 3698 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3827 summary->set_in(1, Location::RequiresFpuRegister()); | 3699 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3828 summary->set_out(0, Location::SameAsFirstInput()); | 3700 summary->set_out(0, Location::SameAsFirstInput()); |
| 3829 return summary; | 3701 return summary; |
| 3830 } | 3702 } |
| 3831 | 3703 |
| 3832 | |
| 3833 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3704 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3834 XmmRegister left = locs()->in(0).fpu_reg(); | 3705 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3835 XmmRegister right = locs()->in(1).fpu_reg(); | 3706 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3836 | 3707 |
| 3837 ASSERT(locs()->out(0).fpu_reg() == left); | 3708 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3838 | 3709 |
| 3839 switch (op_kind()) { | 3710 switch (op_kind()) { |
| 3840 case Token::kADD: | 3711 case Token::kADD: |
| 3841 __ addsd(left, right); | 3712 __ addsd(left, right); |
| 3842 break; | 3713 break; |
| 3843 case Token::kSUB: | 3714 case Token::kSUB: |
| 3844 __ subsd(left, right); | 3715 __ subsd(left, right); |
| 3845 break; | 3716 break; |
| 3846 case Token::kMUL: | 3717 case Token::kMUL: |
| 3847 __ mulsd(left, right); | 3718 __ mulsd(left, right); |
| 3848 break; | 3719 break; |
| 3849 case Token::kDIV: | 3720 case Token::kDIV: |
| 3850 __ divsd(left, right); | 3721 __ divsd(left, right); |
| 3851 break; | 3722 break; |
| 3852 default: | 3723 default: |
| 3853 UNREACHABLE(); | 3724 UNREACHABLE(); |
| 3854 } | 3725 } |
| 3855 } | 3726 } |
| 3856 | 3727 |
| 3857 | |
| 3858 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 3728 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |
| 3859 bool opt) const { | 3729 bool opt) const { |
| 3860 const intptr_t kNumInputs = 1; | 3730 const intptr_t kNumInputs = 1; |
| 3861 const intptr_t kNumTemps = | 3731 const intptr_t kNumTemps = |
| 3862 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; | 3732 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; |
| 3863 LocationSummary* summary = new (zone) | 3733 LocationSummary* summary = new (zone) |
| 3864 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3734 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3865 summary->set_in(0, Location::RequiresFpuRegister()); | 3735 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3866 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 3736 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
| 3867 summary->set_temp(0, Location::RequiresRegister()); | 3737 summary->set_temp(0, Location::RequiresRegister()); |
| 3868 } | 3738 } |
| 3869 summary->set_out(0, Location::RequiresRegister()); | 3739 summary->set_out(0, Location::RequiresRegister()); |
| 3870 return summary; | 3740 return summary; |
| 3871 } | 3741 } |
| 3872 | 3742 |
| 3873 | |
| 3874 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 3743 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 3875 BranchLabels labels) { | 3744 BranchLabels labels) { |
| 3876 ASSERT(compiler->is_optimizing()); | 3745 ASSERT(compiler->is_optimizing()); |
| 3877 const XmmRegister value = locs()->in(0).fpu_reg(); | 3746 const XmmRegister value = locs()->in(0).fpu_reg(); |
| 3878 const bool is_negated = kind() != Token::kEQ; | 3747 const bool is_negated = kind() != Token::kEQ; |
| 3879 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { | 3748 if (op_kind() == MethodRecognizer::kDouble_getIsNaN) { |
| 3880 Label is_nan; | 3749 Label is_nan; |
| 3881 __ comisd(value, value); | 3750 __ comisd(value, value); |
| 3882 return is_negated ? PARITY_ODD : PARITY_EVEN; | 3751 return is_negated ? PARITY_ODD : PARITY_EVEN; |
| 3883 } else { | 3752 } else { |
| 3884 ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite); | 3753 ASSERT(op_kind() == MethodRecognizer::kDouble_getIsInfinite); |
| 3885 const Register temp = locs()->temp(0).reg(); | 3754 const Register temp = locs()->temp(0).reg(); |
| 3886 __ AddImmediate(RSP, Immediate(-kDoubleSize)); | 3755 __ AddImmediate(RSP, Immediate(-kDoubleSize)); |
| 3887 __ movsd(Address(RSP, 0), value); | 3756 __ movsd(Address(RSP, 0), value); |
| 3888 __ movq(temp, Address(RSP, 0)); | 3757 __ movq(temp, Address(RSP, 0)); |
| 3889 __ AddImmediate(RSP, Immediate(kDoubleSize)); | 3758 __ AddImmediate(RSP, Immediate(kDoubleSize)); |
| 3890 // Mask off the sign. | 3759 // Mask off the sign. |
| 3891 __ AndImmediate(temp, Immediate(0x7FFFFFFFFFFFFFFFLL)); | 3760 __ AndImmediate(temp, Immediate(0x7FFFFFFFFFFFFFFFLL)); |
| 3892 // Compare with +infinity. | 3761 // Compare with +infinity. |
| 3893 __ CompareImmediate(temp, Immediate(0x7FF0000000000000LL)); | 3762 __ CompareImmediate(temp, Immediate(0x7FF0000000000000LL)); |
| 3894 return is_negated ? NOT_EQUAL : EQUAL; | 3763 return is_negated ? NOT_EQUAL : EQUAL; |
| 3895 } | 3764 } |
| 3896 } | 3765 } |
| 3897 | 3766 |
| 3898 | |
| 3899 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 3767 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 3900 bool opt) const { | 3768 bool opt) const { |
| 3901 const intptr_t kNumInputs = 2; | 3769 const intptr_t kNumInputs = 2; |
| 3902 const intptr_t kNumTemps = 0; | 3770 const intptr_t kNumTemps = 0; |
| 3903 LocationSummary* summary = new (zone) | 3771 LocationSummary* summary = new (zone) |
| 3904 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3772 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3905 summary->set_in(0, Location::RequiresFpuRegister()); | 3773 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3906 summary->set_in(1, Location::RequiresFpuRegister()); | 3774 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3907 summary->set_out(0, Location::SameAsFirstInput()); | 3775 summary->set_out(0, Location::SameAsFirstInput()); |
| 3908 return summary; | 3776 return summary; |
| 3909 } | 3777 } |
| 3910 | 3778 |
| 3911 | |
| 3912 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3779 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3913 XmmRegister left = locs()->in(0).fpu_reg(); | 3780 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3914 XmmRegister right = locs()->in(1).fpu_reg(); | 3781 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3915 | 3782 |
| 3916 ASSERT(locs()->out(0).fpu_reg() == left); | 3783 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3917 | 3784 |
| 3918 switch (op_kind()) { | 3785 switch (op_kind()) { |
| 3919 case Token::kADD: | 3786 case Token::kADD: |
| 3920 __ addps(left, right); | 3787 __ addps(left, right); |
| 3921 break; | 3788 break; |
| 3922 case Token::kSUB: | 3789 case Token::kSUB: |
| 3923 __ subps(left, right); | 3790 __ subps(left, right); |
| 3924 break; | 3791 break; |
| 3925 case Token::kMUL: | 3792 case Token::kMUL: |
| 3926 __ mulps(left, right); | 3793 __ mulps(left, right); |
| 3927 break; | 3794 break; |
| 3928 case Token::kDIV: | 3795 case Token::kDIV: |
| 3929 __ divps(left, right); | 3796 __ divps(left, right); |
| 3930 break; | 3797 break; |
| 3931 default: | 3798 default: |
| 3932 UNREACHABLE(); | 3799 UNREACHABLE(); |
| 3933 } | 3800 } |
| 3934 } | 3801 } |
| 3935 | 3802 |
| 3936 | |
| 3937 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, | 3803 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, |
| 3938 bool opt) const { | 3804 bool opt) const { |
| 3939 const intptr_t kNumInputs = 2; | 3805 const intptr_t kNumInputs = 2; |
| 3940 const intptr_t kNumTemps = 0; | 3806 const intptr_t kNumTemps = 0; |
| 3941 LocationSummary* summary = new (zone) | 3807 LocationSummary* summary = new (zone) |
| 3942 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3808 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3943 summary->set_in(0, Location::RequiresFpuRegister()); | 3809 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3944 summary->set_in(1, Location::RequiresFpuRegister()); | 3810 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3945 summary->set_out(0, Location::SameAsFirstInput()); | 3811 summary->set_out(0, Location::SameAsFirstInput()); |
| 3946 return summary; | 3812 return summary; |
| 3947 } | 3813 } |
| 3948 | 3814 |
| 3949 | |
| 3950 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3815 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3951 XmmRegister left = locs()->in(0).fpu_reg(); | 3816 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3952 XmmRegister right = locs()->in(1).fpu_reg(); | 3817 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3953 | 3818 |
| 3954 ASSERT(locs()->out(0).fpu_reg() == left); | 3819 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3955 | 3820 |
| 3956 switch (op_kind()) { | 3821 switch (op_kind()) { |
| 3957 case Token::kADD: | 3822 case Token::kADD: |
| 3958 __ addpd(left, right); | 3823 __ addpd(left, right); |
| 3959 break; | 3824 break; |
| 3960 case Token::kSUB: | 3825 case Token::kSUB: |
| 3961 __ subpd(left, right); | 3826 __ subpd(left, right); |
| 3962 break; | 3827 break; |
| 3963 case Token::kMUL: | 3828 case Token::kMUL: |
| 3964 __ mulpd(left, right); | 3829 __ mulpd(left, right); |
| 3965 break; | 3830 break; |
| 3966 case Token::kDIV: | 3831 case Token::kDIV: |
| 3967 __ divpd(left, right); | 3832 __ divpd(left, right); |
| 3968 break; | 3833 break; |
| 3969 default: | 3834 default: |
| 3970 UNREACHABLE(); | 3835 UNREACHABLE(); |
| 3971 } | 3836 } |
| 3972 } | 3837 } |
| 3973 | 3838 |
| 3974 | |
| 3975 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, | 3839 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 3976 bool opt) const { | 3840 bool opt) const { |
| 3977 const intptr_t kNumInputs = 1; | 3841 const intptr_t kNumInputs = 1; |
| 3978 const intptr_t kNumTemps = 0; | 3842 const intptr_t kNumTemps = 0; |
| 3979 LocationSummary* summary = new (zone) | 3843 LocationSummary* summary = new (zone) |
| 3980 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3844 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3981 summary->set_in(0, Location::RequiresFpuRegister()); | 3845 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3982 summary->set_out(0, Location::SameAsFirstInput()); | 3846 summary->set_out(0, Location::SameAsFirstInput()); |
| 3983 return summary; | 3847 return summary; |
| 3984 } | 3848 } |
| 3985 | 3849 |
| 3986 | |
| 3987 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3850 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3988 XmmRegister value = locs()->in(0).fpu_reg(); | 3851 XmmRegister value = locs()->in(0).fpu_reg(); |
| 3989 | 3852 |
| 3990 ASSERT(locs()->out(0).fpu_reg() == value); | 3853 ASSERT(locs()->out(0).fpu_reg() == value); |
| 3991 | 3854 |
| 3992 switch (op_kind()) { | 3855 switch (op_kind()) { |
| 3993 case MethodRecognizer::kFloat32x4ShuffleX: | 3856 case MethodRecognizer::kFloat32x4ShuffleX: |
| 3994 // Shuffle not necessary. | 3857 // Shuffle not necessary. |
| 3995 __ cvtss2sd(value, value); | 3858 __ cvtss2sd(value, value); |
| 3996 break; | 3859 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4008 break; | 3871 break; |
| 4009 case MethodRecognizer::kFloat32x4Shuffle: | 3872 case MethodRecognizer::kFloat32x4Shuffle: |
| 4010 case MethodRecognizer::kInt32x4Shuffle: | 3873 case MethodRecognizer::kInt32x4Shuffle: |
| 4011 __ shufps(value, value, Immediate(mask_)); | 3874 __ shufps(value, value, Immediate(mask_)); |
| 4012 break; | 3875 break; |
| 4013 default: | 3876 default: |
| 4014 UNREACHABLE(); | 3877 UNREACHABLE(); |
| 4015 } | 3878 } |
| 4016 } | 3879 } |
| 4017 | 3880 |
| 4018 | |
| 4019 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 3881 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |
| 4020 bool opt) const { | 3882 bool opt) const { |
| 4021 const intptr_t kNumInputs = 2; | 3883 const intptr_t kNumInputs = 2; |
| 4022 const intptr_t kNumTemps = 0; | 3884 const intptr_t kNumTemps = 0; |
| 4023 LocationSummary* summary = new (zone) | 3885 LocationSummary* summary = new (zone) |
| 4024 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3886 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4025 summary->set_in(0, Location::RequiresFpuRegister()); | 3887 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4026 summary->set_in(1, Location::RequiresFpuRegister()); | 3888 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4027 summary->set_out(0, Location::SameAsFirstInput()); | 3889 summary->set_out(0, Location::SameAsFirstInput()); |
| 4028 return summary; | 3890 return summary; |
| 4029 } | 3891 } |
| 4030 | 3892 |
| 4031 | |
| 4032 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3893 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4033 XmmRegister left = locs()->in(0).fpu_reg(); | 3894 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4034 XmmRegister right = locs()->in(1).fpu_reg(); | 3895 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4035 | 3896 |
| 4036 ASSERT(locs()->out(0).fpu_reg() == left); | 3897 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4037 switch (op_kind()) { | 3898 switch (op_kind()) { |
| 4038 case MethodRecognizer::kFloat32x4ShuffleMix: | 3899 case MethodRecognizer::kFloat32x4ShuffleMix: |
| 4039 case MethodRecognizer::kInt32x4ShuffleMix: | 3900 case MethodRecognizer::kInt32x4ShuffleMix: |
| 4040 __ shufps(left, right, Immediate(mask_)); | 3901 __ shufps(left, right, Immediate(mask_)); |
| 4041 break; | 3902 break; |
| 4042 default: | 3903 default: |
| 4043 UNREACHABLE(); | 3904 UNREACHABLE(); |
| 4044 } | 3905 } |
| 4045 } | 3906 } |
| 4046 | 3907 |
| 4047 | |
| 4048 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, | 3908 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, |
| 4049 bool opt) const { | 3909 bool opt) const { |
| 4050 const intptr_t kNumInputs = 1; | 3910 const intptr_t kNumInputs = 1; |
| 4051 const intptr_t kNumTemps = 0; | 3911 const intptr_t kNumTemps = 0; |
| 4052 LocationSummary* summary = new (zone) | 3912 LocationSummary* summary = new (zone) |
| 4053 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3913 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4054 summary->set_in(0, Location::RequiresFpuRegister()); | 3914 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4055 summary->set_out(0, Location::RequiresRegister()); | 3915 summary->set_out(0, Location::RequiresRegister()); |
| 4056 return summary; | 3916 return summary; |
| 4057 } | 3917 } |
| 4058 | 3918 |
| 4059 | |
| 4060 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3919 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4061 XmmRegister value = locs()->in(0).fpu_reg(); | 3920 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4062 Register out = locs()->out(0).reg(); | 3921 Register out = locs()->out(0).reg(); |
| 4063 | 3922 |
| 4064 __ movmskps(out, value); | 3923 __ movmskps(out, value); |
| 4065 __ SmiTag(out); | 3924 __ SmiTag(out); |
| 4066 } | 3925 } |
| 4067 | 3926 |
| 4068 | |
| 4069 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 3927 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
| 4070 Zone* zone, | 3928 Zone* zone, |
| 4071 bool opt) const { | 3929 bool opt) const { |
| 4072 const intptr_t kNumInputs = 4; | 3930 const intptr_t kNumInputs = 4; |
| 4073 const intptr_t kNumTemps = 0; | 3931 const intptr_t kNumTemps = 0; |
| 4074 LocationSummary* summary = new (zone) | 3932 LocationSummary* summary = new (zone) |
| 4075 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3933 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4076 summary->set_in(0, Location::RequiresFpuRegister()); | 3934 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4077 summary->set_in(1, Location::RequiresFpuRegister()); | 3935 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4078 summary->set_in(2, Location::RequiresFpuRegister()); | 3936 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4079 summary->set_in(3, Location::RequiresFpuRegister()); | 3937 summary->set_in(3, Location::RequiresFpuRegister()); |
| 4080 summary->set_out(0, Location::SameAsFirstInput()); | 3938 summary->set_out(0, Location::SameAsFirstInput()); |
| 4081 return summary; | 3939 return summary; |
| 4082 } | 3940 } |
| 4083 | 3941 |
| 4084 | |
| 4085 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3942 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4086 XmmRegister v0 = locs()->in(0).fpu_reg(); | 3943 XmmRegister v0 = locs()->in(0).fpu_reg(); |
| 4087 XmmRegister v1 = locs()->in(1).fpu_reg(); | 3944 XmmRegister v1 = locs()->in(1).fpu_reg(); |
| 4088 XmmRegister v2 = locs()->in(2).fpu_reg(); | 3945 XmmRegister v2 = locs()->in(2).fpu_reg(); |
| 4089 XmmRegister v3 = locs()->in(3).fpu_reg(); | 3946 XmmRegister v3 = locs()->in(3).fpu_reg(); |
| 4090 ASSERT(v0 == locs()->out(0).fpu_reg()); | 3947 ASSERT(v0 == locs()->out(0).fpu_reg()); |
| 4091 __ AddImmediate(RSP, Immediate(-16)); | 3948 __ AddImmediate(RSP, Immediate(-16)); |
| 4092 __ cvtsd2ss(v0, v0); | 3949 __ cvtsd2ss(v0, v0); |
| 4093 __ movss(Address(RSP, 0), v0); | 3950 __ movss(Address(RSP, 0), v0); |
| 4094 __ movsd(v0, v1); | 3951 __ movsd(v0, v1); |
| 4095 __ cvtsd2ss(v0, v0); | 3952 __ cvtsd2ss(v0, v0); |
| 4096 __ movss(Address(RSP, 4), v0); | 3953 __ movss(Address(RSP, 4), v0); |
| 4097 __ movsd(v0, v2); | 3954 __ movsd(v0, v2); |
| 4098 __ cvtsd2ss(v0, v0); | 3955 __ cvtsd2ss(v0, v0); |
| 4099 __ movss(Address(RSP, 8), v0); | 3956 __ movss(Address(RSP, 8), v0); |
| 4100 __ movsd(v0, v3); | 3957 __ movsd(v0, v3); |
| 4101 __ cvtsd2ss(v0, v0); | 3958 __ cvtsd2ss(v0, v0); |
| 4102 __ movss(Address(RSP, 12), v0); | 3959 __ movss(Address(RSP, 12), v0); |
| 4103 __ movups(v0, Address(RSP, 0)); | 3960 __ movups(v0, Address(RSP, 0)); |
| 4104 __ AddImmediate(RSP, Immediate(16)); | 3961 __ AddImmediate(RSP, Immediate(16)); |
| 4105 } | 3962 } |
| 4106 | 3963 |
| 4107 | |
| 4108 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, | 3964 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, |
| 4109 bool opt) const { | 3965 bool opt) const { |
| 4110 const intptr_t kNumInputs = 0; | 3966 const intptr_t kNumInputs = 0; |
| 4111 const intptr_t kNumTemps = 0; | 3967 const intptr_t kNumTemps = 0; |
| 4112 LocationSummary* summary = new (zone) | 3968 LocationSummary* summary = new (zone) |
| 4113 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3969 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4114 summary->set_out(0, Location::RequiresFpuRegister()); | 3970 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4115 return summary; | 3971 return summary; |
| 4116 } | 3972 } |
| 4117 | 3973 |
| 4118 | |
| 4119 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3974 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4120 XmmRegister value = locs()->out(0).fpu_reg(); | 3975 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4121 __ xorps(value, value); | 3976 __ xorps(value, value); |
| 4122 } | 3977 } |
| 4123 | 3978 |
| 4124 | |
| 4125 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, | 3979 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, |
| 4126 bool opt) const { | 3980 bool opt) const { |
| 4127 const intptr_t kNumInputs = 1; | 3981 const intptr_t kNumInputs = 1; |
| 4128 const intptr_t kNumTemps = 0; | 3982 const intptr_t kNumTemps = 0; |
| 4129 LocationSummary* summary = new (zone) | 3983 LocationSummary* summary = new (zone) |
| 4130 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3984 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4131 summary->set_in(0, Location::RequiresFpuRegister()); | 3985 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4132 summary->set_out(0, Location::SameAsFirstInput()); | 3986 summary->set_out(0, Location::SameAsFirstInput()); |
| 4133 return summary; | 3987 return summary; |
| 4134 } | 3988 } |
| 4135 | 3989 |
| 4136 | |
| 4137 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3990 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4138 XmmRegister value = locs()->out(0).fpu_reg(); | 3991 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4139 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); | 3992 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); |
| 4140 // Convert to Float32. | 3993 // Convert to Float32. |
| 4141 __ cvtsd2ss(value, value); | 3994 __ cvtsd2ss(value, value); |
| 4142 // Splat across all lanes. | 3995 // Splat across all lanes. |
| 4143 __ shufps(value, value, Immediate(0x00)); | 3996 __ shufps(value, value, Immediate(0x00)); |
| 4144 } | 3997 } |
| 4145 | 3998 |
| 4146 | |
| 4147 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, | 3999 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, |
| 4148 bool opt) const { | 4000 bool opt) const { |
| 4149 const intptr_t kNumInputs = 2; | 4001 const intptr_t kNumInputs = 2; |
| 4150 const intptr_t kNumTemps = 0; | 4002 const intptr_t kNumTemps = 0; |
| 4151 LocationSummary* summary = new (zone) | 4003 LocationSummary* summary = new (zone) |
| 4152 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4004 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4153 summary->set_in(0, Location::RequiresFpuRegister()); | 4005 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4154 summary->set_in(1, Location::RequiresFpuRegister()); | 4006 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4155 summary->set_out(0, Location::SameAsFirstInput()); | 4007 summary->set_out(0, Location::SameAsFirstInput()); |
| 4156 return summary; | 4008 return summary; |
| 4157 } | 4009 } |
| 4158 | 4010 |
| 4159 | |
| 4160 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4011 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4161 XmmRegister left = locs()->in(0).fpu_reg(); | 4012 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4162 XmmRegister right = locs()->in(1).fpu_reg(); | 4013 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4163 | 4014 |
| 4164 ASSERT(locs()->out(0).fpu_reg() == left); | 4015 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4165 | 4016 |
| 4166 switch (op_kind()) { | 4017 switch (op_kind()) { |
| 4167 case MethodRecognizer::kFloat32x4Equal: | 4018 case MethodRecognizer::kFloat32x4Equal: |
| 4168 __ cmppseq(left, right); | 4019 __ cmppseq(left, right); |
| 4169 break; | 4020 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4181 break; | 4032 break; |
| 4182 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 4033 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
| 4183 __ cmppsle(left, right); | 4034 __ cmppsle(left, right); |
| 4184 break; | 4035 break; |
| 4185 | 4036 |
| 4186 default: | 4037 default: |
| 4187 UNREACHABLE(); | 4038 UNREACHABLE(); |
| 4188 } | 4039 } |
| 4189 } | 4040 } |
| 4190 | 4041 |
| 4191 | |
| 4192 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, | 4042 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, |
| 4193 bool opt) const { | 4043 bool opt) const { |
| 4194 const intptr_t kNumInputs = 2; | 4044 const intptr_t kNumInputs = 2; |
| 4195 const intptr_t kNumTemps = 0; | 4045 const intptr_t kNumTemps = 0; |
| 4196 LocationSummary* summary = new (zone) | 4046 LocationSummary* summary = new (zone) |
| 4197 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4047 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4198 summary->set_in(0, Location::RequiresFpuRegister()); | 4048 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4199 summary->set_in(1, Location::RequiresFpuRegister()); | 4049 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4200 summary->set_out(0, Location::SameAsFirstInput()); | 4050 summary->set_out(0, Location::SameAsFirstInput()); |
| 4201 return summary; | 4051 return summary; |
| 4202 } | 4052 } |
| 4203 | 4053 |
| 4204 | |
| 4205 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4054 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4206 XmmRegister left = locs()->in(0).fpu_reg(); | 4055 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4207 XmmRegister right = locs()->in(1).fpu_reg(); | 4056 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4208 | 4057 |
| 4209 ASSERT(locs()->out(0).fpu_reg() == left); | 4058 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4210 | 4059 |
| 4211 switch (op_kind()) { | 4060 switch (op_kind()) { |
| 4212 case MethodRecognizer::kFloat32x4Min: | 4061 case MethodRecognizer::kFloat32x4Min: |
| 4213 __ minps(left, right); | 4062 __ minps(left, right); |
| 4214 break; | 4063 break; |
| 4215 case MethodRecognizer::kFloat32x4Max: | 4064 case MethodRecognizer::kFloat32x4Max: |
| 4216 __ maxps(left, right); | 4065 __ maxps(left, right); |
| 4217 break; | 4066 break; |
| 4218 default: | 4067 default: |
| 4219 UNREACHABLE(); | 4068 UNREACHABLE(); |
| 4220 } | 4069 } |
| 4221 } | 4070 } |
| 4222 | 4071 |
| 4223 | |
| 4224 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, | 4072 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, |
| 4225 bool opt) const { | 4073 bool opt) const { |
| 4226 const intptr_t kNumInputs = 2; | 4074 const intptr_t kNumInputs = 2; |
| 4227 const intptr_t kNumTemps = 0; | 4075 const intptr_t kNumTemps = 0; |
| 4228 LocationSummary* summary = new (zone) | 4076 LocationSummary* summary = new (zone) |
| 4229 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4077 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4230 summary->set_in(0, Location::RequiresFpuRegister()); | 4078 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4231 summary->set_in(1, Location::RequiresFpuRegister()); | 4079 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4232 summary->set_out(0, Location::SameAsFirstInput()); | 4080 summary->set_out(0, Location::SameAsFirstInput()); |
| 4233 return summary; | 4081 return summary; |
| 4234 } | 4082 } |
| 4235 | 4083 |
| 4236 | |
| 4237 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4084 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4238 XmmRegister left = locs()->in(0).fpu_reg(); | 4085 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4239 XmmRegister right = locs()->in(1).fpu_reg(); | 4086 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4240 | 4087 |
| 4241 ASSERT(locs()->out(0).fpu_reg() == left); | 4088 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4242 | 4089 |
| 4243 switch (op_kind()) { | 4090 switch (op_kind()) { |
| 4244 case MethodRecognizer::kFloat32x4Scale: | 4091 case MethodRecognizer::kFloat32x4Scale: |
| 4245 __ cvtsd2ss(left, left); | 4092 __ cvtsd2ss(left, left); |
| 4246 __ shufps(left, left, Immediate(0x00)); | 4093 __ shufps(left, left, Immediate(0x00)); |
| 4247 __ mulps(left, right); | 4094 __ mulps(left, right); |
| 4248 break; | 4095 break; |
| 4249 default: | 4096 default: |
| 4250 UNREACHABLE(); | 4097 UNREACHABLE(); |
| 4251 } | 4098 } |
| 4252 } | 4099 } |
| 4253 | 4100 |
| 4254 | |
| 4255 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, | 4101 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, |
| 4256 bool opt) const { | 4102 bool opt) const { |
| 4257 const intptr_t kNumInputs = 1; | 4103 const intptr_t kNumInputs = 1; |
| 4258 const intptr_t kNumTemps = 0; | 4104 const intptr_t kNumTemps = 0; |
| 4259 LocationSummary* summary = new (zone) | 4105 LocationSummary* summary = new (zone) |
| 4260 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4106 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4261 summary->set_in(0, Location::RequiresFpuRegister()); | 4107 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4262 summary->set_out(0, Location::SameAsFirstInput()); | 4108 summary->set_out(0, Location::SameAsFirstInput()); |
| 4263 return summary; | 4109 return summary; |
| 4264 } | 4110 } |
| 4265 | 4111 |
| 4266 | |
| 4267 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4112 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4268 XmmRegister left = locs()->in(0).fpu_reg(); | 4113 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4269 | 4114 |
| 4270 ASSERT(locs()->out(0).fpu_reg() == left); | 4115 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4271 | 4116 |
| 4272 switch (op_kind()) { | 4117 switch (op_kind()) { |
| 4273 case MethodRecognizer::kFloat32x4Sqrt: | 4118 case MethodRecognizer::kFloat32x4Sqrt: |
| 4274 __ sqrtps(left); | 4119 __ sqrtps(left); |
| 4275 break; | 4120 break; |
| 4276 case MethodRecognizer::kFloat32x4Reciprocal: | 4121 case MethodRecognizer::kFloat32x4Reciprocal: |
| 4277 __ reciprocalps(left); | 4122 __ reciprocalps(left); |
| 4278 break; | 4123 break; |
| 4279 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 4124 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
| 4280 __ rsqrtps(left); | 4125 __ rsqrtps(left); |
| 4281 break; | 4126 break; |
| 4282 default: | 4127 default: |
| 4283 UNREACHABLE(); | 4128 UNREACHABLE(); |
| 4284 } | 4129 } |
| 4285 } | 4130 } |
| 4286 | 4131 |
| 4287 | |
| 4288 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4132 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, |
| 4289 bool opt) const { | 4133 bool opt) const { |
| 4290 const intptr_t kNumInputs = 1; | 4134 const intptr_t kNumInputs = 1; |
| 4291 const intptr_t kNumTemps = 0; | 4135 const intptr_t kNumTemps = 0; |
| 4292 LocationSummary* summary = new (zone) | 4136 LocationSummary* summary = new (zone) |
| 4293 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4137 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4294 summary->set_in(0, Location::RequiresFpuRegister()); | 4138 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4295 summary->set_out(0, Location::SameAsFirstInput()); | 4139 summary->set_out(0, Location::SameAsFirstInput()); |
| 4296 return summary; | 4140 return summary; |
| 4297 } | 4141 } |
| 4298 | 4142 |
| 4299 | |
| 4300 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4143 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4301 XmmRegister left = locs()->in(0).fpu_reg(); | 4144 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4302 | 4145 |
| 4303 ASSERT(locs()->out(0).fpu_reg() == left); | 4146 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4304 switch (op_kind()) { | 4147 switch (op_kind()) { |
| 4305 case MethodRecognizer::kFloat32x4Negate: | 4148 case MethodRecognizer::kFloat32x4Negate: |
| 4306 __ negateps(left); | 4149 __ negateps(left); |
| 4307 break; | 4150 break; |
| 4308 case MethodRecognizer::kFloat32x4Absolute: | 4151 case MethodRecognizer::kFloat32x4Absolute: |
| 4309 __ absps(left); | 4152 __ absps(left); |
| 4310 break; | 4153 break; |
| 4311 default: | 4154 default: |
| 4312 UNREACHABLE(); | 4155 UNREACHABLE(); |
| 4313 } | 4156 } |
| 4314 } | 4157 } |
| 4315 | 4158 |
| 4316 | |
| 4317 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, | 4159 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, |
| 4318 bool opt) const { | 4160 bool opt) const { |
| 4319 const intptr_t kNumInputs = 3; | 4161 const intptr_t kNumInputs = 3; |
| 4320 const intptr_t kNumTemps = 0; | 4162 const intptr_t kNumTemps = 0; |
| 4321 LocationSummary* summary = new (zone) | 4163 LocationSummary* summary = new (zone) |
| 4322 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4164 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4323 summary->set_in(0, Location::RequiresFpuRegister()); | 4165 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4324 summary->set_in(1, Location::RequiresFpuRegister()); | 4166 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4325 summary->set_in(2, Location::RequiresFpuRegister()); | 4167 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4326 summary->set_out(0, Location::SameAsFirstInput()); | 4168 summary->set_out(0, Location::SameAsFirstInput()); |
| 4327 return summary; | 4169 return summary; |
| 4328 } | 4170 } |
| 4329 | 4171 |
| 4330 | |
| 4331 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4172 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4332 XmmRegister left = locs()->in(0).fpu_reg(); | 4173 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4333 XmmRegister lower = locs()->in(1).fpu_reg(); | 4174 XmmRegister lower = locs()->in(1).fpu_reg(); |
| 4334 XmmRegister upper = locs()->in(2).fpu_reg(); | 4175 XmmRegister upper = locs()->in(2).fpu_reg(); |
| 4335 ASSERT(locs()->out(0).fpu_reg() == left); | 4176 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4336 __ minps(left, upper); | 4177 __ minps(left, upper); |
| 4337 __ maxps(left, lower); | 4178 __ maxps(left, lower); |
| 4338 } | 4179 } |
| 4339 | 4180 |
| 4340 | |
| 4341 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, | 4181 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, |
| 4342 bool opt) const { | 4182 bool opt) const { |
| 4343 const intptr_t kNumInputs = 2; | 4183 const intptr_t kNumInputs = 2; |
| 4344 const intptr_t kNumTemps = 0; | 4184 const intptr_t kNumTemps = 0; |
| 4345 LocationSummary* summary = new (zone) | 4185 LocationSummary* summary = new (zone) |
| 4346 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4186 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4347 summary->set_in(0, Location::RequiresFpuRegister()); | 4187 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4348 summary->set_in(1, Location::RequiresFpuRegister()); | 4188 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4349 summary->set_out(0, Location::SameAsFirstInput()); | 4189 summary->set_out(0, Location::SameAsFirstInput()); |
| 4350 return summary; | 4190 return summary; |
| 4351 } | 4191 } |
| 4352 | 4192 |
| 4353 | |
| 4354 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4193 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4355 XmmRegister replacement = locs()->in(0).fpu_reg(); | 4194 XmmRegister replacement = locs()->in(0).fpu_reg(); |
| 4356 XmmRegister value = locs()->in(1).fpu_reg(); | 4195 XmmRegister value = locs()->in(1).fpu_reg(); |
| 4357 | 4196 |
| 4358 ASSERT(locs()->out(0).fpu_reg() == replacement); | 4197 ASSERT(locs()->out(0).fpu_reg() == replacement); |
| 4359 | 4198 |
| 4360 switch (op_kind()) { | 4199 switch (op_kind()) { |
| 4361 case MethodRecognizer::kFloat32x4WithX: | 4200 case MethodRecognizer::kFloat32x4WithX: |
| 4362 __ cvtsd2ss(replacement, replacement); | 4201 __ cvtsd2ss(replacement, replacement); |
| 4363 __ AddImmediate(RSP, Immediate(-16)); | 4202 __ AddImmediate(RSP, Immediate(-16)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4400 __ movss(Address(RSP, 12), replacement); | 4239 __ movss(Address(RSP, 12), replacement); |
| 4401 // Move updated value into output register. | 4240 // Move updated value into output register. |
| 4402 __ movups(replacement, Address(RSP, 0)); | 4241 __ movups(replacement, Address(RSP, 0)); |
| 4403 __ AddImmediate(RSP, Immediate(16)); | 4242 __ AddImmediate(RSP, Immediate(16)); |
| 4404 break; | 4243 break; |
| 4405 default: | 4244 default: |
| 4406 UNREACHABLE(); | 4245 UNREACHABLE(); |
| 4407 } | 4246 } |
| 4408 } | 4247 } |
| 4409 | 4248 |
| 4410 | |
| 4411 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, | 4249 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, |
| 4412 bool opt) const { | 4250 bool opt) const { |
| 4413 const intptr_t kNumInputs = 1; | 4251 const intptr_t kNumInputs = 1; |
| 4414 const intptr_t kNumTemps = 0; | 4252 const intptr_t kNumTemps = 0; |
| 4415 LocationSummary* summary = new (zone) | 4253 LocationSummary* summary = new (zone) |
| 4416 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4254 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4417 summary->set_in(0, Location::RequiresFpuRegister()); | 4255 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4418 summary->set_out(0, Location::SameAsFirstInput()); | 4256 summary->set_out(0, Location::SameAsFirstInput()); |
| 4419 return summary; | 4257 return summary; |
| 4420 } | 4258 } |
| 4421 | 4259 |
| 4422 | |
| 4423 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4260 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4424 // NOP. | 4261 // NOP. |
| 4425 } | 4262 } |
| 4426 | 4263 |
| 4427 | |
| 4428 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 4264 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 4429 bool opt) const { | 4265 bool opt) const { |
| 4430 const intptr_t kNumInputs = 1; | 4266 const intptr_t kNumInputs = 1; |
| 4431 const intptr_t kNumTemps = 0; | 4267 const intptr_t kNumTemps = 0; |
| 4432 LocationSummary* summary = new (zone) | 4268 LocationSummary* summary = new (zone) |
| 4433 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4269 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4434 summary->set_in(0, Location::RequiresFpuRegister()); | 4270 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4435 summary->set_out(0, Location::SameAsFirstInput()); | 4271 summary->set_out(0, Location::SameAsFirstInput()); |
| 4436 return summary; | 4272 return summary; |
| 4437 } | 4273 } |
| 4438 | 4274 |
| 4439 | |
| 4440 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4275 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4441 XmmRegister value = locs()->in(0).fpu_reg(); | 4276 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4442 | 4277 |
| 4443 ASSERT(locs()->out(0).fpu_reg() == value); | 4278 ASSERT(locs()->out(0).fpu_reg() == value); |
| 4444 switch (op_kind()) { | 4279 switch (op_kind()) { |
| 4445 case MethodRecognizer::kFloat64x2GetX: | 4280 case MethodRecognizer::kFloat64x2GetX: |
| 4446 // nop. | 4281 // nop. |
| 4447 break; | 4282 break; |
| 4448 case MethodRecognizer::kFloat64x2GetY: | 4283 case MethodRecognizer::kFloat64x2GetY: |
| 4449 __ shufpd(value, value, Immediate(0x33)); | 4284 __ shufpd(value, value, Immediate(0x33)); |
| 4450 break; | 4285 break; |
| 4451 default: | 4286 default: |
| 4452 UNREACHABLE(); | 4287 UNREACHABLE(); |
| 4453 } | 4288 } |
| 4454 } | 4289 } |
| 4455 | 4290 |
| 4456 | |
| 4457 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 4291 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |
| 4458 bool opt) const { | 4292 bool opt) const { |
| 4459 const intptr_t kNumInputs = 0; | 4293 const intptr_t kNumInputs = 0; |
| 4460 const intptr_t kNumTemps = 0; | 4294 const intptr_t kNumTemps = 0; |
| 4461 LocationSummary* summary = new (zone) | 4295 LocationSummary* summary = new (zone) |
| 4462 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4296 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4463 summary->set_out(0, Location::RequiresFpuRegister()); | 4297 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4464 return summary; | 4298 return summary; |
| 4465 } | 4299 } |
| 4466 | 4300 |
| 4467 | |
| 4468 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4301 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4469 XmmRegister value = locs()->out(0).fpu_reg(); | 4302 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4470 __ xorpd(value, value); | 4303 __ xorpd(value, value); |
| 4471 } | 4304 } |
| 4472 | 4305 |
| 4473 | |
| 4474 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 4306 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |
| 4475 bool opt) const { | 4307 bool opt) const { |
| 4476 const intptr_t kNumInputs = 1; | 4308 const intptr_t kNumInputs = 1; |
| 4477 const intptr_t kNumTemps = 0; | 4309 const intptr_t kNumTemps = 0; |
| 4478 LocationSummary* summary = new (zone) | 4310 LocationSummary* summary = new (zone) |
| 4479 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4311 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4480 summary->set_in(0, Location::RequiresFpuRegister()); | 4312 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4481 summary->set_out(0, Location::SameAsFirstInput()); | 4313 summary->set_out(0, Location::SameAsFirstInput()); |
| 4482 return summary; | 4314 return summary; |
| 4483 } | 4315 } |
| 4484 | 4316 |
| 4485 | |
| 4486 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4317 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4487 XmmRegister value = locs()->out(0).fpu_reg(); | 4318 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4488 __ shufpd(value, value, Immediate(0x0)); | 4319 __ shufpd(value, value, Immediate(0x0)); |
| 4489 } | 4320 } |
| 4490 | 4321 |
| 4491 | |
| 4492 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 4322 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
| 4493 Zone* zone, | 4323 Zone* zone, |
| 4494 bool opt) const { | 4324 bool opt) const { |
| 4495 const intptr_t kNumInputs = 2; | 4325 const intptr_t kNumInputs = 2; |
| 4496 const intptr_t kNumTemps = 0; | 4326 const intptr_t kNumTemps = 0; |
| 4497 LocationSummary* summary = new (zone) | 4327 LocationSummary* summary = new (zone) |
| 4498 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4328 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4499 summary->set_in(0, Location::RequiresFpuRegister()); | 4329 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4500 summary->set_in(1, Location::RequiresFpuRegister()); | 4330 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4501 summary->set_out(0, Location::SameAsFirstInput()); | 4331 summary->set_out(0, Location::SameAsFirstInput()); |
| 4502 return summary; | 4332 return summary; |
| 4503 } | 4333 } |
| 4504 | 4334 |
| 4505 | |
| 4506 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4335 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4507 XmmRegister v0 = locs()->in(0).fpu_reg(); | 4336 XmmRegister v0 = locs()->in(0).fpu_reg(); |
| 4508 XmmRegister v1 = locs()->in(1).fpu_reg(); | 4337 XmmRegister v1 = locs()->in(1).fpu_reg(); |
| 4509 ASSERT(v0 == locs()->out(0).fpu_reg()); | 4338 ASSERT(v0 == locs()->out(0).fpu_reg()); |
| 4510 // shufpd mask 0x0 results in: | 4339 // shufpd mask 0x0 results in: |
| 4511 // Lower 64-bits of v0 = Lower 64-bits of v0. | 4340 // Lower 64-bits of v0 = Lower 64-bits of v0. |
| 4512 // Upper 64-bits of v0 = Lower 64-bits of v1. | 4341 // Upper 64-bits of v0 = Lower 64-bits of v1. |
| 4513 __ shufpd(v0, v1, Immediate(0x0)); | 4342 __ shufpd(v0, v1, Immediate(0x0)); |
| 4514 } | 4343 } |
| 4515 | 4344 |
| 4516 | |
| 4517 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 4345 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
| 4518 Zone* zone, | 4346 Zone* zone, |
| 4519 bool opt) const { | 4347 bool opt) const { |
| 4520 const intptr_t kNumInputs = 1; | 4348 const intptr_t kNumInputs = 1; |
| 4521 const intptr_t kNumTemps = 0; | 4349 const intptr_t kNumTemps = 0; |
| 4522 LocationSummary* summary = new (zone) | 4350 LocationSummary* summary = new (zone) |
| 4523 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4351 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4524 summary->set_in(0, Location::RequiresFpuRegister()); | 4352 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4525 summary->set_out(0, Location::SameAsFirstInput()); | 4353 summary->set_out(0, Location::SameAsFirstInput()); |
| 4526 return summary; | 4354 return summary; |
| 4527 } | 4355 } |
| 4528 | 4356 |
| 4529 | |
| 4530 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4357 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4531 XmmRegister value = locs()->out(0).fpu_reg(); | 4358 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4532 __ cvtpd2ps(value, value); | 4359 __ cvtpd2ps(value, value); |
| 4533 } | 4360 } |
| 4534 | 4361 |
| 4535 | |
| 4536 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 4362 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
| 4537 Zone* zone, | 4363 Zone* zone, |
| 4538 bool opt) const { | 4364 bool opt) const { |
| 4539 const intptr_t kNumInputs = 1; | 4365 const intptr_t kNumInputs = 1; |
| 4540 const intptr_t kNumTemps = 0; | 4366 const intptr_t kNumTemps = 0; |
| 4541 LocationSummary* summary = new (zone) | 4367 LocationSummary* summary = new (zone) |
| 4542 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4368 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4543 summary->set_in(0, Location::RequiresFpuRegister()); | 4369 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4544 summary->set_out(0, Location::SameAsFirstInput()); | 4370 summary->set_out(0, Location::SameAsFirstInput()); |
| 4545 return summary; | 4371 return summary; |
| 4546 } | 4372 } |
| 4547 | 4373 |
| 4548 | |
| 4549 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4374 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4550 XmmRegister value = locs()->out(0).fpu_reg(); | 4375 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4551 __ cvtps2pd(value, value); | 4376 __ cvtps2pd(value, value); |
| 4552 } | 4377 } |
| 4553 | 4378 |
| 4554 | |
| 4555 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4379 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, |
| 4556 bool opt) const { | 4380 bool opt) const { |
| 4557 const intptr_t kNumInputs = 1; | 4381 const intptr_t kNumInputs = 1; |
| 4558 const intptr_t kNumTemps = 0; | 4382 const intptr_t kNumTemps = 0; |
| 4559 LocationSummary* summary = new (zone) | 4383 LocationSummary* summary = new (zone) |
| 4560 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4384 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4561 summary->set_in(0, Location::RequiresFpuRegister()); | 4385 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4562 if (representation() == kTagged) { | 4386 if (representation() == kTagged) { |
| 4563 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 4387 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |
| 4564 summary->set_out(0, Location::RequiresRegister()); | 4388 summary->set_out(0, Location::RequiresRegister()); |
| 4565 } else { | 4389 } else { |
| 4566 ASSERT(representation() == kUnboxedFloat64x2); | 4390 ASSERT(representation() == kUnboxedFloat64x2); |
| 4567 summary->set_out(0, Location::SameAsFirstInput()); | 4391 summary->set_out(0, Location::SameAsFirstInput()); |
| 4568 } | 4392 } |
| 4569 return summary; | 4393 return summary; |
| 4570 } | 4394 } |
| 4571 | 4395 |
| 4572 | |
| 4573 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4396 void Float64x2ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4574 XmmRegister left = locs()->in(0).fpu_reg(); | 4397 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4575 | 4398 |
| 4576 ASSERT((op_kind() == MethodRecognizer::kFloat64x2GetSignMask) || | 4399 ASSERT((op_kind() == MethodRecognizer::kFloat64x2GetSignMask) || |
| 4577 (locs()->out(0).fpu_reg() == left)); | 4400 (locs()->out(0).fpu_reg() == left)); |
| 4578 | 4401 |
| 4579 switch (op_kind()) { | 4402 switch (op_kind()) { |
| 4580 case MethodRecognizer::kFloat64x2Negate: | 4403 case MethodRecognizer::kFloat64x2Negate: |
| 4581 __ negatepd(left); | 4404 __ negatepd(left); |
| 4582 break; | 4405 break; |
| 4583 case MethodRecognizer::kFloat64x2Abs: | 4406 case MethodRecognizer::kFloat64x2Abs: |
| 4584 __ abspd(left); | 4407 __ abspd(left); |
| 4585 break; | 4408 break; |
| 4586 case MethodRecognizer::kFloat64x2Sqrt: | 4409 case MethodRecognizer::kFloat64x2Sqrt: |
| 4587 __ sqrtpd(left); | 4410 __ sqrtpd(left); |
| 4588 break; | 4411 break; |
| 4589 case MethodRecognizer::kFloat64x2GetSignMask: | 4412 case MethodRecognizer::kFloat64x2GetSignMask: |
| 4590 __ movmskpd(locs()->out(0).reg(), left); | 4413 __ movmskpd(locs()->out(0).reg(), left); |
| 4591 __ SmiTag(locs()->out(0).reg()); | 4414 __ SmiTag(locs()->out(0).reg()); |
| 4592 break; | 4415 break; |
| 4593 default: | 4416 default: |
| 4594 UNREACHABLE(); | 4417 UNREACHABLE(); |
| 4595 } | 4418 } |
| 4596 } | 4419 } |
| 4597 | 4420 |
| 4598 | |
| 4599 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, | 4421 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, |
| 4600 bool opt) const { | 4422 bool opt) const { |
| 4601 const intptr_t kNumInputs = 2; | 4423 const intptr_t kNumInputs = 2; |
| 4602 const intptr_t kNumTemps = 0; | 4424 const intptr_t kNumTemps = 0; |
| 4603 LocationSummary* summary = new (zone) | 4425 LocationSummary* summary = new (zone) |
| 4604 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4426 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4605 summary->set_in(0, Location::RequiresFpuRegister()); | 4427 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4606 summary->set_in(1, Location::RequiresFpuRegister()); | 4428 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4607 summary->set_out(0, Location::SameAsFirstInput()); | 4429 summary->set_out(0, Location::SameAsFirstInput()); |
| 4608 return summary; | 4430 return summary; |
| 4609 } | 4431 } |
| 4610 | 4432 |
| 4611 | |
| 4612 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4433 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4613 XmmRegister left = locs()->in(0).fpu_reg(); | 4434 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4614 XmmRegister right = locs()->in(1).fpu_reg(); | 4435 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4615 ASSERT((locs()->out(0).fpu_reg() == left)); | 4436 ASSERT((locs()->out(0).fpu_reg() == left)); |
| 4616 | 4437 |
| 4617 switch (op_kind()) { | 4438 switch (op_kind()) { |
| 4618 case MethodRecognizer::kFloat64x2Scale: | 4439 case MethodRecognizer::kFloat64x2Scale: |
| 4619 __ shufpd(right, right, Immediate(0x00)); | 4440 __ shufpd(right, right, Immediate(0x00)); |
| 4620 __ mulpd(left, right); | 4441 __ mulpd(left, right); |
| 4621 break; | 4442 break; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4643 __ minpd(left, right); | 4464 __ minpd(left, right); |
| 4644 break; | 4465 break; |
| 4645 case MethodRecognizer::kFloat64x2Max: | 4466 case MethodRecognizer::kFloat64x2Max: |
| 4646 __ maxpd(left, right); | 4467 __ maxpd(left, right); |
| 4647 break; | 4468 break; |
| 4648 default: | 4469 default: |
| 4649 UNREACHABLE(); | 4470 UNREACHABLE(); |
| 4650 } | 4471 } |
| 4651 } | 4472 } |
| 4652 | 4473 |
| 4653 | |
| 4654 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, | 4474 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, |
| 4655 bool opt) const { | 4475 bool opt) const { |
| 4656 const intptr_t kNumInputs = 4; | 4476 const intptr_t kNumInputs = 4; |
| 4657 const intptr_t kNumTemps = 0; | 4477 const intptr_t kNumTemps = 0; |
| 4658 LocationSummary* summary = new (zone) | 4478 LocationSummary* summary = new (zone) |
| 4659 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4479 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4660 summary->set_in(0, Location::RequiresRegister()); | 4480 summary->set_in(0, Location::RequiresRegister()); |
| 4661 summary->set_in(1, Location::RequiresRegister()); | 4481 summary->set_in(1, Location::RequiresRegister()); |
| 4662 summary->set_in(2, Location::RequiresRegister()); | 4482 summary->set_in(2, Location::RequiresRegister()); |
| 4663 summary->set_in(3, Location::RequiresRegister()); | 4483 summary->set_in(3, Location::RequiresRegister()); |
| 4664 summary->set_out(0, Location::RequiresFpuRegister()); | 4484 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4665 return summary; | 4485 return summary; |
| 4666 } | 4486 } |
| 4667 | 4487 |
| 4668 | |
| 4669 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4488 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4670 Register v0 = locs()->in(0).reg(); | 4489 Register v0 = locs()->in(0).reg(); |
| 4671 Register v1 = locs()->in(1).reg(); | 4490 Register v1 = locs()->in(1).reg(); |
| 4672 Register v2 = locs()->in(2).reg(); | 4491 Register v2 = locs()->in(2).reg(); |
| 4673 Register v3 = locs()->in(3).reg(); | 4492 Register v3 = locs()->in(3).reg(); |
| 4674 XmmRegister result = locs()->out(0).fpu_reg(); | 4493 XmmRegister result = locs()->out(0).fpu_reg(); |
| 4675 __ AddImmediate(RSP, Immediate(-4 * kInt32Size)); | 4494 __ AddImmediate(RSP, Immediate(-4 * kInt32Size)); |
| 4676 __ movl(Address(RSP, 0 * kInt32Size), v0); | 4495 __ movl(Address(RSP, 0 * kInt32Size), v0); |
| 4677 __ movl(Address(RSP, 1 * kInt32Size), v1); | 4496 __ movl(Address(RSP, 1 * kInt32Size), v1); |
| 4678 __ movl(Address(RSP, 2 * kInt32Size), v2); | 4497 __ movl(Address(RSP, 2 * kInt32Size), v2); |
| 4679 __ movl(Address(RSP, 3 * kInt32Size), v3); | 4498 __ movl(Address(RSP, 3 * kInt32Size), v3); |
| 4680 __ movups(result, Address(RSP, 0)); | 4499 __ movups(result, Address(RSP, 0)); |
| 4681 __ AddImmediate(RSP, Immediate(4 * kInt32Size)); | 4500 __ AddImmediate(RSP, Immediate(4 * kInt32Size)); |
| 4682 } | 4501 } |
| 4683 | 4502 |
| 4684 | |
| 4685 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 4503 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
| 4686 Zone* zone, | 4504 Zone* zone, |
| 4687 bool opt) const { | 4505 bool opt) const { |
| 4688 const intptr_t kNumInputs = 4; | 4506 const intptr_t kNumInputs = 4; |
| 4689 const intptr_t kNumTemps = 1; | 4507 const intptr_t kNumTemps = 1; |
| 4690 LocationSummary* summary = new (zone) | 4508 LocationSummary* summary = new (zone) |
| 4691 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4509 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4692 summary->set_in(0, Location::RequiresRegister()); | 4510 summary->set_in(0, Location::RequiresRegister()); |
| 4693 summary->set_in(1, Location::RequiresRegister()); | 4511 summary->set_in(1, Location::RequiresRegister()); |
| 4694 summary->set_in(2, Location::RequiresRegister()); | 4512 summary->set_in(2, Location::RequiresRegister()); |
| 4695 summary->set_in(3, Location::RequiresRegister()); | 4513 summary->set_in(3, Location::RequiresRegister()); |
| 4696 summary->set_temp(0, Location::RequiresRegister()); | 4514 summary->set_temp(0, Location::RequiresRegister()); |
| 4697 summary->set_out(0, Location::RequiresFpuRegister()); | 4515 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4698 return summary; | 4516 return summary; |
| 4699 } | 4517 } |
| 4700 | 4518 |
| 4701 | |
| 4702 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4519 void Int32x4BoolConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4703 Register v0 = locs()->in(0).reg(); | 4520 Register v0 = locs()->in(0).reg(); |
| 4704 Register v1 = locs()->in(1).reg(); | 4521 Register v1 = locs()->in(1).reg(); |
| 4705 Register v2 = locs()->in(2).reg(); | 4522 Register v2 = locs()->in(2).reg(); |
| 4706 Register v3 = locs()->in(3).reg(); | 4523 Register v3 = locs()->in(3).reg(); |
| 4707 Register temp = locs()->temp(0).reg(); | 4524 Register temp = locs()->temp(0).reg(); |
| 4708 XmmRegister result = locs()->out(0).fpu_reg(); | 4525 XmmRegister result = locs()->out(0).fpu_reg(); |
| 4709 Label x_false, x_done; | 4526 Label x_false, x_done; |
| 4710 Label y_false, y_done; | 4527 Label y_false, y_done; |
| 4711 Label z_false, z_done; | 4528 Label z_false, z_done; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4745 __ jmp(&w_done); | 4562 __ jmp(&w_done); |
| 4746 __ Bind(&w_false); | 4563 __ Bind(&w_false); |
| 4747 __ LoadImmediate(temp, Immediate(0x0)); | 4564 __ LoadImmediate(temp, Immediate(0x0)); |
| 4748 __ Bind(&w_done); | 4565 __ Bind(&w_done); |
| 4749 __ movl(Address(RSP, 12), temp); | 4566 __ movl(Address(RSP, 12), temp); |
| 4750 | 4567 |
| 4751 __ movups(result, Address(RSP, 0)); | 4568 __ movups(result, Address(RSP, 0)); |
| 4752 __ AddImmediate(RSP, Immediate(16)); | 4569 __ AddImmediate(RSP, Immediate(16)); |
| 4753 } | 4570 } |
| 4754 | 4571 |
| 4755 | |
| 4756 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, | 4572 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, |
| 4757 bool opt) const { | 4573 bool opt) const { |
| 4758 const intptr_t kNumInputs = 1; | 4574 const intptr_t kNumInputs = 1; |
| 4759 const intptr_t kNumTemps = 0; | 4575 const intptr_t kNumTemps = 0; |
| 4760 LocationSummary* summary = new (zone) | 4576 LocationSummary* summary = new (zone) |
| 4761 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4577 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4762 summary->set_in(0, Location::RequiresFpuRegister()); | 4578 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4763 summary->set_out(0, Location::RequiresRegister()); | 4579 summary->set_out(0, Location::RequiresRegister()); |
| 4764 return summary; | 4580 return summary; |
| 4765 } | 4581 } |
| 4766 | 4582 |
| 4767 | |
| 4768 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4583 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4769 XmmRegister value = locs()->in(0).fpu_reg(); | 4584 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4770 Register result = locs()->out(0).reg(); | 4585 Register result = locs()->out(0).reg(); |
| 4771 Label done; | 4586 Label done; |
| 4772 Label non_zero; | 4587 Label non_zero; |
| 4773 __ AddImmediate(RSP, Immediate(-16)); | 4588 __ AddImmediate(RSP, Immediate(-16)); |
| 4774 // Move value to stack. | 4589 // Move value to stack. |
| 4775 __ movups(Address(RSP, 0), value); | 4590 __ movups(Address(RSP, 0), value); |
| 4776 switch (op_kind()) { | 4591 switch (op_kind()) { |
| 4777 case MethodRecognizer::kInt32x4GetFlagX: | 4592 case MethodRecognizer::kInt32x4GetFlagX: |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4792 __ AddImmediate(RSP, Immediate(16)); | 4607 __ AddImmediate(RSP, Immediate(16)); |
| 4793 __ testl(result, result); | 4608 __ testl(result, result); |
| 4794 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); | 4609 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); |
| 4795 __ LoadObject(result, Bool::False()); | 4610 __ LoadObject(result, Bool::False()); |
| 4796 __ jmp(&done); | 4611 __ jmp(&done); |
| 4797 __ Bind(&non_zero); | 4612 __ Bind(&non_zero); |
| 4798 __ LoadObject(result, Bool::True()); | 4613 __ LoadObject(result, Bool::True()); |
| 4799 __ Bind(&done); | 4614 __ Bind(&done); |
| 4800 } | 4615 } |
| 4801 | 4616 |
| 4802 | |
| 4803 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, | 4617 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, |
| 4804 bool opt) const { | 4618 bool opt) const { |
| 4805 const intptr_t kNumInputs = 3; | 4619 const intptr_t kNumInputs = 3; |
| 4806 const intptr_t kNumTemps = 1; | 4620 const intptr_t kNumTemps = 1; |
| 4807 LocationSummary* summary = new (zone) | 4621 LocationSummary* summary = new (zone) |
| 4808 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4622 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4809 summary->set_in(0, Location::RequiresFpuRegister()); | 4623 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4810 summary->set_in(1, Location::RequiresFpuRegister()); | 4624 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4811 summary->set_in(2, Location::RequiresFpuRegister()); | 4625 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4812 summary->set_temp(0, Location::RequiresFpuRegister()); | 4626 summary->set_temp(0, Location::RequiresFpuRegister()); |
| 4813 summary->set_out(0, Location::SameAsFirstInput()); | 4627 summary->set_out(0, Location::SameAsFirstInput()); |
| 4814 return summary; | 4628 return summary; |
| 4815 } | 4629 } |
| 4816 | 4630 |
| 4817 | |
| 4818 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4631 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4819 XmmRegister mask = locs()->in(0).fpu_reg(); | 4632 XmmRegister mask = locs()->in(0).fpu_reg(); |
| 4820 XmmRegister trueValue = locs()->in(1).fpu_reg(); | 4633 XmmRegister trueValue = locs()->in(1).fpu_reg(); |
| 4821 XmmRegister falseValue = locs()->in(2).fpu_reg(); | 4634 XmmRegister falseValue = locs()->in(2).fpu_reg(); |
| 4822 XmmRegister out = locs()->out(0).fpu_reg(); | 4635 XmmRegister out = locs()->out(0).fpu_reg(); |
| 4823 XmmRegister temp = locs()->temp(0).fpu_reg(); | 4636 XmmRegister temp = locs()->temp(0).fpu_reg(); |
| 4824 ASSERT(out == mask); | 4637 ASSERT(out == mask); |
| 4825 // Copy mask. | 4638 // Copy mask. |
| 4826 __ movaps(temp, mask); | 4639 __ movaps(temp, mask); |
| 4827 // Invert it. | 4640 // Invert it. |
| 4828 __ notps(temp); | 4641 __ notps(temp); |
| 4829 // mask = mask & trueValue. | 4642 // mask = mask & trueValue. |
| 4830 __ andps(mask, trueValue); | 4643 __ andps(mask, trueValue); |
| 4831 // temp = temp & falseValue. | 4644 // temp = temp & falseValue. |
| 4832 __ andps(temp, falseValue); | 4645 __ andps(temp, falseValue); |
| 4833 // out = mask | temp. | 4646 // out = mask | temp. |
| 4834 __ orps(mask, temp); | 4647 __ orps(mask, temp); |
| 4835 } | 4648 } |
| 4836 | 4649 |
| 4837 | |
| 4838 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, | 4650 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, |
| 4839 bool opt) const { | 4651 bool opt) const { |
| 4840 const intptr_t kNumInputs = 2; | 4652 const intptr_t kNumInputs = 2; |
| 4841 const intptr_t kNumTemps = 1; | 4653 const intptr_t kNumTemps = 1; |
| 4842 LocationSummary* summary = new (zone) | 4654 LocationSummary* summary = new (zone) |
| 4843 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4655 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4844 summary->set_in(0, Location::RequiresFpuRegister()); | 4656 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4845 summary->set_in(1, Location::RequiresRegister()); | 4657 summary->set_in(1, Location::RequiresRegister()); |
| 4846 summary->set_temp(0, Location::RequiresRegister()); | 4658 summary->set_temp(0, Location::RequiresRegister()); |
| 4847 summary->set_out(0, Location::SameAsFirstInput()); | 4659 summary->set_out(0, Location::SameAsFirstInput()); |
| 4848 return summary; | 4660 return summary; |
| 4849 } | 4661 } |
| 4850 | 4662 |
| 4851 | |
| 4852 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4663 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4853 XmmRegister mask = locs()->in(0).fpu_reg(); | 4664 XmmRegister mask = locs()->in(0).fpu_reg(); |
| 4854 Register flag = locs()->in(1).reg(); | 4665 Register flag = locs()->in(1).reg(); |
| 4855 Register temp = locs()->temp(0).reg(); | 4666 Register temp = locs()->temp(0).reg(); |
| 4856 ASSERT(mask == locs()->out(0).fpu_reg()); | 4667 ASSERT(mask == locs()->out(0).fpu_reg()); |
| 4857 __ AddImmediate(RSP, Immediate(-16)); | 4668 __ AddImmediate(RSP, Immediate(-16)); |
| 4858 // Copy mask to stack. | 4669 // Copy mask to stack. |
| 4859 __ movups(Address(RSP, 0), mask); | 4670 __ movups(Address(RSP, 0), mask); |
| 4860 Label falsePath, exitPath; | 4671 Label falsePath, exitPath; |
| 4861 __ CompareObject(flag, Bool::True()); | 4672 __ CompareObject(flag, Bool::True()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4895 break; | 4706 break; |
| 4896 default: | 4707 default: |
| 4897 UNREACHABLE(); | 4708 UNREACHABLE(); |
| 4898 } | 4709 } |
| 4899 __ Bind(&exitPath); | 4710 __ Bind(&exitPath); |
| 4900 // Copy mask back to register. | 4711 // Copy mask back to register. |
| 4901 __ movups(mask, Address(RSP, 0)); | 4712 __ movups(mask, Address(RSP, 0)); |
| 4902 __ AddImmediate(RSP, Immediate(16)); | 4713 __ AddImmediate(RSP, Immediate(16)); |
| 4903 } | 4714 } |
| 4904 | 4715 |
| 4905 | |
| 4906 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, | 4716 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, |
| 4907 bool opt) const { | 4717 bool opt) const { |
| 4908 const intptr_t kNumInputs = 1; | 4718 const intptr_t kNumInputs = 1; |
| 4909 const intptr_t kNumTemps = 0; | 4719 const intptr_t kNumTemps = 0; |
| 4910 LocationSummary* summary = new (zone) | 4720 LocationSummary* summary = new (zone) |
| 4911 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4721 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4912 summary->set_in(0, Location::RequiresFpuRegister()); | 4722 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4913 summary->set_out(0, Location::SameAsFirstInput()); | 4723 summary->set_out(0, Location::SameAsFirstInput()); |
| 4914 return summary; | 4724 return summary; |
| 4915 } | 4725 } |
| 4916 | 4726 |
| 4917 | |
| 4918 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4727 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4919 // NOP. | 4728 // NOP. |
| 4920 } | 4729 } |
| 4921 | 4730 |
| 4922 | |
| 4923 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, | 4731 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 4924 bool opt) const { | 4732 bool opt) const { |
| 4925 const intptr_t kNumInputs = 2; | 4733 const intptr_t kNumInputs = 2; |
| 4926 const intptr_t kNumTemps = 0; | 4734 const intptr_t kNumTemps = 0; |
| 4927 LocationSummary* summary = new (zone) | 4735 LocationSummary* summary = new (zone) |
| 4928 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4736 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4929 summary->set_in(0, Location::RequiresFpuRegister()); | 4737 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4930 summary->set_in(1, Location::RequiresFpuRegister()); | 4738 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4931 summary->set_out(0, Location::SameAsFirstInput()); | 4739 summary->set_out(0, Location::SameAsFirstInput()); |
| 4932 return summary; | 4740 return summary; |
| 4933 } | 4741 } |
| 4934 | 4742 |
| 4935 | |
| 4936 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4743 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4937 XmmRegister left = locs()->in(0).fpu_reg(); | 4744 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4938 XmmRegister right = locs()->in(1).fpu_reg(); | 4745 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4939 ASSERT(left == locs()->out(0).fpu_reg()); | 4746 ASSERT(left == locs()->out(0).fpu_reg()); |
| 4940 switch (op_kind()) { | 4747 switch (op_kind()) { |
| 4941 case Token::kBIT_AND: { | 4748 case Token::kBIT_AND: { |
| 4942 __ andps(left, right); | 4749 __ andps(left, right); |
| 4943 break; | 4750 break; |
| 4944 } | 4751 } |
| 4945 case Token::kBIT_OR: { | 4752 case Token::kBIT_OR: { |
| 4946 __ orps(left, right); | 4753 __ orps(left, right); |
| 4947 break; | 4754 break; |
| 4948 } | 4755 } |
| 4949 case Token::kBIT_XOR: { | 4756 case Token::kBIT_XOR: { |
| 4950 __ xorps(left, right); | 4757 __ xorps(left, right); |
| 4951 break; | 4758 break; |
| 4952 } | 4759 } |
| 4953 case Token::kADD: | 4760 case Token::kADD: |
| 4954 __ addpl(left, right); | 4761 __ addpl(left, right); |
| 4955 break; | 4762 break; |
| 4956 case Token::kSUB: | 4763 case Token::kSUB: |
| 4957 __ subpl(left, right); | 4764 __ subpl(left, right); |
| 4958 break; | 4765 break; |
| 4959 default: | 4766 default: |
| 4960 UNREACHABLE(); | 4767 UNREACHABLE(); |
| 4961 } | 4768 } |
| 4962 } | 4769 } |
| 4963 | 4770 |
| 4964 | |
| 4965 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 4771 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |
| 4966 bool opt) const { | 4772 bool opt) const { |
| 4967 ASSERT((kind() == MathUnaryInstr::kSqrt) || | 4773 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
| 4968 (kind() == MathUnaryInstr::kDoubleSquare)); | 4774 (kind() == MathUnaryInstr::kDoubleSquare)); |
| 4969 const intptr_t kNumInputs = 1; | 4775 const intptr_t kNumInputs = 1; |
| 4970 const intptr_t kNumTemps = 0; | 4776 const intptr_t kNumTemps = 0; |
| 4971 LocationSummary* summary = new (zone) | 4777 LocationSummary* summary = new (zone) |
| 4972 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4778 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4973 summary->set_in(0, Location::RequiresFpuRegister()); | 4779 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4974 if (kind() == MathUnaryInstr::kDoubleSquare) { | 4780 if (kind() == MathUnaryInstr::kDoubleSquare) { |
| 4975 summary->set_out(0, Location::SameAsFirstInput()); | 4781 summary->set_out(0, Location::SameAsFirstInput()); |
| 4976 } else { | 4782 } else { |
| 4977 summary->set_out(0, Location::RequiresFpuRegister()); | 4783 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4978 } | 4784 } |
| 4979 return summary; | 4785 return summary; |
| 4980 } | 4786 } |
| 4981 | 4787 |
| 4982 | |
| 4983 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4788 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4984 if (kind() == MathUnaryInstr::kSqrt) { | 4789 if (kind() == MathUnaryInstr::kSqrt) { |
| 4985 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 4790 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 4986 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 4791 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
| 4987 XmmRegister value_reg = locs()->in(0).fpu_reg(); | 4792 XmmRegister value_reg = locs()->in(0).fpu_reg(); |
| 4988 __ mulsd(value_reg, value_reg); | 4793 __ mulsd(value_reg, value_reg); |
| 4989 ASSERT(value_reg == locs()->out(0).fpu_reg()); | 4794 ASSERT(value_reg == locs()->out(0).fpu_reg()); |
| 4990 } else { | 4795 } else { |
| 4991 UNREACHABLE(); | 4796 UNREACHABLE(); |
| 4992 } | 4797 } |
| 4993 } | 4798 } |
| 4994 | 4799 |
| 4995 | |
| 4996 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 4800 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |
| 4997 Zone* zone, | 4801 Zone* zone, |
| 4998 bool opt) const { | 4802 bool opt) const { |
| 4999 const intptr_t kNumTemps = 0; | 4803 const intptr_t kNumTemps = 0; |
| 5000 LocationSummary* summary = new (zone) | 4804 LocationSummary* summary = new (zone) |
| 5001 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); | 4805 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 5002 summary->set_in(0, Location::RegisterLocation(CallingConventions::kArg1Reg)); | 4806 summary->set_in(0, Location::RegisterLocation(CallingConventions::kArg1Reg)); |
| 5003 summary->set_in(1, Location::RegisterLocation(CallingConventions::kArg2Reg)); | 4807 summary->set_in(1, Location::RegisterLocation(CallingConventions::kArg2Reg)); |
| 5004 summary->set_in(2, Location::RegisterLocation(CallingConventions::kArg3Reg)); | 4808 summary->set_in(2, Location::RegisterLocation(CallingConventions::kArg3Reg)); |
| 5005 summary->set_in(3, Location::RegisterLocation(CallingConventions::kArg4Reg)); | 4809 summary->set_in(3, Location::RegisterLocation(CallingConventions::kArg4Reg)); |
| 5006 summary->set_out(0, Location::RegisterLocation(RAX)); | 4810 summary->set_out(0, Location::RegisterLocation(RAX)); |
| 5007 return summary; | 4811 return summary; |
| 5008 } | 4812 } |
| 5009 | 4813 |
| 5010 | |
| 5011 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 4814 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |
| 5012 FlowGraphCompiler* compiler) { | 4815 FlowGraphCompiler* compiler) { |
| 5013 // Save RSP. R13 is chosen because it is callee saved so we do not need to | 4816 // Save RSP. R13 is chosen because it is callee saved so we do not need to |
| 5014 // back it up before calling into the runtime. | 4817 // back it up before calling into the runtime. |
| 5015 static const Register kSavedSPReg = R13; | 4818 static const Register kSavedSPReg = R13; |
| 5016 __ movq(kSavedSPReg, RSP); | 4819 __ movq(kSavedSPReg, RSP); |
| 5017 __ ReserveAlignedFrameSpace(0); | 4820 __ ReserveAlignedFrameSpace(0); |
| 5018 | 4821 |
| 5019 // Call the function. Parameters are already in their correct spots. | 4822 // Call the function. Parameters are already in their correct spots. |
| 5020 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 4823 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |
| 5021 | 4824 |
| 5022 // Restore RSP. | 4825 // Restore RSP. |
| 5023 __ movq(RSP, kSavedSPReg); | 4826 __ movq(RSP, kSavedSPReg); |
| 5024 } | 4827 } |
| 5025 | 4828 |
| 5026 | |
| 5027 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 4829 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 5028 bool opt) const { | 4830 bool opt) const { |
| 5029 const intptr_t kNumInputs = 1; | 4831 const intptr_t kNumInputs = 1; |
| 5030 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), | 4832 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
| 5031 LocationSummary::kNoCall); | 4833 LocationSummary::kNoCall); |
| 5032 } | 4834 } |
| 5033 | 4835 |
| 5034 | |
| 5035 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4836 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5036 Register value = locs()->in(0).reg(); | 4837 Register value = locs()->in(0).reg(); |
| 5037 ASSERT(value == locs()->out(0).reg()); | 4838 ASSERT(value == locs()->out(0).reg()); |
| 5038 switch (op_kind()) { | 4839 switch (op_kind()) { |
| 5039 case Token::kNEGATE: { | 4840 case Token::kNEGATE: { |
| 5040 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); | 4841 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); |
| 5041 __ negq(value); | 4842 __ negq(value); |
| 5042 __ j(OVERFLOW, deopt); | 4843 __ j(OVERFLOW, deopt); |
| 5043 break; | 4844 break; |
| 5044 } | 4845 } |
| 5045 case Token::kBIT_NOT: | 4846 case Token::kBIT_NOT: |
| 5046 __ notq(value); | 4847 __ notq(value); |
| 5047 // Remove inverted smi-tag. | 4848 // Remove inverted smi-tag. |
| 5048 __ AndImmediate(value, Immediate(~kSmiTagMask)); | 4849 __ AndImmediate(value, Immediate(~kSmiTagMask)); |
| 5049 break; | 4850 break; |
| 5050 default: | 4851 default: |
| 5051 UNREACHABLE(); | 4852 UNREACHABLE(); |
| 5052 } | 4853 } |
| 5053 } | 4854 } |
| 5054 | 4855 |
| 5055 | |
| 5056 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 4856 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 5057 bool opt) const { | 4857 bool opt) const { |
| 5058 const intptr_t kNumInputs = 1; | 4858 const intptr_t kNumInputs = 1; |
| 5059 const intptr_t kNumTemps = 0; | 4859 const intptr_t kNumTemps = 0; |
| 5060 LocationSummary* summary = new (zone) | 4860 LocationSummary* summary = new (zone) |
| 5061 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4861 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5062 summary->set_in(0, Location::RequiresFpuRegister()); | 4862 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5063 summary->set_out(0, Location::SameAsFirstInput()); | 4863 summary->set_out(0, Location::SameAsFirstInput()); |
| 5064 return summary; | 4864 return summary; |
| 5065 } | 4865 } |
| 5066 | 4866 |
| 5067 | |
| 5068 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4867 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5069 XmmRegister value = locs()->in(0).fpu_reg(); | 4868 XmmRegister value = locs()->in(0).fpu_reg(); |
| 5070 ASSERT(locs()->out(0).fpu_reg() == value); | 4869 ASSERT(locs()->out(0).fpu_reg() == value); |
| 5071 __ DoubleNegate(value); | 4870 __ DoubleNegate(value); |
| 5072 } | 4871 } |
| 5073 | 4872 |
| 5074 | |
| 5075 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 4873 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |
| 5076 bool opt) const { | 4874 bool opt) const { |
| 5077 if (result_cid() == kDoubleCid) { | 4875 if (result_cid() == kDoubleCid) { |
| 5078 const intptr_t kNumInputs = 2; | 4876 const intptr_t kNumInputs = 2; |
| 5079 const intptr_t kNumTemps = 1; | 4877 const intptr_t kNumTemps = 1; |
| 5080 LocationSummary* summary = new (zone) | 4878 LocationSummary* summary = new (zone) |
| 5081 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4879 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5082 summary->set_in(0, Location::RequiresFpuRegister()); | 4880 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5083 summary->set_in(1, Location::RequiresFpuRegister()); | 4881 summary->set_in(1, Location::RequiresFpuRegister()); |
| 5084 // Reuse the left register so that code can be made shorter. | 4882 // Reuse the left register so that code can be made shorter. |
| 5085 summary->set_out(0, Location::SameAsFirstInput()); | 4883 summary->set_out(0, Location::SameAsFirstInput()); |
| 5086 summary->set_temp(0, Location::RequiresRegister()); | 4884 summary->set_temp(0, Location::RequiresRegister()); |
| 5087 return summary; | 4885 return summary; |
| 5088 } | 4886 } |
| 5089 ASSERT(result_cid() == kSmiCid); | 4887 ASSERT(result_cid() == kSmiCid); |
| 5090 const intptr_t kNumInputs = 2; | 4888 const intptr_t kNumInputs = 2; |
| 5091 const intptr_t kNumTemps = 0; | 4889 const intptr_t kNumTemps = 0; |
| 5092 LocationSummary* summary = new (zone) | 4890 LocationSummary* summary = new (zone) |
| 5093 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4891 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5094 summary->set_in(0, Location::RequiresRegister()); | 4892 summary->set_in(0, Location::RequiresRegister()); |
| 5095 summary->set_in(1, Location::RequiresRegister()); | 4893 summary->set_in(1, Location::RequiresRegister()); |
| 5096 // Reuse the left register so that code can be made shorter. | 4894 // Reuse the left register so that code can be made shorter. |
| 5097 summary->set_out(0, Location::SameAsFirstInput()); | 4895 summary->set_out(0, Location::SameAsFirstInput()); |
| 5098 return summary; | 4896 return summary; |
| 5099 } | 4897 } |
| 5100 | 4898 |
| 5101 | |
| 5102 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4899 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5103 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 4900 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
| 5104 (op_kind() == MethodRecognizer::kMathMax)); | 4901 (op_kind() == MethodRecognizer::kMathMax)); |
| 5105 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); | 4902 const intptr_t is_min = (op_kind() == MethodRecognizer::kMathMin); |
| 5106 if (result_cid() == kDoubleCid) { | 4903 if (result_cid() == kDoubleCid) { |
| 5107 Label done, returns_nan, are_equal; | 4904 Label done, returns_nan, are_equal; |
| 5108 XmmRegister left = locs()->in(0).fpu_reg(); | 4905 XmmRegister left = locs()->in(0).fpu_reg(); |
| 5109 XmmRegister right = locs()->in(1).fpu_reg(); | 4906 XmmRegister right = locs()->in(1).fpu_reg(); |
| 5110 XmmRegister result = locs()->out(0).fpu_reg(); | 4907 XmmRegister result = locs()->out(0).fpu_reg(); |
| 5111 Register temp = locs()->temp(0).reg(); | 4908 Register temp = locs()->temp(0).reg(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5154 Register result = locs()->out(0).reg(); | 4951 Register result = locs()->out(0).reg(); |
| 5155 __ cmpq(left, right); | 4952 __ cmpq(left, right); |
| 5156 ASSERT(result == left); | 4953 ASSERT(result == left); |
| 5157 if (is_min) { | 4954 if (is_min) { |
| 5158 __ cmovgeq(result, right); | 4955 __ cmovgeq(result, right); |
| 5159 } else { | 4956 } else { |
| 5160 __ cmovlessq(result, right); | 4957 __ cmovlessq(result, right); |
| 5161 } | 4958 } |
| 5162 } | 4959 } |
| 5163 | 4960 |
| 5164 | |
| 5165 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 4961 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5166 bool opt) const { | 4962 bool opt) const { |
| 5167 const intptr_t kNumInputs = 1; | 4963 const intptr_t kNumInputs = 1; |
| 5168 const intptr_t kNumTemps = 0; | 4964 const intptr_t kNumTemps = 0; |
| 5169 LocationSummary* result = new (zone) | 4965 LocationSummary* result = new (zone) |
| 5170 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4966 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5171 result->set_in(0, Location::RequiresRegister()); | 4967 result->set_in(0, Location::RequiresRegister()); |
| 5172 result->set_out(0, Location::RequiresFpuRegister()); | 4968 result->set_out(0, Location::RequiresFpuRegister()); |
| 5173 return result; | 4969 return result; |
| 5174 } | 4970 } |
| 5175 | 4971 |
| 5176 | |
| 5177 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4972 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5178 Register value = locs()->in(0).reg(); | 4973 Register value = locs()->in(0).reg(); |
| 5179 FpuRegister result = locs()->out(0).fpu_reg(); | 4974 FpuRegister result = locs()->out(0).fpu_reg(); |
| 5180 __ cvtsi2sdl(result, value); | 4975 __ cvtsi2sdl(result, value); |
| 5181 } | 4976 } |
| 5182 | 4977 |
| 5183 | |
| 5184 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 4978 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5185 bool opt) const { | 4979 bool opt) const { |
| 5186 const intptr_t kNumInputs = 1; | 4980 const intptr_t kNumInputs = 1; |
| 5187 const intptr_t kNumTemps = 0; | 4981 const intptr_t kNumTemps = 0; |
| 5188 LocationSummary* result = new (zone) | 4982 LocationSummary* result = new (zone) |
| 5189 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4983 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5190 result->set_in(0, Location::WritableRegister()); | 4984 result->set_in(0, Location::WritableRegister()); |
| 5191 result->set_out(0, Location::RequiresFpuRegister()); | 4985 result->set_out(0, Location::RequiresFpuRegister()); |
| 5192 return result; | 4986 return result; |
| 5193 } | 4987 } |
| 5194 | 4988 |
| 5195 | |
| 5196 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4989 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5197 Register value = locs()->in(0).reg(); | 4990 Register value = locs()->in(0).reg(); |
| 5198 FpuRegister result = locs()->out(0).fpu_reg(); | 4991 FpuRegister result = locs()->out(0).fpu_reg(); |
| 5199 __ SmiUntag(value); | 4992 __ SmiUntag(value); |
| 5200 __ cvtsi2sdq(result, value); | 4993 __ cvtsi2sdq(result, value); |
| 5201 } | 4994 } |
| 5202 | 4995 |
| 5203 | |
| 5204 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone, | 4996 LocationSummary* MintToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5205 bool opt) const { | 4997 bool opt) const { |
| 5206 UNIMPLEMENTED(); | 4998 UNIMPLEMENTED(); |
| 5207 return NULL; | 4999 return NULL; |
| 5208 } | 5000 } |
| 5209 | 5001 |
| 5210 | |
| 5211 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5002 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5212 UNIMPLEMENTED(); | 5003 UNIMPLEMENTED(); |
| 5213 } | 5004 } |
| 5214 | 5005 |
| 5215 | |
| 5216 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 5006 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |
| 5217 bool opt) const { | 5007 bool opt) const { |
| 5218 const intptr_t kNumInputs = 1; | 5008 const intptr_t kNumInputs = 1; |
| 5219 const intptr_t kNumTemps = 1; | 5009 const intptr_t kNumTemps = 1; |
| 5220 LocationSummary* result = new (zone) | 5010 LocationSummary* result = new (zone) |
| 5221 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5011 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 5222 result->set_in(0, Location::RegisterLocation(RCX)); | 5012 result->set_in(0, Location::RegisterLocation(RCX)); |
| 5223 result->set_out(0, Location::RegisterLocation(RAX)); | 5013 result->set_out(0, Location::RegisterLocation(RAX)); |
| 5224 result->set_temp(0, Location::RegisterLocation(RBX)); | 5014 result->set_temp(0, Location::RegisterLocation(RBX)); |
| 5225 return result; | 5015 return result; |
| 5226 } | 5016 } |
| 5227 | 5017 |
| 5228 | |
| 5229 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5018 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5230 Register result = locs()->out(0).reg(); | 5019 Register result = locs()->out(0).reg(); |
| 5231 Register value_obj = locs()->in(0).reg(); | 5020 Register value_obj = locs()->in(0).reg(); |
| 5232 Register temp = locs()->temp(0).reg(); | 5021 Register temp = locs()->temp(0).reg(); |
| 5233 XmmRegister value_double = XMM0; | 5022 XmmRegister value_double = XMM0; |
| 5234 ASSERT(result == RAX); | 5023 ASSERT(result == RAX); |
| 5235 ASSERT(result != value_obj); | 5024 ASSERT(result != value_obj); |
| 5236 ASSERT(result != temp); | 5025 ASSERT(result != temp); |
| 5237 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); | 5026 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); |
| 5238 __ cvttsd2siq(result, value_double); | 5027 __ cvttsd2siq(result, value_double); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5252 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 5041 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
| 5253 const int kTypeArgsLen = 0; | 5042 const int kTypeArgsLen = 0; |
| 5254 const int kNumberOfArguments = 1; | 5043 const int kNumberOfArguments = 1; |
| 5255 const Array& kNoArgumentNames = Object::null_array(); | 5044 const Array& kNoArgumentNames = Object::null_array(); |
| 5256 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); | 5045 ArgumentsInfo args_info(kTypeArgsLen, kNumberOfArguments, kNoArgumentNames); |
| 5257 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, | 5046 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, |
| 5258 args_info, locs(), ICData::Handle()); | 5047 args_info, locs(), ICData::Handle()); |
| 5259 __ Bind(&done); | 5048 __ Bind(&done); |
| 5260 } | 5049 } |
| 5261 | 5050 |
| 5262 | |
| 5263 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 5051 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |
| 5264 bool opt) const { | 5052 bool opt) const { |
| 5265 const intptr_t kNumInputs = 1; | 5053 const intptr_t kNumInputs = 1; |
| 5266 const intptr_t kNumTemps = 1; | 5054 const intptr_t kNumTemps = 1; |
| 5267 LocationSummary* result = new (zone) | 5055 LocationSummary* result = new (zone) |
| 5268 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5056 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5269 result->set_in(0, Location::RequiresFpuRegister()); | 5057 result->set_in(0, Location::RequiresFpuRegister()); |
| 5270 result->set_out(0, Location::RequiresRegister()); | 5058 result->set_out(0, Location::RequiresRegister()); |
| 5271 result->set_temp(0, Location::RequiresRegister()); | 5059 result->set_temp(0, Location::RequiresRegister()); |
| 5272 return result; | 5060 return result; |
| 5273 } | 5061 } |
| 5274 | 5062 |
| 5275 | |
| 5276 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5063 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5277 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 5064 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
| 5278 Register result = locs()->out(0).reg(); | 5065 Register result = locs()->out(0).reg(); |
| 5279 XmmRegister value = locs()->in(0).fpu_reg(); | 5066 XmmRegister value = locs()->in(0).fpu_reg(); |
| 5280 Register temp = locs()->temp(0).reg(); | 5067 Register temp = locs()->temp(0).reg(); |
| 5281 | 5068 |
| 5282 __ cvttsd2siq(result, value); | 5069 __ cvttsd2siq(result, value); |
| 5283 // Overflow is signalled with minint. | 5070 // Overflow is signalled with minint. |
| 5284 Label do_call, done; | 5071 Label do_call, done; |
| 5285 // Check for overflow and that it fits into Smi. | 5072 // Check for overflow and that it fits into Smi. |
| 5286 __ movq(temp, result); | 5073 __ movq(temp, result); |
| 5287 __ shlq(temp, Immediate(1)); | 5074 __ shlq(temp, Immediate(1)); |
| 5288 __ j(OVERFLOW, deopt); | 5075 __ j(OVERFLOW, deopt); |
| 5289 __ SmiTag(result); | 5076 __ SmiTag(result); |
| 5290 } | 5077 } |
| 5291 | 5078 |
| 5292 | |
| 5293 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, | 5079 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5294 bool opt) const { | 5080 bool opt) const { |
| 5295 const intptr_t kNumInputs = 1; | 5081 const intptr_t kNumInputs = 1; |
| 5296 const intptr_t kNumTemps = 0; | 5082 const intptr_t kNumTemps = 0; |
| 5297 LocationSummary* result = new (zone) | 5083 LocationSummary* result = new (zone) |
| 5298 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5084 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5299 result->set_in(0, Location::RequiresFpuRegister()); | 5085 result->set_in(0, Location::RequiresFpuRegister()); |
| 5300 result->set_out(0, Location::RequiresFpuRegister()); | 5086 result->set_out(0, Location::RequiresFpuRegister()); |
| 5301 return result; | 5087 return result; |
| 5302 } | 5088 } |
| 5303 | 5089 |
| 5304 | |
| 5305 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5090 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5306 XmmRegister value = locs()->in(0).fpu_reg(); | 5091 XmmRegister value = locs()->in(0).fpu_reg(); |
| 5307 XmmRegister result = locs()->out(0).fpu_reg(); | 5092 XmmRegister result = locs()->out(0).fpu_reg(); |
| 5308 switch (recognized_kind()) { | 5093 switch (recognized_kind()) { |
| 5309 case MethodRecognizer::kDoubleTruncate: | 5094 case MethodRecognizer::kDoubleTruncate: |
| 5310 __ roundsd(result, value, Assembler::kRoundToZero); | 5095 __ roundsd(result, value, Assembler::kRoundToZero); |
| 5311 break; | 5096 break; |
| 5312 case MethodRecognizer::kDoubleFloor: | 5097 case MethodRecognizer::kDoubleFloor: |
| 5313 __ roundsd(result, value, Assembler::kRoundDown); | 5098 __ roundsd(result, value, Assembler::kRoundDown); |
| 5314 break; | 5099 break; |
| 5315 case MethodRecognizer::kDoubleCeil: | 5100 case MethodRecognizer::kDoubleCeil: |
| 5316 __ roundsd(result, value, Assembler::kRoundUp); | 5101 __ roundsd(result, value, Assembler::kRoundUp); |
| 5317 break; | 5102 break; |
| 5318 default: | 5103 default: |
| 5319 UNREACHABLE(); | 5104 UNREACHABLE(); |
| 5320 } | 5105 } |
| 5321 } | 5106 } |
| 5322 | 5107 |
| 5323 | |
| 5324 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 5108 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |
| 5325 bool opt) const { | 5109 bool opt) const { |
| 5326 const intptr_t kNumInputs = 1; | 5110 const intptr_t kNumInputs = 1; |
| 5327 const intptr_t kNumTemps = 0; | 5111 const intptr_t kNumTemps = 0; |
| 5328 LocationSummary* result = new (zone) | 5112 LocationSummary* result = new (zone) |
| 5329 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5113 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5330 result->set_in(0, Location::RequiresFpuRegister()); | 5114 result->set_in(0, Location::RequiresFpuRegister()); |
| 5331 result->set_out(0, Location::SameAsFirstInput()); | 5115 result->set_out(0, Location::SameAsFirstInput()); |
| 5332 return result; | 5116 return result; |
| 5333 } | 5117 } |
| 5334 | 5118 |
| 5335 | |
| 5336 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5119 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5337 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5120 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 5338 } | 5121 } |
| 5339 | 5122 |
| 5340 | |
| 5341 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 5123 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5342 bool opt) const { | 5124 bool opt) const { |
| 5343 const intptr_t kNumInputs = 1; | 5125 const intptr_t kNumInputs = 1; |
| 5344 const intptr_t kNumTemps = 0; | 5126 const intptr_t kNumTemps = 0; |
| 5345 LocationSummary* result = new (zone) | 5127 LocationSummary* result = new (zone) |
| 5346 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5128 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5347 result->set_in(0, Location::RequiresFpuRegister()); | 5129 result->set_in(0, Location::RequiresFpuRegister()); |
| 5348 result->set_out(0, Location::SameAsFirstInput()); | 5130 result->set_out(0, Location::SameAsFirstInput()); |
| 5349 return result; | 5131 return result; |
| 5350 } | 5132 } |
| 5351 | 5133 |
| 5352 | |
| 5353 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5134 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5354 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5135 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 5355 } | 5136 } |
| 5356 | 5137 |
| 5357 | |
| 5358 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 5138 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |
| 5359 bool opt) const { | 5139 bool opt) const { |
| 5360 // Calling convention on x64 uses XMM0 and XMM1 to pass the first two | 5140 // Calling convention on x64 uses XMM0 and XMM1 to pass the first two |
| 5361 // double arguments and XMM0 to return the result. Unfortunately | 5141 // double arguments and XMM0 to return the result. Unfortunately |
| 5362 // currently we can't specify these registers because ParallelMoveResolver | 5142 // currently we can't specify these registers because ParallelMoveResolver |
| 5363 // assumes that XMM0 is free at all times. | 5143 // assumes that XMM0 is free at all times. |
| 5364 // TODO(vegorov): allow XMM0 to be used. | 5144 // TODO(vegorov): allow XMM0 to be used. |
| 5365 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 5145 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
| 5366 const intptr_t kNumTemps = | 5146 const intptr_t kNumTemps = |
| 5367 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; | 5147 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; |
| 5368 LocationSummary* result = new (zone) | 5148 LocationSummary* result = new (zone) |
| 5369 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5149 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 5370 ASSERT(R13 != CALLEE_SAVED_TEMP); | 5150 ASSERT(R13 != CALLEE_SAVED_TEMP); |
| 5371 ASSERT(((1 << R13) & CallingConventions::kCalleeSaveCpuRegisters) != 0); | 5151 ASSERT(((1 << R13) & CallingConventions::kCalleeSaveCpuRegisters) != 0); |
| 5372 result->set_temp(0, Location::RegisterLocation(R13)); | 5152 result->set_temp(0, Location::RegisterLocation(R13)); |
| 5373 result->set_in(0, Location::FpuRegisterLocation(XMM2)); | 5153 result->set_in(0, Location::FpuRegisterLocation(XMM2)); |
| 5374 if (InputCount() == 2) { | 5154 if (InputCount() == 2) { |
| 5375 result->set_in(1, Location::FpuRegisterLocation(XMM1)); | 5155 result->set_in(1, Location::FpuRegisterLocation(XMM1)); |
| 5376 } | 5156 } |
| 5377 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5157 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 5378 // Temp index 1. | 5158 // Temp index 1. |
| 5379 result->set_temp(1, Location::RegisterLocation(RAX)); | 5159 result->set_temp(1, Location::RegisterLocation(RAX)); |
| 5380 // Temp index 2. | 5160 // Temp index 2. |
| 5381 result->set_temp(2, Location::FpuRegisterLocation(XMM4)); | 5161 result->set_temp(2, Location::FpuRegisterLocation(XMM4)); |
| 5382 } | 5162 } |
| 5383 result->set_out(0, Location::FpuRegisterLocation(XMM3)); | 5163 result->set_out(0, Location::FpuRegisterLocation(XMM3)); |
| 5384 return result; | 5164 return result; |
| 5385 } | 5165 } |
| 5386 | 5166 |
| 5387 | |
| 5388 // Pseudo code: | 5167 // Pseudo code: |
| 5389 // if (exponent == 0.0) return 1.0; | 5168 // if (exponent == 0.0) return 1.0; |
| 5390 // // Speed up simple cases. | 5169 // // Speed up simple cases. |
| 5391 // if (exponent == 1.0) return base; | 5170 // if (exponent == 1.0) return base; |
| 5392 // if (exponent == 2.0) return base * base; | 5171 // if (exponent == 2.0) return base * base; |
| 5393 // if (exponent == 3.0) return base * base * base; | 5172 // if (exponent == 3.0) return base * base * base; |
| 5394 // if (base == 1.0) return 1.0; | 5173 // if (base == 1.0) return 1.0; |
| 5395 // if (base.isNaN || exponent.isNaN) { | 5174 // if (base.isNaN || exponent.isNaN) { |
| 5396 // return double.NAN; | 5175 // return double.NAN; |
| 5397 // } | 5176 // } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5510 __ movaps(XMM0, locs->in(0).fpu_reg()); | 5289 __ movaps(XMM0, locs->in(0).fpu_reg()); |
| 5511 ASSERT(locs->in(1).fpu_reg() == XMM1); | 5290 ASSERT(locs->in(1).fpu_reg() == XMM1); |
| 5512 | 5291 |
| 5513 __ CallRuntime(instr->TargetFunction(), kInputCount); | 5292 __ CallRuntime(instr->TargetFunction(), kInputCount); |
| 5514 __ movaps(locs->out(0).fpu_reg(), XMM0); | 5293 __ movaps(locs->out(0).fpu_reg(), XMM0); |
| 5515 // Restore RSP. | 5294 // Restore RSP. |
| 5516 __ movq(RSP, locs->temp(InvokeMathCFunctionInstr::kSavedSpTempIndex).reg()); | 5295 __ movq(RSP, locs->temp(InvokeMathCFunctionInstr::kSavedSpTempIndex).reg()); |
| 5517 __ Bind(&skip_call); | 5296 __ Bind(&skip_call); |
| 5518 } | 5297 } |
| 5519 | 5298 |
| 5520 | |
| 5521 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5299 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5522 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5300 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 5523 InvokeDoublePow(compiler, this); | 5301 InvokeDoublePow(compiler, this); |
| 5524 return; | 5302 return; |
| 5525 } | 5303 } |
| 5526 // Save RSP. | 5304 // Save RSP. |
| 5527 __ movq(locs()->temp(kSavedSpTempIndex).reg(), RSP); | 5305 __ movq(locs()->temp(kSavedSpTempIndex).reg(), RSP); |
| 5528 __ ReserveAlignedFrameSpace(0); | 5306 __ ReserveAlignedFrameSpace(0); |
| 5529 __ movaps(XMM0, locs()->in(0).fpu_reg()); | 5307 __ movaps(XMM0, locs()->in(0).fpu_reg()); |
| 5530 if (InputCount() == 2) { | 5308 if (InputCount() == 2) { |
| 5531 ASSERT(locs()->in(1).fpu_reg() == XMM1); | 5309 ASSERT(locs()->in(1).fpu_reg() == XMM1); |
| 5532 } | 5310 } |
| 5533 | 5311 |
| 5534 __ CallRuntime(TargetFunction(), InputCount()); | 5312 __ CallRuntime(TargetFunction(), InputCount()); |
| 5535 __ movaps(locs()->out(0).fpu_reg(), XMM0); | 5313 __ movaps(locs()->out(0).fpu_reg(), XMM0); |
| 5536 // Restore RSP. | 5314 // Restore RSP. |
| 5537 __ movq(RSP, locs()->temp(kSavedSpTempIndex).reg()); | 5315 __ movq(RSP, locs()->temp(kSavedSpTempIndex).reg()); |
| 5538 } | 5316 } |
| 5539 | 5317 |
| 5540 | |
| 5541 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 5318 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |
| 5542 bool opt) const { | 5319 bool opt) const { |
| 5543 // Only use this instruction in optimized code. | 5320 // Only use this instruction in optimized code. |
| 5544 ASSERT(opt); | 5321 ASSERT(opt); |
| 5545 const intptr_t kNumInputs = 1; | 5322 const intptr_t kNumInputs = 1; |
| 5546 LocationSummary* summary = | 5323 LocationSummary* summary = |
| 5547 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); | 5324 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 5548 if (representation() == kUnboxedDouble) { | 5325 if (representation() == kUnboxedDouble) { |
| 5549 if (index() == 0) { | 5326 if (index() == 0) { |
| 5550 summary->set_in( | 5327 summary->set_in( |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5563 } else { | 5340 } else { |
| 5564 ASSERT(index() == 1); | 5341 ASSERT(index() == 1); |
| 5565 summary->set_in( | 5342 summary->set_in( |
| 5566 0, Location::Pair(Location::Any(), Location::RequiresRegister())); | 5343 0, Location::Pair(Location::Any(), Location::RequiresRegister())); |
| 5567 } | 5344 } |
| 5568 summary->set_out(0, Location::RequiresRegister()); | 5345 summary->set_out(0, Location::RequiresRegister()); |
| 5569 } | 5346 } |
| 5570 return summary; | 5347 return summary; |
| 5571 } | 5348 } |
| 5572 | 5349 |
| 5573 | |
| 5574 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5350 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5575 ASSERT(locs()->in(0).IsPairLocation()); | 5351 ASSERT(locs()->in(0).IsPairLocation()); |
| 5576 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5352 PairLocation* pair = locs()->in(0).AsPairLocation(); |
| 5577 Location in_loc = pair->At(index()); | 5353 Location in_loc = pair->At(index()); |
| 5578 if (representation() == kUnboxedDouble) { | 5354 if (representation() == kUnboxedDouble) { |
| 5579 XmmRegister out = locs()->out(0).fpu_reg(); | 5355 XmmRegister out = locs()->out(0).fpu_reg(); |
| 5580 XmmRegister in = in_loc.fpu_reg(); | 5356 XmmRegister in = in_loc.fpu_reg(); |
| 5581 __ movaps(out, in); | 5357 __ movaps(out, in); |
| 5582 } else { | 5358 } else { |
| 5583 ASSERT(representation() == kTagged); | 5359 ASSERT(representation() == kTagged); |
| 5584 Register out = locs()->out(0).reg(); | 5360 Register out = locs()->out(0).reg(); |
| 5585 Register in = in_loc.reg(); | 5361 Register in = in_loc.reg(); |
| 5586 __ movq(out, in); | 5362 __ movq(out, in); |
| 5587 } | 5363 } |
| 5588 } | 5364 } |
| 5589 | 5365 |
| 5590 | |
| 5591 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone, | 5366 LocationSummary* TruncDivModInstr::MakeLocationSummary(Zone* zone, |
| 5592 bool opt) const { | 5367 bool opt) const { |
| 5593 const intptr_t kNumInputs = 2; | 5368 const intptr_t kNumInputs = 2; |
| 5594 const intptr_t kNumTemps = 0; | 5369 const intptr_t kNumTemps = 0; |
| 5595 LocationSummary* summary = new (zone) | 5370 LocationSummary* summary = new (zone) |
| 5596 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5371 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5597 // Both inputs must be writable because they will be untagged. | 5372 // Both inputs must be writable because they will be untagged. |
| 5598 summary->set_in(0, Location::RegisterLocation(RAX)); | 5373 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 5599 summary->set_in(1, Location::WritableRegister()); | 5374 summary->set_in(1, Location::WritableRegister()); |
| 5600 summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX), | 5375 summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX), |
| 5601 Location::RegisterLocation(RDX))); | 5376 Location::RegisterLocation(RDX))); |
| 5602 return summary; | 5377 return summary; |
| 5603 } | 5378 } |
| 5604 | 5379 |
| 5605 | |
| 5606 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5380 void TruncDivModInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5607 ASSERT(CanDeoptimize()); | 5381 ASSERT(CanDeoptimize()); |
| 5608 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 5382 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
| 5609 Register left = locs()->in(0).reg(); | 5383 Register left = locs()->in(0).reg(); |
| 5610 Register right = locs()->in(1).reg(); | 5384 Register right = locs()->in(1).reg(); |
| 5611 ASSERT(locs()->out(0).IsPairLocation()); | 5385 ASSERT(locs()->out(0).IsPairLocation()); |
| 5612 PairLocation* pair = locs()->out(0).AsPairLocation(); | 5386 PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 5613 Register result1 = pair->At(0).reg(); | 5387 Register result1 = pair->At(0).reg(); |
| 5614 Register result2 = pair->At(1).reg(); | 5388 Register result2 = pair->At(1).reg(); |
| 5615 Label not_32bit, done; | 5389 Label not_32bit, done; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5685 __ subq(RDX, right); | 5459 __ subq(RDX, right); |
| 5686 } | 5460 } |
| 5687 __ Bind(&all_done); | 5461 __ Bind(&all_done); |
| 5688 | 5462 |
| 5689 __ SmiTag(RAX); | 5463 __ SmiTag(RAX); |
| 5690 __ SmiTag(RDX); | 5464 __ SmiTag(RDX); |
| 5691 // Note that the result of an integer division/modulo of two | 5465 // Note that the result of an integer division/modulo of two |
| 5692 // in-range arguments, cannot create out-of-range result. | 5466 // in-range arguments, cannot create out-of-range result. |
| 5693 } | 5467 } |
| 5694 | 5468 |
| 5695 | |
| 5696 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 5469 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
| 5697 Zone* zone, | 5470 Zone* zone, |
| 5698 bool opt) const { | 5471 bool opt) const { |
| 5699 return MakeCallSummary(zone); | 5472 return MakeCallSummary(zone); |
| 5700 } | 5473 } |
| 5701 | 5474 |
| 5702 | |
| 5703 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 5475 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5704 comparison()->InitializeLocationSummary(zone, opt); | 5476 comparison()->InitializeLocationSummary(zone, opt); |
| 5705 // Branches don't produce a result. | 5477 // Branches don't produce a result. |
| 5706 comparison()->locs()->set_out(0, Location::NoLocation()); | 5478 comparison()->locs()->set_out(0, Location::NoLocation()); |
| 5707 return comparison()->locs(); | 5479 return comparison()->locs(); |
| 5708 } | 5480 } |
| 5709 | 5481 |
| 5710 | |
| 5711 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5482 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5712 comparison()->EmitBranchCode(compiler, this); | 5483 comparison()->EmitBranchCode(compiler, this); |
| 5713 } | 5484 } |
| 5714 | 5485 |
| 5715 | |
| 5716 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 5486 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
| 5717 bool opt) const { | 5487 bool opt) const { |
| 5718 const intptr_t kNumInputs = 1; | 5488 const intptr_t kNumInputs = 1; |
| 5719 const bool need_mask_temp = IsBitTest(); | 5489 const bool need_mask_temp = IsBitTest(); |
| 5720 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 5490 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
| 5721 LocationSummary* summary = new (zone) | 5491 LocationSummary* summary = new (zone) |
| 5722 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5492 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5723 summary->set_in(0, Location::RequiresRegister()); | 5493 summary->set_in(0, Location::RequiresRegister()); |
| 5724 if (!IsNullCheck()) { | 5494 if (!IsNullCheck()) { |
| 5725 summary->set_temp(0, Location::RequiresRegister()); | 5495 summary->set_temp(0, Location::RequiresRegister()); |
| 5726 if (need_mask_temp) { | 5496 if (need_mask_temp) { |
| 5727 summary->set_temp(1, Location::RequiresRegister()); | 5497 summary->set_temp(1, Location::RequiresRegister()); |
| 5728 } | 5498 } |
| 5729 } | 5499 } |
| 5730 return summary; | 5500 return summary; |
| 5731 } | 5501 } |
| 5732 | 5502 |
| 5733 | |
| 5734 void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) { | 5503 void CheckClassInstr::EmitNullCheck(FlowGraphCompiler* compiler, Label* deopt) { |
| 5735 __ CompareObject(locs()->in(0).reg(), Object::null_object()); | 5504 __ CompareObject(locs()->in(0).reg(), Object::null_object()); |
| 5736 Condition cond = IsDeoptIfNull() ? EQUAL : NOT_EQUAL; | 5505 Condition cond = IsDeoptIfNull() ? EQUAL : NOT_EQUAL; |
| 5737 __ j(cond, deopt); | 5506 __ j(cond, deopt); |
| 5738 } | 5507 } |
| 5739 | 5508 |
| 5740 | |
| 5741 void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler, | 5509 void CheckClassInstr::EmitBitTest(FlowGraphCompiler* compiler, |
| 5742 intptr_t min, | 5510 intptr_t min, |
| 5743 intptr_t max, | 5511 intptr_t max, |
| 5744 intptr_t mask, | 5512 intptr_t mask, |
| 5745 Label* deopt) { | 5513 Label* deopt) { |
| 5746 Register biased_cid = locs()->temp(0).reg(); | 5514 Register biased_cid = locs()->temp(0).reg(); |
| 5747 __ subq(biased_cid, Immediate(min)); | 5515 __ subq(biased_cid, Immediate(min)); |
| 5748 __ cmpq(biased_cid, Immediate(max - min)); | 5516 __ cmpq(biased_cid, Immediate(max - min)); |
| 5749 __ j(ABOVE, deopt); | 5517 __ j(ABOVE, deopt); |
| 5750 | 5518 |
| 5751 Register mask_reg = locs()->temp(1).reg(); | 5519 Register mask_reg = locs()->temp(1).reg(); |
| 5752 __ movq(mask_reg, Immediate(mask)); | 5520 __ movq(mask_reg, Immediate(mask)); |
| 5753 __ btq(mask_reg, biased_cid); | 5521 __ btq(mask_reg, biased_cid); |
| 5754 __ j(NOT_CARRY, deopt); | 5522 __ j(NOT_CARRY, deopt); |
| 5755 } | 5523 } |
| 5756 | 5524 |
| 5757 | |
| 5758 int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler, | 5525 int CheckClassInstr::EmitCheckCid(FlowGraphCompiler* compiler, |
| 5759 int bias, | 5526 int bias, |
| 5760 intptr_t cid_start, | 5527 intptr_t cid_start, |
| 5761 intptr_t cid_end, | 5528 intptr_t cid_end, |
| 5762 bool is_last, | 5529 bool is_last, |
| 5763 Label* is_ok, | 5530 Label* is_ok, |
| 5764 Label* deopt, | 5531 Label* deopt, |
| 5765 bool use_near_jump) { | 5532 bool use_near_jump) { |
| 5766 Register biased_cid = locs()->temp(0).reg(); | 5533 Register biased_cid = locs()->temp(0).reg(); |
| 5767 Condition no_match, match; | 5534 Condition no_match, match; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 5784 } else { | 5551 } else { |
| 5785 if (use_near_jump) { | 5552 if (use_near_jump) { |
| 5786 __ j(match, is_ok, Assembler::kNearJump); | 5553 __ j(match, is_ok, Assembler::kNearJump); |
| 5787 } else { | 5554 } else { |
| 5788 __ j(match, is_ok); | 5555 __ j(match, is_ok); |
| 5789 } | 5556 } |
| 5790 } | 5557 } |
| 5791 return bias; | 5558 return bias; |
| 5792 } | 5559 } |
| 5793 | 5560 |
| 5794 | |
| 5795 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 5561 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
| 5796 bool opt) const { | 5562 bool opt) const { |
| 5797 const intptr_t kNumInputs = 1; | 5563 const intptr_t kNumInputs = 1; |
| 5798 const intptr_t kNumTemps = 0; | 5564 const intptr_t kNumTemps = 0; |
| 5799 LocationSummary* summary = new (zone) | 5565 LocationSummary* summary = new (zone) |
| 5800 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5566 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5801 summary->set_in(0, Location::RequiresRegister()); | 5567 summary->set_in(0, Location::RequiresRegister()); |
| 5802 return summary; | 5568 return summary; |
| 5803 } | 5569 } |
| 5804 | 5570 |
| 5805 | |
| 5806 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5571 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5807 Register value = locs()->in(0).reg(); | 5572 Register value = locs()->in(0).reg(); |
| 5808 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, | 5573 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, |
| 5809 licm_hoisted_ ? ICData::kHoisted : 0); | 5574 licm_hoisted_ ? ICData::kHoisted : 0); |
| 5810 __ BranchIfNotSmi(value, deopt); | 5575 __ BranchIfNotSmi(value, deopt); |
| 5811 } | 5576 } |
| 5812 | 5577 |
| 5813 | |
| 5814 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 5578 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
| 5815 bool opt) const { | 5579 bool opt) const { |
| 5816 const intptr_t kNumInputs = 1; | 5580 const intptr_t kNumInputs = 1; |
| 5817 const intptr_t kNumTemps = 0; | 5581 const intptr_t kNumTemps = 0; |
| 5818 LocationSummary* summary = new (zone) | 5582 LocationSummary* summary = new (zone) |
| 5819 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5583 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5820 summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister() | 5584 summary->set_in(0, cids_.IsSingleCid() ? Location::RequiresRegister() |
| 5821 : Location::WritableRegister()); | 5585 : Location::WritableRegister()); |
| 5822 return summary; | 5586 return summary; |
| 5823 } | 5587 } |
| 5824 | 5588 |
| 5825 | |
| 5826 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5589 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5827 Register value = locs()->in(0).reg(); | 5590 Register value = locs()->in(0).reg(); |
| 5828 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 5591 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
| 5829 if (cids_.IsSingleCid()) { | 5592 if (cids_.IsSingleCid()) { |
| 5830 __ CompareImmediate(value, Immediate(Smi::RawValue(cids_.cid_start))); | 5593 __ CompareImmediate(value, Immediate(Smi::RawValue(cids_.cid_start))); |
| 5831 __ j(NOT_ZERO, deopt); | 5594 __ j(NOT_ZERO, deopt); |
| 5832 } else { | 5595 } else { |
| 5833 __ AddImmediate(value, Immediate(-Smi::RawValue(cids_.cid_start))); | 5596 __ AddImmediate(value, Immediate(-Smi::RawValue(cids_.cid_start))); |
| 5834 __ cmpq(value, Immediate(Smi::RawValue(cids_.Extent()))); | 5597 __ cmpq(value, Immediate(Smi::RawValue(cids_.Extent()))); |
| 5835 __ j(ABOVE, deopt); | 5598 __ j(ABOVE, deopt); |
| 5836 } | 5599 } |
| 5837 } | 5600 } |
| 5838 | 5601 |
| 5839 | |
| 5840 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, | 5602 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, |
| 5841 bool opt) const { | 5603 bool opt) const { |
| 5842 const intptr_t kNumInputs = 2; | 5604 const intptr_t kNumInputs = 2; |
| 5843 const intptr_t kNumTemps = 0; | 5605 const intptr_t kNumTemps = 0; |
| 5844 LocationSummary* locs = new (zone) LocationSummary( | 5606 LocationSummary* locs = new (zone) LocationSummary( |
| 5845 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 5607 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 5846 locs->set_in(kLengthPos, Location::RequiresRegister()); | 5608 locs->set_in(kLengthPos, Location::RequiresRegister()); |
| 5847 locs->set_in(kIndexPos, Location::RequiresRegister()); | 5609 locs->set_in(kIndexPos, Location::RequiresRegister()); |
| 5848 return locs; | 5610 return locs; |
| 5849 } | 5611 } |
| 5850 | 5612 |
| 5851 | |
| 5852 class RangeErrorSlowPath : public SlowPathCode { | 5613 class RangeErrorSlowPath : public SlowPathCode { |
| 5853 public: | 5614 public: |
| 5854 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) | 5615 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) |
| 5855 : instruction_(instruction), try_index_(try_index) {} | 5616 : instruction_(instruction), try_index_(try_index) {} |
| 5856 | 5617 |
| 5857 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 5618 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5858 if (Assembler::EmittingComments()) { | 5619 if (Assembler::EmittingComments()) { |
| 5859 __ Comment("slow path check bound operation"); | 5620 __ Comment("slow path check bound operation"); |
| 5860 } | 5621 } |
| 5861 __ Bind(entry_label()); | 5622 __ Bind(entry_label()); |
| 5862 LocationSummary* locs = instruction_->locs(); | 5623 LocationSummary* locs = instruction_->locs(); |
| 5863 compiler->SaveLiveRegisters(locs); | 5624 compiler->SaveLiveRegisters(locs); |
| 5864 __ pushq(locs->in(0).reg()); | 5625 __ pushq(locs->in(0).reg()); |
| 5865 __ pushq(locs->in(1).reg()); | 5626 __ pushq(locs->in(1).reg()); |
| 5866 __ CallRuntime(kRangeErrorRuntimeEntry, 2); | 5627 __ CallRuntime(kRangeErrorRuntimeEntry, 2); |
| 5867 compiler->AddDescriptor( | 5628 compiler->AddDescriptor( |
| 5868 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), | 5629 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), |
| 5869 instruction_->deopt_id(), instruction_->token_pos(), try_index_); | 5630 instruction_->deopt_id(), instruction_->token_pos(), try_index_); |
| 5870 compiler->RecordSafepoint(locs, 2); | 5631 compiler->RecordSafepoint(locs, 2); |
| 5871 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); | 5632 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |
| 5872 compiler->EmitCatchEntryState(env, try_index_); | 5633 compiler->EmitCatchEntryState(env, try_index_); |
| 5873 __ int3(); | 5634 __ int3(); |
| 5874 } | 5635 } |
| 5875 | 5636 |
| 5876 private: | 5637 private: |
| 5877 GenericCheckBoundInstr* instruction_; | 5638 GenericCheckBoundInstr* instruction_; |
| 5878 intptr_t try_index_; | 5639 intptr_t try_index_; |
| 5879 }; | 5640 }; |
| 5880 | 5641 |
| 5881 | |
| 5882 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5642 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5883 RangeErrorSlowPath* slow_path = | 5643 RangeErrorSlowPath* slow_path = |
| 5884 new RangeErrorSlowPath(this, compiler->CurrentTryIndex()); | 5644 new RangeErrorSlowPath(this, compiler->CurrentTryIndex()); |
| 5885 compiler->AddSlowPathCode(slow_path); | 5645 compiler->AddSlowPathCode(slow_path); |
| 5886 Location length_loc = locs()->in(kLengthPos); | 5646 Location length_loc = locs()->in(kLengthPos); |
| 5887 Location index_loc = locs()->in(kIndexPos); | 5647 Location index_loc = locs()->in(kIndexPos); |
| 5888 Register length = length_loc.reg(); | 5648 Register length = length_loc.reg(); |
| 5889 Register index = index_loc.reg(); | 5649 Register index = index_loc.reg(); |
| 5890 const intptr_t index_cid = this->index()->Type()->ToCid(); | 5650 const intptr_t index_cid = this->index()->Type()->ToCid(); |
| 5891 if (index_cid != kSmiCid) { | 5651 if (index_cid != kSmiCid) { |
| 5892 __ BranchIfNotSmi(index, slow_path->entry_label()); | 5652 __ BranchIfNotSmi(index, slow_path->entry_label()); |
| 5893 } | 5653 } |
| 5894 __ cmpq(index, length); | 5654 __ cmpq(index, length); |
| 5895 __ j(ABOVE_EQUAL, slow_path->entry_label()); | 5655 __ j(ABOVE_EQUAL, slow_path->entry_label()); |
| 5896 } | 5656 } |
| 5897 | 5657 |
| 5898 | |
| 5899 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 5658 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
| 5900 bool opt) const { | 5659 bool opt) const { |
| 5901 const intptr_t kNumInputs = 2; | 5660 const intptr_t kNumInputs = 2; |
| 5902 const intptr_t kNumTemps = 0; | 5661 const intptr_t kNumTemps = 0; |
| 5903 LocationSummary* locs = new (zone) | 5662 LocationSummary* locs = new (zone) |
| 5904 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5663 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5905 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 5664 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
| 5906 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 5665 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
| 5907 return locs; | 5666 return locs; |
| 5908 } | 5667 } |
| 5909 | 5668 |
| 5910 | |
| 5911 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5669 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5912 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 5670 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |
| 5913 flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 5671 flags |= licm_hoisted_ ? ICData::kHoisted : 0; |
| 5914 Label* deopt = | 5672 Label* deopt = |
| 5915 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); | 5673 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); |
| 5916 | 5674 |
| 5917 Location length_loc = locs()->in(kLengthPos); | 5675 Location length_loc = locs()->in(kLengthPos); |
| 5918 Location index_loc = locs()->in(kIndexPos); | 5676 Location index_loc = locs()->in(kIndexPos); |
| 5919 | 5677 |
| 5920 if (length_loc.IsConstant() && index_loc.IsConstant()) { | 5678 if (length_loc.IsConstant() && index_loc.IsConstant()) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5952 Register length = length_loc.reg(); | 5710 Register length = length_loc.reg(); |
| 5953 Register index = index_loc.reg(); | 5711 Register index = index_loc.reg(); |
| 5954 if (index_cid != kSmiCid) { | 5712 if (index_cid != kSmiCid) { |
| 5955 __ BranchIfNotSmi(index, deopt); | 5713 __ BranchIfNotSmi(index, deopt); |
| 5956 } | 5714 } |
| 5957 __ cmpq(index, length); | 5715 __ cmpq(index, length); |
| 5958 __ j(ABOVE_EQUAL, deopt); | 5716 __ j(ABOVE_EQUAL, deopt); |
| 5959 } | 5717 } |
| 5960 } | 5718 } |
| 5961 | 5719 |
| 5962 | |
| 5963 template <typename OperandType> | 5720 template <typename OperandType> |
| 5964 static void EmitInt64Arithmetic(FlowGraphCompiler* compiler, | 5721 static void EmitInt64Arithmetic(FlowGraphCompiler* compiler, |
| 5965 Token::Kind op_kind, | 5722 Token::Kind op_kind, |
| 5966 Register left, | 5723 Register left, |
| 5967 const OperandType& right, | 5724 const OperandType& right, |
| 5968 Label* deopt) { | 5725 Label* deopt) { |
| 5969 switch (op_kind) { | 5726 switch (op_kind) { |
| 5970 case Token::kADD: | 5727 case Token::kADD: |
| 5971 __ addq(left, right); | 5728 __ addq(left, right); |
| 5972 break; | 5729 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5984 break; | 5741 break; |
| 5985 case Token::kMUL: | 5742 case Token::kMUL: |
| 5986 __ imulq(left, right); | 5743 __ imulq(left, right); |
| 5987 break; | 5744 break; |
| 5988 default: | 5745 default: |
| 5989 UNREACHABLE(); | 5746 UNREACHABLE(); |
| 5990 } | 5747 } |
| 5991 if (deopt != NULL) __ j(OVERFLOW, deopt); | 5748 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 5992 } | 5749 } |
| 5993 | 5750 |
| 5994 | |
| 5995 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5751 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, |
| 5996 bool opt) const { | 5752 bool opt) const { |
| 5997 const intptr_t kNumInputs = 2; | 5753 const intptr_t kNumInputs = 2; |
| 5998 const intptr_t kNumTemps = 0; | 5754 const intptr_t kNumTemps = 0; |
| 5999 LocationSummary* summary = new (zone) | 5755 LocationSummary* summary = new (zone) |
| 6000 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5756 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6001 summary->set_in(0, Location::RequiresRegister()); | 5757 summary->set_in(0, Location::RequiresRegister()); |
| 6002 summary->set_in(1, Location::RequiresRegister()); | 5758 summary->set_in(1, Location::RequiresRegister()); |
| 6003 summary->set_out(0, Location::SameAsFirstInput()); | 5759 summary->set_out(0, Location::SameAsFirstInput()); |
| 6004 return summary; | 5760 return summary; |
| 6005 } | 5761 } |
| 6006 | 5762 |
| 6007 | |
| 6008 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5763 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6009 const Register left = locs()->in(0).reg(); | 5764 const Register left = locs()->in(0).reg(); |
| 6010 const Register right = locs()->in(1).reg(); | 5765 const Register right = locs()->in(1).reg(); |
| 6011 const Register out = locs()->out(0).reg(); | 5766 const Register out = locs()->out(0).reg(); |
| 6012 | 5767 |
| 6013 ASSERT(out == left); | 5768 ASSERT(out == left); |
| 6014 | 5769 |
| 6015 Label* deopt = NULL; | 5770 Label* deopt = NULL; |
| 6016 if (CanDeoptimize()) { | 5771 if (CanDeoptimize()) { |
| 6017 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5772 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 6018 } | 5773 } |
| 6019 | 5774 |
| 6020 EmitInt64Arithmetic(compiler, op_kind(), left, right, deopt); | 5775 EmitInt64Arithmetic(compiler, op_kind(), left, right, deopt); |
| 6021 } | 5776 } |
| 6022 | 5777 |
| 6023 | |
| 6024 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, | 5778 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, |
| 6025 bool opt) const { | 5779 bool opt) const { |
| 6026 const intptr_t kNumInputs = 1; | 5780 const intptr_t kNumInputs = 1; |
| 6027 const intptr_t kNumTemps = 0; | 5781 const intptr_t kNumTemps = 0; |
| 6028 LocationSummary* summary = new (zone) | 5782 LocationSummary* summary = new (zone) |
| 6029 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5783 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6030 summary->set_in(0, Location::RequiresRegister()); | 5784 summary->set_in(0, Location::RequiresRegister()); |
| 6031 summary->set_out(0, Location::SameAsFirstInput()); | 5785 summary->set_out(0, Location::SameAsFirstInput()); |
| 6032 return summary; | 5786 return summary; |
| 6033 } | 5787 } |
| 6034 | 5788 |
| 6035 | |
| 6036 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5789 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6037 ASSERT(op_kind() == Token::kBIT_NOT); | 5790 ASSERT(op_kind() == Token::kBIT_NOT); |
| 6038 const Register left = locs()->in(0).reg(); | 5791 const Register left = locs()->in(0).reg(); |
| 6039 const Register out = locs()->out(0).reg(); | 5792 const Register out = locs()->out(0).reg(); |
| 6040 ASSERT(out == left); | 5793 ASSERT(out == left); |
| 6041 __ notq(left); | 5794 __ notq(left); |
| 6042 } | 5795 } |
| 6043 | 5796 |
| 6044 | |
| 6045 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, | 5797 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, |
| 6046 bool opt) const { | 5798 bool opt) const { |
| 6047 const intptr_t kNumInputs = 2; | 5799 const intptr_t kNumInputs = 2; |
| 6048 const intptr_t kNumTemps = can_overflow() ? 1 : 0; | 5800 const intptr_t kNumTemps = can_overflow() ? 1 : 0; |
| 6049 LocationSummary* summary = new (zone) | 5801 LocationSummary* summary = new (zone) |
| 6050 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5802 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6051 summary->set_in(0, Location::RequiresRegister()); | 5803 summary->set_in(0, Location::RequiresRegister()); |
| 6052 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 5804 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
| 6053 if (kNumTemps > 0) { | 5805 if (kNumTemps > 0) { |
| 6054 summary->set_temp(0, Location::RequiresRegister()); | 5806 summary->set_temp(0, Location::RequiresRegister()); |
| 6055 } | 5807 } |
| 6056 summary->set_out(0, Location::SameAsFirstInput()); | 5808 summary->set_out(0, Location::SameAsFirstInput()); |
| 6057 return summary; | 5809 return summary; |
| 6058 } | 5810 } |
| 6059 | 5811 |
| 6060 | |
| 6061 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5812 void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6062 const Register left = locs()->in(0).reg(); | 5813 const Register left = locs()->in(0).reg(); |
| 6063 const Register out = locs()->out(0).reg(); | 5814 const Register out = locs()->out(0).reg(); |
| 6064 ASSERT(left == out); | 5815 ASSERT(left == out); |
| 6065 | 5816 |
| 6066 Label* deopt = NULL; | 5817 Label* deopt = NULL; |
| 6067 if (CanDeoptimize()) { | 5818 if (CanDeoptimize()) { |
| 6068 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5819 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 6069 } | 5820 } |
| 6070 if (locs()->in(1).IsConstant()) { | 5821 if (locs()->in(1).IsConstant()) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6124 // Shift for result now we know there is no overflow. | 5875 // Shift for result now we know there is no overflow. |
| 6125 __ shlq(left, RCX); | 5876 __ shlq(left, RCX); |
| 6126 break; | 5877 break; |
| 6127 } | 5878 } |
| 6128 default: | 5879 default: |
| 6129 UNREACHABLE(); | 5880 UNREACHABLE(); |
| 6130 } | 5881 } |
| 6131 } | 5882 } |
| 6132 } | 5883 } |
| 6133 | 5884 |
| 6134 | |
| 6135 CompileType BinaryUint32OpInstr::ComputeType() const { | 5885 CompileType BinaryUint32OpInstr::ComputeType() const { |
| 6136 return CompileType::FromCid(kSmiCid); | 5886 return CompileType::FromCid(kSmiCid); |
| 6137 } | 5887 } |
| 6138 | 5888 |
| 6139 | |
| 6140 CompileType ShiftUint32OpInstr::ComputeType() const { | 5889 CompileType ShiftUint32OpInstr::ComputeType() const { |
| 6141 return CompileType::FromCid(kSmiCid); | 5890 return CompileType::FromCid(kSmiCid); |
| 6142 } | 5891 } |
| 6143 | 5892 |
| 6144 | |
| 6145 CompileType UnaryUint32OpInstr::ComputeType() const { | 5893 CompileType UnaryUint32OpInstr::ComputeType() const { |
| 6146 return CompileType::FromCid(kSmiCid); | 5894 return CompileType::FromCid(kSmiCid); |
| 6147 } | 5895 } |
| 6148 | 5896 |
| 6149 | |
| 6150 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 5897 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 6151 bool opt) const { | 5898 bool opt) const { |
| 6152 const intptr_t kNumInputs = 2; | 5899 const intptr_t kNumInputs = 2; |
| 6153 const intptr_t kNumTemps = 0; | 5900 const intptr_t kNumTemps = 0; |
| 6154 LocationSummary* summary = new (zone) | 5901 LocationSummary* summary = new (zone) |
| 6155 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5902 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6156 summary->set_in(0, Location::RequiresRegister()); | 5903 summary->set_in(0, Location::RequiresRegister()); |
| 6157 summary->set_in(1, Location::RequiresRegister()); | 5904 summary->set_in(1, Location::RequiresRegister()); |
| 6158 summary->set_out(0, Location::SameAsFirstInput()); | 5905 summary->set_out(0, Location::SameAsFirstInput()); |
| 6159 return summary; | 5906 return summary; |
| 6160 } | 5907 } |
| 6161 | 5908 |
| 6162 | |
| 6163 template <typename OperandType> | 5909 template <typename OperandType> |
| 6164 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, | 5910 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, |
| 6165 Token::Kind op_kind, | 5911 Token::Kind op_kind, |
| 6166 Register left, | 5912 Register left, |
| 6167 const OperandType& right, | 5913 const OperandType& right, |
| 6168 Label* deopt) { | 5914 Label* deopt) { |
| 6169 switch (op_kind) { | 5915 switch (op_kind) { |
| 6170 case Token::kADD: | 5916 case Token::kADD: |
| 6171 __ addl(left, right); | 5917 __ addl(left, right); |
| 6172 break; | 5918 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 6184 break; | 5930 break; |
| 6185 case Token::kMUL: | 5931 case Token::kMUL: |
| 6186 __ imull(left, right); | 5932 __ imull(left, right); |
| 6187 break; | 5933 break; |
| 6188 default: | 5934 default: |
| 6189 UNREACHABLE(); | 5935 UNREACHABLE(); |
| 6190 } | 5936 } |
| 6191 if (deopt != NULL) __ j(OVERFLOW, deopt); | 5937 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 6192 } | 5938 } |
| 6193 | 5939 |
| 6194 | |
| 6195 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5940 void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6196 Register left = locs()->in(0).reg(); | 5941 Register left = locs()->in(0).reg(); |
| 6197 Register right = locs()->in(1).reg(); | 5942 Register right = locs()->in(1).reg(); |
| 6198 Register out = locs()->out(0).reg(); | 5943 Register out = locs()->out(0).reg(); |
| 6199 ASSERT(out == left); | 5944 ASSERT(out == left); |
| 6200 switch (op_kind()) { | 5945 switch (op_kind()) { |
| 6201 case Token::kBIT_AND: | 5946 case Token::kBIT_AND: |
| 6202 case Token::kBIT_OR: | 5947 case Token::kBIT_OR: |
| 6203 case Token::kBIT_XOR: | 5948 case Token::kBIT_XOR: |
| 6204 case Token::kADD: | 5949 case Token::kADD: |
| 6205 case Token::kSUB: | 5950 case Token::kSUB: |
| 6206 case Token::kMUL: | 5951 case Token::kMUL: |
| 6207 EmitIntegerArithmetic(compiler, op_kind(), left, right, NULL); | 5952 EmitIntegerArithmetic(compiler, op_kind(), left, right, NULL); |
| 6208 return; | 5953 return; |
| 6209 default: | 5954 default: |
| 6210 UNREACHABLE(); | 5955 UNREACHABLE(); |
| 6211 } | 5956 } |
| 6212 } | 5957 } |
| 6213 | 5958 |
| 6214 | |
| 6215 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, | 5959 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 6216 bool opt) const { | 5960 bool opt) const { |
| 6217 const intptr_t kNumInputs = 2; | 5961 const intptr_t kNumInputs = 2; |
| 6218 const intptr_t kNumTemps = 0; | 5962 const intptr_t kNumTemps = 0; |
| 6219 LocationSummary* summary = new (zone) | 5963 LocationSummary* summary = new (zone) |
| 6220 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5964 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6221 summary->set_in(0, Location::RequiresRegister()); | 5965 summary->set_in(0, Location::RequiresRegister()); |
| 6222 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 5966 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
| 6223 summary->set_out(0, Location::SameAsFirstInput()); | 5967 summary->set_out(0, Location::SameAsFirstInput()); |
| 6224 return summary; | 5968 return summary; |
| 6225 } | 5969 } |
| 6226 | 5970 |
| 6227 | |
| 6228 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5971 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6229 const intptr_t kShifterLimit = 31; | 5972 const intptr_t kShifterLimit = 31; |
| 6230 | 5973 |
| 6231 Register left = locs()->in(0).reg(); | 5974 Register left = locs()->in(0).reg(); |
| 6232 Register out = locs()->out(0).reg(); | 5975 Register out = locs()->out(0).reg(); |
| 6233 ASSERT(left == out); | 5976 ASSERT(left == out); |
| 6234 | 5977 |
| 6235 | |
| 6236 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 5978 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 6237 | 5979 |
| 6238 if (locs()->in(1).IsConstant()) { | 5980 if (locs()->in(1).IsConstant()) { |
| 6239 // Shifter is constant. | 5981 // Shifter is constant. |
| 6240 | 5982 |
| 6241 const Object& constant = locs()->in(1).constant(); | 5983 const Object& constant = locs()->in(1).constant(); |
| 6242 ASSERT(constant.IsSmi()); | 5984 ASSERT(constant.IsSmi()); |
| 6243 const intptr_t shift_value = Smi::Cast(constant).Value(); | 5985 const intptr_t shift_value = Smi::Cast(constant).Value(); |
| 6244 | 5986 |
| 6245 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). | 5987 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6288 } | 6030 } |
| 6289 | 6031 |
| 6290 __ Bind(&zero); | 6032 __ Bind(&zero); |
| 6291 // Shift was greater than 31 bits, just return zero. | 6033 // Shift was greater than 31 bits, just return zero. |
| 6292 __ xorq(left, left); | 6034 __ xorq(left, left); |
| 6293 | 6035 |
| 6294 // Exit path. | 6036 // Exit path. |
| 6295 __ Bind(&done); | 6037 __ Bind(&done); |
| 6296 } | 6038 } |
| 6297 | 6039 |
| 6298 | |
| 6299 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 6040 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 6300 bool opt) const { | 6041 bool opt) const { |
| 6301 const intptr_t kNumInputs = 1; | 6042 const intptr_t kNumInputs = 1; |
| 6302 const intptr_t kNumTemps = 0; | 6043 const intptr_t kNumTemps = 0; |
| 6303 LocationSummary* summary = new (zone) | 6044 LocationSummary* summary = new (zone) |
| 6304 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6045 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6305 summary->set_in(0, Location::RequiresRegister()); | 6046 summary->set_in(0, Location::RequiresRegister()); |
| 6306 summary->set_out(0, Location::SameAsFirstInput()); | 6047 summary->set_out(0, Location::SameAsFirstInput()); |
| 6307 return summary; | 6048 return summary; |
| 6308 } | 6049 } |
| 6309 | 6050 |
| 6310 | |
| 6311 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6051 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6312 Register out = locs()->out(0).reg(); | 6052 Register out = locs()->out(0).reg(); |
| 6313 ASSERT(locs()->in(0).reg() == out); | 6053 ASSERT(locs()->in(0).reg() == out); |
| 6314 | 6054 |
| 6315 ASSERT(op_kind() == Token::kBIT_NOT); | 6055 ASSERT(op_kind() == Token::kBIT_NOT); |
| 6316 | 6056 |
| 6317 __ notl(out); | 6057 __ notl(out); |
| 6318 } | 6058 } |
| 6319 | 6059 |
| 6320 | |
| 6321 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 6060 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
| 6322 | 6061 |
| 6323 | |
| 6324 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 6062 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |
| 6325 bool opt) const { | 6063 bool opt) const { |
| 6326 const intptr_t kNumInputs = 1; | 6064 const intptr_t kNumInputs = 1; |
| 6327 const intptr_t kNumTemps = 0; | 6065 const intptr_t kNumTemps = 0; |
| 6328 LocationSummary* summary = new (zone) | 6066 LocationSummary* summary = new (zone) |
| 6329 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6067 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6330 if (from() == kUnboxedMint) { | 6068 if (from() == kUnboxedMint) { |
| 6331 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 6069 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 6332 summary->set_in(0, Location::RequiresRegister()); | 6070 summary->set_in(0, Location::RequiresRegister()); |
| 6333 summary->set_out(0, Location::SameAsFirstInput()); | 6071 summary->set_out(0, Location::SameAsFirstInput()); |
| 6334 } else if (to() == kUnboxedMint) { | 6072 } else if (to() == kUnboxedMint) { |
| 6335 ASSERT((from() == kUnboxedInt32) || (from() == kUnboxedUint32)); | 6073 ASSERT((from() == kUnboxedInt32) || (from() == kUnboxedUint32)); |
| 6336 summary->set_in(0, Location::RequiresRegister()); | 6074 summary->set_in(0, Location::RequiresRegister()); |
| 6337 summary->set_out(0, Location::SameAsFirstInput()); | 6075 summary->set_out(0, Location::SameAsFirstInput()); |
| 6338 } else { | 6076 } else { |
| 6339 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 6077 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 6340 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | 6078 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 6341 summary->set_in(0, Location::RequiresRegister()); | 6079 summary->set_in(0, Location::RequiresRegister()); |
| 6342 summary->set_out(0, Location::SameAsFirstInput()); | 6080 summary->set_out(0, Location::SameAsFirstInput()); |
| 6343 } | 6081 } |
| 6344 return summary; | 6082 return summary; |
| 6345 } | 6083 } |
| 6346 | 6084 |
| 6347 | |
| 6348 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6085 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6349 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { | 6086 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { |
| 6350 const Register value = locs()->in(0).reg(); | 6087 const Register value = locs()->in(0).reg(); |
| 6351 const Register out = locs()->out(0).reg(); | 6088 const Register out = locs()->out(0).reg(); |
| 6352 // Representations are bitwise equivalent but we want to normalize | 6089 // Representations are bitwise equivalent but we want to normalize |
| 6353 // upperbits for safety reasons. | 6090 // upperbits for safety reasons. |
| 6354 // TODO(vegorov) if we ensure that we never use upperbits we could | 6091 // TODO(vegorov) if we ensure that we never use upperbits we could |
| 6355 // avoid this. | 6092 // avoid this. |
| 6356 __ movl(out, value); | 6093 __ movl(out, value); |
| 6357 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { | 6094 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6392 } else { | 6129 } else { |
| 6393 // Sign extend. | 6130 // Sign extend. |
| 6394 ASSERT(from() == kUnboxedInt32); | 6131 ASSERT(from() == kUnboxedInt32); |
| 6395 __ movsxd(out, value); | 6132 __ movsxd(out, value); |
| 6396 } | 6133 } |
| 6397 } else { | 6134 } else { |
| 6398 UNREACHABLE(); | 6135 UNREACHABLE(); |
| 6399 } | 6136 } |
| 6400 } | 6137 } |
| 6401 | 6138 |
| 6402 | |
| 6403 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6139 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6404 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | 6140 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 6405 } | 6141 } |
| 6406 | 6142 |
| 6407 | |
| 6408 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6143 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6409 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, | 6144 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, |
| 6410 locs()); | 6145 locs()); |
| 6411 __ int3(); | 6146 __ int3(); |
| 6412 } | 6147 } |
| 6413 | 6148 |
| 6414 | |
| 6415 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6149 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6416 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | 6150 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 6417 } | 6151 } |
| 6418 | 6152 |
| 6419 | |
| 6420 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6153 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6421 compiler->SetNeedsStackTrace(catch_try_index()); | 6154 compiler->SetNeedsStackTrace(catch_try_index()); |
| 6422 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, | 6155 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, |
| 6423 2, locs()); | 6156 2, locs()); |
| 6424 __ int3(); | 6157 __ int3(); |
| 6425 } | 6158 } |
| 6426 | 6159 |
| 6427 | |
| 6428 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6160 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6429 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | 6161 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 6430 } | 6162 } |
| 6431 | 6163 |
| 6432 | |
| 6433 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6164 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6434 __ Stop(message()); | 6165 __ Stop(message()); |
| 6435 } | 6166 } |
| 6436 | 6167 |
| 6437 | |
| 6438 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6168 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6439 if (!compiler->CanFallThroughTo(normal_entry())) { | 6169 if (!compiler->CanFallThroughTo(normal_entry())) { |
| 6440 __ jmp(compiler->GetJumpLabel(normal_entry())); | 6170 __ jmp(compiler->GetJumpLabel(normal_entry())); |
| 6441 } | 6171 } |
| 6442 } | 6172 } |
| 6443 | 6173 |
| 6444 | |
| 6445 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { | 6174 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6446 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | 6175 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 6447 } | 6176 } |
| 6448 | 6177 |
| 6449 | |
| 6450 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6178 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6451 if (!compiler->is_optimizing()) { | 6179 if (!compiler->is_optimizing()) { |
| 6452 if (FLAG_reorder_basic_blocks) { | 6180 if (FLAG_reorder_basic_blocks) { |
| 6453 compiler->EmitEdgeCounter(block()->preorder_number()); | 6181 compiler->EmitEdgeCounter(block()->preorder_number()); |
| 6454 } | 6182 } |
| 6455 // Add a deoptimization descriptor for deoptimizing instructions that | 6183 // Add a deoptimization descriptor for deoptimizing instructions that |
| 6456 // may be inserted before this instruction. | 6184 // may be inserted before this instruction. |
| 6457 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), | 6185 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), |
| 6458 TokenPosition::kNoSource); | 6186 TokenPosition::kNoSource); |
| 6459 } | 6187 } |
| 6460 if (HasParallelMove()) { | 6188 if (HasParallelMove()) { |
| 6461 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 6189 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 6462 } | 6190 } |
| 6463 | 6191 |
| 6464 // We can fall through if the successor is the next block in the list. | 6192 // We can fall through if the successor is the next block in the list. |
| 6465 // Otherwise, we need a jump. | 6193 // Otherwise, we need a jump. |
| 6466 if (!compiler->CanFallThroughTo(successor())) { | 6194 if (!compiler->CanFallThroughTo(successor())) { |
| 6467 __ jmp(compiler->GetJumpLabel(successor())); | 6195 __ jmp(compiler->GetJumpLabel(successor())); |
| 6468 } | 6196 } |
| 6469 } | 6197 } |
| 6470 | 6198 |
| 6471 | |
| 6472 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 6199 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |
| 6473 bool opt) const { | 6200 bool opt) const { |
| 6474 const intptr_t kNumInputs = 1; | 6201 const intptr_t kNumInputs = 1; |
| 6475 const intptr_t kNumTemps = 1; | 6202 const intptr_t kNumTemps = 1; |
| 6476 | 6203 |
| 6477 LocationSummary* summary = new (zone) | 6204 LocationSummary* summary = new (zone) |
| 6478 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6205 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6479 | 6206 |
| 6480 summary->set_in(0, Location::RequiresRegister()); | 6207 summary->set_in(0, Location::RequiresRegister()); |
| 6481 summary->set_temp(0, Location::RequiresRegister()); | 6208 summary->set_temp(0, Location::RequiresRegister()); |
| 6482 | 6209 |
| 6483 return summary; | 6210 return summary; |
| 6484 } | 6211 } |
| 6485 | 6212 |
| 6486 | |
| 6487 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6213 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6488 Register offset_reg = locs()->in(0).reg(); | 6214 Register offset_reg = locs()->in(0).reg(); |
| 6489 Register target_address_reg = locs()->temp(0).reg(); | 6215 Register target_address_reg = locs()->temp(0).reg(); |
| 6490 | 6216 |
| 6491 { | 6217 { |
| 6492 const intptr_t kRIPRelativeLeaqSize = 7; | 6218 const intptr_t kRIPRelativeLeaqSize = 7; |
| 6493 const intptr_t entry_to_rip_offset = __ CodeSize() + kRIPRelativeLeaqSize; | 6219 const intptr_t entry_to_rip_offset = __ CodeSize() + kRIPRelativeLeaqSize; |
| 6494 __ leaq(target_address_reg, | 6220 __ leaq(target_address_reg, |
| 6495 Address::AddressRIPRelative(-entry_to_rip_offset)); | 6221 Address::AddressRIPRelative(-entry_to_rip_offset)); |
| 6496 ASSERT(__ CodeSize() == entry_to_rip_offset); | 6222 ASSERT(__ CodeSize() == entry_to_rip_offset); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 6525 locs->set_in(0, Location::RegisterOrConstant(left())); | 6251 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 6526 // Only one of the inputs can be a constant. Choose register if the first one | 6252 // Only one of the inputs can be a constant. Choose register if the first one |
| 6527 // is a constant. | 6253 // is a constant. |
| 6528 locs->set_in(1, locs->in(0).IsConstant() | 6254 locs->set_in(1, locs->in(0).IsConstant() |
| 6529 ? Location::RequiresRegister() | 6255 ? Location::RequiresRegister() |
| 6530 : Location::RegisterOrConstant(right())); | 6256 : Location::RegisterOrConstant(right())); |
| 6531 locs->set_out(0, Location::RequiresRegister()); | 6257 locs->set_out(0, Location::RequiresRegister()); |
| 6532 return locs; | 6258 return locs; |
| 6533 } | 6259 } |
| 6534 | 6260 |
| 6535 | |
| 6536 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 6261 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 6537 BranchLabels labels) { | 6262 BranchLabels labels) { |
| 6538 Location left = locs()->in(0); | 6263 Location left = locs()->in(0); |
| 6539 Location right = locs()->in(1); | 6264 Location right = locs()->in(1); |
| 6540 ASSERT(!left.IsConstant() || !right.IsConstant()); | 6265 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 6541 Condition true_condition; | 6266 Condition true_condition; |
| 6542 if (left.IsConstant()) { | 6267 if (left.IsConstant()) { |
| 6543 true_condition = compiler->EmitEqualityRegConstCompare( | 6268 true_condition = compiler->EmitEqualityRegConstCompare( |
| 6544 right.reg(), left.constant(), needs_number_check(), token_pos(), | 6269 right.reg(), left.constant(), needs_number_check(), token_pos(), |
| 6545 deopt_id_); | 6270 deopt_id_); |
| 6546 } else if (right.IsConstant()) { | 6271 } else if (right.IsConstant()) { |
| 6547 true_condition = compiler->EmitEqualityRegConstCompare( | 6272 true_condition = compiler->EmitEqualityRegConstCompare( |
| 6548 left.reg(), right.constant(), needs_number_check(), token_pos(), | 6273 left.reg(), right.constant(), needs_number_check(), token_pos(), |
| 6549 deopt_id_); | 6274 deopt_id_); |
| 6550 } else { | 6275 } else { |
| 6551 true_condition = compiler->EmitEqualityRegRegCompare( | 6276 true_condition = compiler->EmitEqualityRegRegCompare( |
| 6552 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); | 6277 left.reg(), right.reg(), needs_number_check(), token_pos(), deopt_id_); |
| 6553 } | 6278 } |
| 6554 if (kind() != Token::kEQ_STRICT) { | 6279 if (kind() != Token::kEQ_STRICT) { |
| 6555 ASSERT(kind() == Token::kNE_STRICT); | 6280 ASSERT(kind() == Token::kNE_STRICT); |
| 6556 true_condition = NegateCondition(true_condition); | 6281 true_condition = NegateCondition(true_condition); |
| 6557 } | 6282 } |
| 6558 return true_condition; | 6283 return true_condition; |
| 6559 } | 6284 } |
| 6560 | 6285 |
| 6561 | |
| 6562 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 6286 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |
| 6563 bool opt) const { | 6287 bool opt) const { |
| 6564 const intptr_t kNumInputs = 1; | 6288 const intptr_t kNumInputs = 1; |
| 6565 const intptr_t kNumTemps = 0; | 6289 const intptr_t kNumTemps = 0; |
| 6566 LocationSummary* summary = new (zone) | 6290 LocationSummary* summary = new (zone) |
| 6567 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6291 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 6568 summary->set_in(0, Location::RegisterLocation(RAX)); // Function. | 6292 summary->set_in(0, Location::RegisterLocation(RAX)); // Function. |
| 6569 summary->set_out(0, Location::RegisterLocation(RAX)); | 6293 summary->set_out(0, Location::RegisterLocation(RAX)); |
| 6570 return summary; | 6294 return summary; |
| 6571 } | 6295 } |
| 6572 | 6296 |
| 6573 | |
| 6574 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6297 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6575 // Arguments descriptor is expected in R10. | 6298 // Arguments descriptor is expected in R10. |
| 6576 const intptr_t argument_count = ArgumentCount(); // Includes type args. | 6299 const intptr_t argument_count = ArgumentCount(); // Includes type args. |
| 6577 const Array& arguments_descriptor = | 6300 const Array& arguments_descriptor = |
| 6578 Array::ZoneHandle(Z, GetArgumentsDescriptor()); | 6301 Array::ZoneHandle(Z, GetArgumentsDescriptor()); |
| 6579 __ LoadObject(R10, arguments_descriptor); | 6302 __ LoadObject(R10, arguments_descriptor); |
| 6580 | 6303 |
| 6581 // Function in RAX. | 6304 // Function in RAX. |
| 6582 ASSERT(locs()->in(0).reg() == RAX); | 6305 ASSERT(locs()->in(0).reg() == RAX); |
| 6583 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); | 6306 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 6597 compiler->AddDeoptIndexAtCall(deopt_id_after); | 6320 compiler->AddDeoptIndexAtCall(deopt_id_after); |
| 6598 } | 6321 } |
| 6599 // Add deoptimization continuation point after the call and before the | 6322 // Add deoptimization continuation point after the call and before the |
| 6600 // arguments are removed. | 6323 // arguments are removed. |
| 6601 // In optimized code this descriptor is needed for exception handling. | 6324 // In optimized code this descriptor is needed for exception handling. |
| 6602 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, | 6325 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, |
| 6603 token_pos()); | 6326 token_pos()); |
| 6604 __ Drop(argument_count); | 6327 __ Drop(argument_count); |
| 6605 } | 6328 } |
| 6606 | 6329 |
| 6607 | |
| 6608 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 6330 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
| 6609 bool opt) const { | 6331 bool opt) const { |
| 6610 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), | 6332 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
| 6611 LocationSummary::kNoCall); | 6333 LocationSummary::kNoCall); |
| 6612 } | 6334 } |
| 6613 | 6335 |
| 6614 | |
| 6615 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6336 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6616 Register value = locs()->in(0).reg(); | 6337 Register value = locs()->in(0).reg(); |
| 6617 Register result = locs()->out(0).reg(); | 6338 Register result = locs()->out(0).reg(); |
| 6618 | 6339 |
| 6619 Label done; | 6340 Label done; |
| 6620 __ LoadObject(result, Bool::True()); | 6341 __ LoadObject(result, Bool::True()); |
| 6621 __ CompareRegisters(result, value); | 6342 __ CompareRegisters(result, value); |
| 6622 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 6343 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 6623 __ LoadObject(result, Bool::False()); | 6344 __ LoadObject(result, Bool::False()); |
| 6624 __ Bind(&done); | 6345 __ Bind(&done); |
| 6625 } | 6346 } |
| 6626 | 6347 |
| 6627 | |
| 6628 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 6348 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
| 6629 bool opt) const { | 6349 bool opt) const { |
| 6630 return MakeCallSummary(zone); | 6350 return MakeCallSummary(zone); |
| 6631 } | 6351 } |
| 6632 | 6352 |
| 6633 | |
| 6634 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6353 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6635 const Code& stub = Code::ZoneHandle( | 6354 const Code& stub = Code::ZoneHandle( |
| 6636 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 6355 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |
| 6637 const StubEntry stub_entry(stub); | 6356 const StubEntry stub_entry(stub); |
| 6638 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, | 6357 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, |
| 6639 locs()); | 6358 locs()); |
| 6640 compiler->AddStubCallTarget(stub); | 6359 compiler->AddStubCallTarget(stub); |
| 6641 __ Drop(ArgumentCount()); // Discard arguments. | 6360 __ Drop(ArgumentCount()); // Discard arguments. |
| 6642 } | 6361 } |
| 6643 | 6362 |
| 6644 | |
| 6645 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6363 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6646 ASSERT(!compiler->is_optimizing()); | 6364 ASSERT(!compiler->is_optimizing()); |
| 6647 __ CallPatchable(*StubCode::DebugStepCheck_entry()); | 6365 __ CallPatchable(*StubCode::DebugStepCheck_entry()); |
| 6648 compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos()); | 6366 compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos()); |
| 6649 compiler->RecordSafepoint(locs()); | 6367 compiler->RecordSafepoint(locs()); |
| 6650 } | 6368 } |
| 6651 | 6369 |
| 6652 | |
| 6653 } // namespace dart | 6370 } // namespace dart |
| 6654 | 6371 |
| 6655 #undef __ | 6372 #undef __ |
| 6656 | 6373 |
| 6657 #endif // defined TARGET_ARCH_X64 | 6374 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |