| 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 10 matching lines...) Expand all Loading... |
| 21 #include "vm/symbols.h" | 21 #include "vm/symbols.h" |
| 22 | 22 |
| 23 #define __ compiler->assembler()-> | 23 #define __ compiler->assembler()-> |
| 24 #define Z (compiler->zone()) | 24 #define Z (compiler->zone()) |
| 25 | 25 |
| 26 namespace dart { | 26 namespace dart { |
| 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 = new(zone) LocationSummary( | 31 LocationSummary* result = |
| 32 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 | 37 |
| 38 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, | 38 LocationSummary* PushArgumentInstr::MakeLocationSummary(Zone* zone, |
| 39 bool opt) const { | 39 bool opt) const { |
| 40 const intptr_t kNumInputs = 1; | 40 const intptr_t kNumInputs = 1; |
| 41 const intptr_t kNumTemps = 0; | 41 const intptr_t kNumTemps = 0; |
| 42 LocationSummary* locs = new(zone) LocationSummary( | 42 LocationSummary* locs = new (zone) |
| 43 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 43 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 44 locs->set_in(0, Location::AnyOrConstant(value())); | 44 locs->set_in(0, Location::AnyOrConstant(value())); |
| 45 return locs; | 45 return locs; |
| 46 } | 46 } |
| 47 | 47 |
| 48 | 48 |
| 49 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 49 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 50 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 50 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
| 51 // where PushArgument is handled by BindInstr::EmitNativeCode. | 51 // where PushArgument is handled by BindInstr::EmitNativeCode. |
| 52 if (compiler->is_optimizing()) { | 52 if (compiler->is_optimizing()) { |
| 53 Location value = locs()->in(0); | 53 Location value = locs()->in(0); |
| 54 if (value.IsRegister()) { | 54 if (value.IsRegister()) { |
| 55 __ pushq(value.reg()); | 55 __ pushq(value.reg()); |
| 56 } else if (value.IsConstant()) { | 56 } else if (value.IsConstant()) { |
| 57 __ PushObject(value.constant()); | 57 __ PushObject(value.constant()); |
| 58 } else { | 58 } else { |
| 59 ASSERT(value.IsStackSlot()); | 59 ASSERT(value.IsStackSlot()); |
| 60 __ pushq(value.ToStackSlotAddress()); | 60 __ pushq(value.ToStackSlotAddress()); |
| 61 } | 61 } |
| 62 } | 62 } |
| 63 } | 63 } |
| 64 | 64 |
| 65 | 65 |
| 66 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, | 66 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 67 bool opt) const { | |
| 68 const intptr_t kNumInputs = 1; | 67 const intptr_t kNumInputs = 1; |
| 69 const intptr_t kNumTemps = 0; | 68 const intptr_t kNumTemps = 0; |
| 70 LocationSummary* locs = new(zone) LocationSummary( | 69 LocationSummary* locs = new (zone) |
| 71 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 70 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 72 locs->set_in(0, Location::RegisterLocation(RAX)); | 71 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 73 return locs; | 72 return locs; |
| 74 } | 73 } |
| 75 | 74 |
| 76 | 75 |
| 77 // Attempt optimized compilation at return instruction instead of at the entry. | 76 // Attempt optimized compilation at return instruction instead of at the entry. |
| 78 // The entry needs to be patchable, no inlined objects are allowed in the area | 77 // The entry needs to be patchable, no inlined objects are allowed in the area |
| 79 // that will be overwritten by the patch instruction: a jump). | 78 // that will be overwritten by the patch instruction: a jump). |
| 80 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 79 void ReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 81 Register result = locs()->in(0).reg(); | 80 Register result = locs()->in(0).reg(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 104 __ LeaveDartFrame(); // Disallows constant pool use. | 103 __ LeaveDartFrame(); // Disallows constant pool use. |
| 105 __ ret(); | 104 __ ret(); |
| 106 // This ReturnInstr may be emitted out of order by the optimizer. The next | 105 // This ReturnInstr may be emitted out of order by the optimizer. The next |
| 107 // block may be a target expecting a properly set constant pool pointer. | 106 // block may be a target expecting a properly set constant pool pointer. |
| 108 __ set_constant_pool_allowed(true); | 107 __ set_constant_pool_allowed(true); |
| 109 } | 108 } |
| 110 | 109 |
| 111 | 110 |
| 112 static Condition NegateCondition(Condition condition) { | 111 static Condition NegateCondition(Condition condition) { |
| 113 switch (condition) { | 112 switch (condition) { |
| 114 case EQUAL: return NOT_EQUAL; | 113 case EQUAL: |
| 115 case NOT_EQUAL: return EQUAL; | 114 return NOT_EQUAL; |
| 116 case LESS: return GREATER_EQUAL; | 115 case NOT_EQUAL: |
| 117 case LESS_EQUAL: return GREATER; | 116 return EQUAL; |
| 118 case GREATER: return LESS_EQUAL; | 117 case LESS: |
| 119 case GREATER_EQUAL: return LESS; | 118 return GREATER_EQUAL; |
| 120 case BELOW: return ABOVE_EQUAL; | 119 case LESS_EQUAL: |
| 121 case BELOW_EQUAL: return ABOVE; | 120 return GREATER; |
| 122 case ABOVE: return BELOW_EQUAL; | 121 case GREATER: |
| 123 case ABOVE_EQUAL: return BELOW; | 122 return LESS_EQUAL; |
| 124 case PARITY_EVEN: return PARITY_ODD; | 123 case GREATER_EQUAL: |
| 125 case PARITY_ODD: return PARITY_EVEN; | 124 return LESS; |
| 125 case BELOW: |
| 126 return ABOVE_EQUAL; |
| 127 case BELOW_EQUAL: |
| 128 return ABOVE; |
| 129 case ABOVE: |
| 130 return BELOW_EQUAL; |
| 131 case ABOVE_EQUAL: |
| 132 return BELOW; |
| 133 case PARITY_EVEN: |
| 134 return PARITY_ODD; |
| 135 case PARITY_ODD: |
| 136 return PARITY_EVEN; |
| 126 default: | 137 default: |
| 127 UNIMPLEMENTED(); | 138 UNIMPLEMENTED(); |
| 128 return EQUAL; | 139 return EQUAL; |
| 129 } | 140 } |
| 130 } | 141 } |
| 131 | 142 |
| 132 | 143 |
| 133 // Detect pattern when one value is zero and another is a power of 2. | 144 // Detect pattern when one value is zero and another is a power of 2. |
| 134 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { | 145 static bool IsPowerOfTwoKind(intptr_t v1, intptr_t v2) { |
| 135 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || | 146 return (Utils::IsPowerOfTwo(v1) && (v2 == 0)) || |
| (...skipping 11 matching lines...) Expand all Loading... |
| 147 | 158 |
| 148 | 159 |
| 149 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 160 void IfThenElseInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 150 ASSERT(locs()->out(0).reg() == RDX); | 161 ASSERT(locs()->out(0).reg() == RDX); |
| 151 | 162 |
| 152 // Clear upper part of the out register. We are going to use setcc on it | 163 // Clear upper part of the out register. We are going to use setcc on it |
| 153 // which is a byte move. | 164 // which is a byte move. |
| 154 __ xorq(RDX, RDX); | 165 __ xorq(RDX, RDX); |
| 155 | 166 |
| 156 // Emit comparison code. This must not overwrite the result register. | 167 // Emit comparison code. This must not overwrite the result register. |
| 157 BranchLabels labels = { NULL, NULL, NULL }; | 168 BranchLabels labels = {NULL, NULL, NULL}; |
| 158 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); | 169 Condition true_condition = comparison()->EmitComparisonCode(compiler, labels); |
| 159 | 170 |
| 160 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); | 171 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); |
| 161 | 172 |
| 162 intptr_t true_value = if_true_; | 173 intptr_t true_value = if_true_; |
| 163 intptr_t false_value = if_false_; | 174 intptr_t false_value = if_false_; |
| 164 | 175 |
| 165 if (is_power_of_two_kind) { | 176 if (is_power_of_two_kind) { |
| 166 if (true_value == 0) { | 177 if (true_value == 0) { |
| 167 // We need to have zero in RDX on true_condition. | 178 // We need to have zero in RDX on true_condition. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 179 } | 190 } |
| 180 | 191 |
| 181 __ setcc(true_condition, DL); | 192 __ setcc(true_condition, DL); |
| 182 | 193 |
| 183 if (is_power_of_two_kind) { | 194 if (is_power_of_two_kind) { |
| 184 const intptr_t shift = | 195 const intptr_t shift = |
| 185 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); | 196 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
| 186 __ shlq(RDX, Immediate(shift + kSmiTagSize)); | 197 __ shlq(RDX, Immediate(shift + kSmiTagSize)); |
| 187 } else { | 198 } else { |
| 188 __ decq(RDX); | 199 __ decq(RDX); |
| 189 __ AndImmediate(RDX, | 200 __ AndImmediate( |
| 190 Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value))); | 201 RDX, Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value))); |
| 191 if (false_value != 0) { | 202 if (false_value != 0) { |
| 192 __ AddImmediate(RDX, Immediate(Smi::RawValue(false_value))); | 203 __ AddImmediate(RDX, Immediate(Smi::RawValue(false_value))); |
| 193 } | 204 } |
| 194 } | 205 } |
| 195 } | 206 } |
| 196 | 207 |
| 197 | 208 |
| 198 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 209 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
| 199 bool opt) const { | 210 bool opt) const { |
| 200 const intptr_t kNumInputs = 0; | 211 const intptr_t kNumInputs = 0; |
| 201 const intptr_t stack_index = (local().index() < 0) | 212 const intptr_t stack_index = (local().index() < 0) |
| 202 ? kFirstLocalSlotFromFp - local().index() | 213 ? kFirstLocalSlotFromFp - local().index() |
| 203 : kParamEndSlotFromFp - local().index(); | 214 : kParamEndSlotFromFp - local().index(); |
| 204 return LocationSummary::Make(zone, | 215 return LocationSummary::Make(zone, kNumInputs, |
| 205 kNumInputs, | |
| 206 Location::StackSlot(stack_index), | 216 Location::StackSlot(stack_index), |
| 207 LocationSummary::kNoCall); | 217 LocationSummary::kNoCall); |
| 208 } | 218 } |
| 209 | 219 |
| 210 | 220 |
| 211 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 221 void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 212 ASSERT(!compiler->is_optimizing()); | 222 ASSERT(!compiler->is_optimizing()); |
| 213 // Nothing to do. | 223 // Nothing to do. |
| 214 } | 224 } |
| 215 | 225 |
| 216 | 226 |
| 217 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, | 227 LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone, |
| 218 bool opt) const { | 228 bool opt) const { |
| 219 const intptr_t kNumInputs = 1; | 229 const intptr_t kNumInputs = 1; |
| 220 return LocationSummary::Make(zone, | 230 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
| 221 kNumInputs, | |
| 222 Location::SameAsFirstInput(), | |
| 223 LocationSummary::kNoCall); | 231 LocationSummary::kNoCall); |
| 224 } | 232 } |
| 225 | 233 |
| 226 | 234 |
| 227 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 235 void StoreLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 228 Register value = locs()->in(0).reg(); | 236 Register value = locs()->in(0).reg(); |
| 229 Register result = locs()->out(0).reg(); | 237 Register result = locs()->out(0).reg(); |
| 230 ASSERT(result == value); // Assert that register assignment is correct. | 238 ASSERT(result == value); // Assert that register assignment is correct. |
| 231 __ movq(Address(RBP, local().index() * kWordSize), value); | 239 __ movq(Address(RBP, local().index() * kWordSize), value); |
| 232 } | 240 } |
| 233 | 241 |
| 234 | 242 |
| 235 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, | 243 LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone, |
| 236 bool opt) const { | 244 bool opt) const { |
| 237 const intptr_t kNumInputs = 0; | 245 const intptr_t kNumInputs = 0; |
| 238 return LocationSummary::Make(zone, | 246 return LocationSummary::Make(zone, kNumInputs, |
| 239 kNumInputs, | |
| 240 Assembler::IsSafe(value()) | 247 Assembler::IsSafe(value()) |
| 241 ? Location::Constant(this) | 248 ? Location::Constant(this) |
| 242 : Location::RequiresRegister(), | 249 : Location::RequiresRegister(), |
| 243 LocationSummary::kNoCall); | 250 LocationSummary::kNoCall); |
| 244 } | 251 } |
| 245 | 252 |
| 246 | 253 |
| 247 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 254 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 248 // The register allocator drops constant definitions that have no uses. | 255 // The register allocator drops constant definitions that have no uses. |
| 249 Location out = locs()->out(0); | 256 Location out = locs()->out(0); |
| 250 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); | 257 ASSERT(out.IsRegister() || out.IsConstant() || out.IsInvalid()); |
| 251 if (out.IsRegister()) { | 258 if (out.IsRegister()) { |
| 252 Register result = out.reg(); | 259 Register result = out.reg(); |
| 253 __ LoadObject(result, value()); | 260 __ LoadObject(result, value()); |
| 254 } | 261 } |
| 255 } | 262 } |
| 256 | 263 |
| 257 | 264 |
| 258 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 265 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
| 259 bool opt) const { | 266 bool opt) const { |
| 260 const intptr_t kNumInputs = 0; | 267 const intptr_t kNumInputs = 0; |
| 261 const intptr_t kNumTemps = 0; | 268 const intptr_t kNumTemps = 0; |
| 262 LocationSummary* locs = new(zone) LocationSummary( | 269 LocationSummary* locs = new (zone) |
| 263 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 270 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 264 switch (representation()) { | 271 switch (representation()) { |
| 265 case kUnboxedDouble: | 272 case kUnboxedDouble: |
| 266 locs->set_out(0, Location::RequiresFpuRegister()); | 273 locs->set_out(0, Location::RequiresFpuRegister()); |
| 267 break; | 274 break; |
| 268 case kUnboxedInt32: | 275 case kUnboxedInt32: |
| 269 locs->set_out(0, Location::RequiresRegister()); | 276 locs->set_out(0, Location::RequiresRegister()); |
| 270 break; | 277 break; |
| 271 default: | 278 default: |
| 272 UNREACHABLE(); | 279 UNREACHABLE(); |
| 273 break; | 280 break; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 298 UNREACHABLE(); | 305 UNREACHABLE(); |
| 299 } | 306 } |
| 300 } | 307 } |
| 301 } | 308 } |
| 302 | 309 |
| 303 | 310 |
| 304 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, | 311 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, |
| 305 bool opt) const { | 312 bool opt) const { |
| 306 const intptr_t kNumInputs = 2; | 313 const intptr_t kNumInputs = 2; |
| 307 const intptr_t kNumTemps = 0; | 314 const intptr_t kNumTemps = 0; |
| 308 LocationSummary* summary = new(zone) LocationSummary( | 315 LocationSummary* summary = new (zone) |
| 309 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 316 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 310 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. | 317 summary->set_in(0, Location::RegisterLocation(RAX)); // Value. |
| 311 summary->set_in(1, Location::RegisterLocation(RDX)); // Type arguments. | 318 summary->set_in(1, Location::RegisterLocation(RDX)); // Type arguments. |
| 312 summary->set_out(0, Location::RegisterLocation(RAX)); | 319 summary->set_out(0, Location::RegisterLocation(RAX)); |
| 313 return summary; | 320 return summary; |
| 314 } | 321 } |
| 315 | 322 |
| 316 | 323 |
| 317 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, | 324 LocationSummary* AssertBooleanInstr::MakeLocationSummary(Zone* zone, |
| 318 bool opt) const { | 325 bool opt) const { |
| 319 const intptr_t kNumInputs = 1; | 326 const intptr_t kNumInputs = 1; |
| 320 const intptr_t kNumTemps = 0; | 327 const intptr_t kNumTemps = 0; |
| 321 LocationSummary* locs = new(zone) LocationSummary( | 328 LocationSummary* locs = new (zone) |
| 322 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 329 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 323 locs->set_in(0, Location::RegisterLocation(RAX)); | 330 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 324 locs->set_out(0, Location::RegisterLocation(RAX)); | 331 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 325 return locs; | 332 return locs; |
| 326 } | 333 } |
| 327 | 334 |
| 328 | 335 |
| 329 static void EmitAssertBoolean(Register reg, | 336 static void EmitAssertBoolean(Register reg, |
| 330 TokenPosition token_pos, | 337 TokenPosition token_pos, |
| 331 intptr_t deopt_id, | 338 intptr_t deopt_id, |
| 332 LocationSummary* locs, | 339 LocationSummary* locs, |
| 333 FlowGraphCompiler* compiler) { | 340 FlowGraphCompiler* compiler) { |
| 334 // Check that the type of the value is allowed in conditional context. | 341 // Check that the type of the value is allowed in conditional context. |
| 335 // Call the runtime if the object is not bool::true or bool::false. | 342 // Call the runtime if the object is not bool::true or bool::false. |
| 336 ASSERT(locs->always_calls()); | 343 ASSERT(locs->always_calls()); |
| 337 Label done; | 344 Label done; |
| 338 | 345 |
| 339 if (Isolate::Current()->type_checks()) { | 346 if (Isolate::Current()->type_checks()) { |
| 340 __ CompareObject(reg, Bool::True()); | 347 __ CompareObject(reg, Bool::True()); |
| 341 __ j(EQUAL, &done, Assembler::kNearJump); | 348 __ j(EQUAL, &done, Assembler::kNearJump); |
| 342 __ CompareObject(reg, Bool::False()); | 349 __ CompareObject(reg, Bool::False()); |
| 343 __ j(EQUAL, &done, Assembler::kNearJump); | 350 __ j(EQUAL, &done, Assembler::kNearJump); |
| 344 } else { | 351 } else { |
| 345 ASSERT(Isolate::Current()->asserts()); | 352 ASSERT(Isolate::Current()->asserts()); |
| 346 __ CompareObject(reg, Object::null_instance()); | 353 __ CompareObject(reg, Object::null_instance()); |
| 347 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 354 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 348 } | 355 } |
| 349 | 356 |
| 350 __ pushq(reg); // Push the source object. | 357 __ pushq(reg); // Push the source object. |
| 351 compiler->GenerateRuntimeCall(token_pos, | 358 compiler->GenerateRuntimeCall(token_pos, deopt_id, |
| 352 deopt_id, | 359 kNonBoolTypeErrorRuntimeEntry, 1, locs); |
| 353 kNonBoolTypeErrorRuntimeEntry, | |
| 354 1, | |
| 355 locs); | |
| 356 // We should never return here. | 360 // We should never return here. |
| 357 __ int3(); | 361 __ int3(); |
| 358 __ Bind(&done); | 362 __ Bind(&done); |
| 359 } | 363 } |
| 360 | 364 |
| 361 | 365 |
| 362 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 366 void AssertBooleanInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 363 Register obj = locs()->in(0).reg(); | 367 Register obj = locs()->in(0).reg(); |
| 364 Register result = locs()->out(0).reg(); | 368 Register result = locs()->out(0).reg(); |
| 365 | 369 |
| 366 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); | 370 EmitAssertBoolean(obj, token_pos(), deopt_id(), locs(), compiler); |
| 367 ASSERT(obj == result); | 371 ASSERT(obj == result); |
| 368 } | 372 } |
| 369 | 373 |
| 370 | 374 |
| 371 static Condition TokenKindToIntCondition(Token::Kind kind) { | 375 static Condition TokenKindToIntCondition(Token::Kind kind) { |
| 372 switch (kind) { | 376 switch (kind) { |
| 373 case Token::kEQ: return EQUAL; | 377 case Token::kEQ: |
| 374 case Token::kNE: return NOT_EQUAL; | 378 return EQUAL; |
| 375 case Token::kLT: return LESS; | 379 case Token::kNE: |
| 376 case Token::kGT: return GREATER; | 380 return NOT_EQUAL; |
| 377 case Token::kLTE: return LESS_EQUAL; | 381 case Token::kLT: |
| 378 case Token::kGTE: return GREATER_EQUAL; | 382 return LESS; |
| 383 case Token::kGT: |
| 384 return GREATER; |
| 385 case Token::kLTE: |
| 386 return LESS_EQUAL; |
| 387 case Token::kGTE: |
| 388 return GREATER_EQUAL; |
| 379 default: | 389 default: |
| 380 UNREACHABLE(); | 390 UNREACHABLE(); |
| 381 return OVERFLOW; | 391 return OVERFLOW; |
| 382 } | 392 } |
| 383 } | 393 } |
| 384 | 394 |
| 385 | 395 |
| 386 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, | 396 LocationSummary* EqualityCompareInstr::MakeLocationSummary(Zone* zone, |
| 387 bool opt) const { | 397 bool opt) const { |
| 388 const intptr_t kNumInputs = 2; | 398 const intptr_t kNumInputs = 2; |
| 389 if (operation_cid() == kMintCid) { | 399 if (operation_cid() == kMintCid) { |
| 390 const intptr_t kNumTemps = 0; | 400 const intptr_t kNumTemps = 0; |
| 391 LocationSummary* locs = new(zone) LocationSummary( | 401 LocationSummary* locs = new (zone) |
| 392 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 402 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 393 locs->set_in(0, Location::RequiresRegister()); | 403 locs->set_in(0, Location::RequiresRegister()); |
| 394 locs->set_in(1, Location::RequiresRegister()); | 404 locs->set_in(1, Location::RequiresRegister()); |
| 395 locs->set_out(0, Location::RequiresRegister()); | 405 locs->set_out(0, Location::RequiresRegister()); |
| 396 return locs; | 406 return locs; |
| 397 } | 407 } |
| 398 if (operation_cid() == kDoubleCid) { | 408 if (operation_cid() == kDoubleCid) { |
| 399 const intptr_t kNumTemps = 0; | 409 const intptr_t kNumTemps = 0; |
| 400 LocationSummary* locs = new(zone) LocationSummary( | 410 LocationSummary* locs = new (zone) |
| 401 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 411 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 402 locs->set_in(0, Location::RequiresFpuRegister()); | 412 locs->set_in(0, Location::RequiresFpuRegister()); |
| 403 locs->set_in(1, Location::RequiresFpuRegister()); | 413 locs->set_in(1, Location::RequiresFpuRegister()); |
| 404 locs->set_out(0, Location::RequiresRegister()); | 414 locs->set_out(0, Location::RequiresRegister()); |
| 405 return locs; | 415 return locs; |
| 406 } | 416 } |
| 407 if (operation_cid() == kSmiCid) { | 417 if (operation_cid() == kSmiCid) { |
| 408 const intptr_t kNumTemps = 0; | 418 const intptr_t kNumTemps = 0; |
| 409 LocationSummary* locs = new(zone) LocationSummary( | 419 LocationSummary* locs = new (zone) |
| 410 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 420 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 411 locs->set_in(0, Location::RegisterOrConstant(left())); | 421 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 412 // Only one input can be a constant operand. The case of two constant | 422 // Only one input can be a constant operand. The case of two constant |
| 413 // operands should be handled by constant propagation. | 423 // operands should be handled by constant propagation. |
| 414 // Only right can be a stack slot. | 424 // Only right can be a stack slot. |
| 415 locs->set_in(1, locs->in(0).IsConstant() | 425 locs->set_in(1, locs->in(0).IsConstant() |
| 416 ? Location::RequiresRegister() | 426 ? Location::RequiresRegister() |
| 417 : Location::RegisterOrConstant(right())); | 427 : Location::RegisterOrConstant(right())); |
| 418 locs->set_out(0, Location::RequiresRegister()); | 428 locs->set_out(0, Location::RequiresRegister()); |
| 419 return locs; | 429 return locs; |
| 420 } | 430 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 437 } else { | 447 } else { |
| 438 __ j(ZERO, value_is_smi); | 448 __ j(ZERO, value_is_smi); |
| 439 } | 449 } |
| 440 __ LoadClassId(value_cid_reg, value_reg); | 450 __ LoadClassId(value_cid_reg, value_reg); |
| 441 __ Bind(&done); | 451 __ Bind(&done); |
| 442 } | 452 } |
| 443 | 453 |
| 444 | 454 |
| 445 static Condition FlipCondition(Condition condition) { | 455 static Condition FlipCondition(Condition condition) { |
| 446 switch (condition) { | 456 switch (condition) { |
| 447 case EQUAL: return EQUAL; | 457 case EQUAL: |
| 448 case NOT_EQUAL: return NOT_EQUAL; | 458 return EQUAL; |
| 449 case LESS: return GREATER; | 459 case NOT_EQUAL: |
| 450 case LESS_EQUAL: return GREATER_EQUAL; | 460 return NOT_EQUAL; |
| 451 case GREATER: return LESS; | 461 case LESS: |
| 452 case GREATER_EQUAL: return LESS_EQUAL; | 462 return GREATER; |
| 453 case BELOW: return ABOVE; | 463 case LESS_EQUAL: |
| 454 case BELOW_EQUAL: return ABOVE_EQUAL; | 464 return GREATER_EQUAL; |
| 455 case ABOVE: return BELOW; | 465 case GREATER: |
| 456 case ABOVE_EQUAL: return BELOW_EQUAL; | 466 return LESS; |
| 467 case GREATER_EQUAL: |
| 468 return LESS_EQUAL; |
| 469 case BELOW: |
| 470 return ABOVE; |
| 471 case BELOW_EQUAL: |
| 472 return ABOVE_EQUAL; |
| 473 case ABOVE: |
| 474 return BELOW; |
| 475 case ABOVE_EQUAL: |
| 476 return BELOW_EQUAL; |
| 457 default: | 477 default: |
| 458 UNIMPLEMENTED(); | 478 UNIMPLEMENTED(); |
| 459 return EQUAL; | 479 return EQUAL; |
| 460 } | 480 } |
| 461 } | 481 } |
| 462 | 482 |
| 463 | 483 |
| 464 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, | 484 static void EmitBranchOnCondition(FlowGraphCompiler* compiler, |
| 465 Condition true_condition, | 485 Condition true_condition, |
| 466 BranchLabels labels) { | 486 BranchLabels labels) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 __ cmpq(left.reg(), right.ToStackSlotAddress()); | 518 __ cmpq(left.reg(), right.ToStackSlotAddress()); |
| 499 } else { | 519 } else { |
| 500 __ cmpq(left.reg(), right.reg()); | 520 __ cmpq(left.reg(), right.reg()); |
| 501 } | 521 } |
| 502 return true_condition; | 522 return true_condition; |
| 503 } | 523 } |
| 504 | 524 |
| 505 | 525 |
| 506 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 526 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| 507 switch (kind) { | 527 switch (kind) { |
| 508 case Token::kEQ: return EQUAL; | 528 case Token::kEQ: |
| 509 case Token::kNE: return NOT_EQUAL; | 529 return EQUAL; |
| 510 case Token::kLT: return BELOW; | 530 case Token::kNE: |
| 511 case Token::kGT: return ABOVE; | 531 return NOT_EQUAL; |
| 512 case Token::kLTE: return BELOW_EQUAL; | 532 case Token::kLT: |
| 513 case Token::kGTE: return ABOVE_EQUAL; | 533 return BELOW; |
| 534 case Token::kGT: |
| 535 return ABOVE; |
| 536 case Token::kLTE: |
| 537 return BELOW_EQUAL; |
| 538 case Token::kGTE: |
| 539 return ABOVE_EQUAL; |
| 514 default: | 540 default: |
| 515 UNREACHABLE(); | 541 UNREACHABLE(); |
| 516 return OVERFLOW; | 542 return OVERFLOW; |
| 517 } | 543 } |
| 518 } | 544 } |
| 519 | 545 |
| 520 | 546 |
| 521 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 547 static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 522 const LocationSummary& locs, | 548 const LocationSummary& locs, |
| 523 Token::Kind kind, | 549 Token::Kind kind, |
| 524 BranchLabels labels) { | 550 BranchLabels labels) { |
| 525 XmmRegister left = locs.in(0).fpu_reg(); | 551 XmmRegister left = locs.in(0).fpu_reg(); |
| 526 XmmRegister right = locs.in(1).fpu_reg(); | 552 XmmRegister right = locs.in(1).fpu_reg(); |
| 527 | 553 |
| 528 __ comisd(left, right); | 554 __ comisd(left, right); |
| 529 | 555 |
| 530 Condition true_condition = TokenKindToDoubleCondition(kind); | 556 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 531 Label* nan_result = (true_condition == NOT_EQUAL) | 557 Label* nan_result = |
| 532 ? labels.true_label : labels.false_label; | 558 (true_condition == NOT_EQUAL) ? labels.true_label : labels.false_label; |
| 533 __ j(PARITY_EVEN, nan_result); | 559 __ j(PARITY_EVEN, nan_result); |
| 534 return true_condition; | 560 return true_condition; |
| 535 } | 561 } |
| 536 | 562 |
| 537 | 563 |
| 538 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 564 Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 539 BranchLabels labels) { | 565 BranchLabels labels) { |
| 540 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { | 566 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
| 541 return EmitInt64ComparisonOp(compiler, *locs(), kind()); | 567 return EmitInt64ComparisonOp(compiler, *locs(), kind()); |
| 542 } else { | 568 } else { |
| 543 ASSERT(operation_cid() == kDoubleCid); | 569 ASSERT(operation_cid() == kDoubleCid); |
| 544 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 570 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 545 } | 571 } |
| 546 } | 572 } |
| 547 | 573 |
| 548 | 574 |
| 549 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 575 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 550 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 576 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| 551 | 577 |
| 552 Label is_true, is_false; | 578 Label is_true, is_false; |
| 553 BranchLabels labels = { &is_true, &is_false, &is_false }; | 579 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 554 Condition true_condition = EmitComparisonCode(compiler, labels); | 580 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 555 EmitBranchOnCondition(compiler, true_condition, labels); | 581 EmitBranchOnCondition(compiler, true_condition, labels); |
| 556 | 582 |
| 557 Register result = locs()->out(0).reg(); | 583 Register result = locs()->out(0).reg(); |
| 558 Label done; | 584 Label done; |
| 559 __ Bind(&is_false); | 585 __ Bind(&is_false); |
| 560 __ LoadObject(result, Bool::False()); | 586 __ LoadObject(result, Bool::False()); |
| 561 __ jmp(&done); | 587 __ jmp(&done); |
| 562 __ Bind(&is_true); | 588 __ Bind(&is_true); |
| 563 __ LoadObject(result, Bool::True()); | 589 __ LoadObject(result, Bool::True()); |
| 564 __ Bind(&done); | 590 __ Bind(&done); |
| 565 } | 591 } |
| 566 | 592 |
| 567 | 593 |
| 568 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 594 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 569 BranchInstr* branch) { | 595 BranchInstr* branch) { |
| 570 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 596 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 571 | 597 |
| 572 BranchLabels labels = compiler->CreateBranchLabels(branch); | 598 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 573 Condition true_condition = EmitComparisonCode(compiler, labels); | 599 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 574 EmitBranchOnCondition(compiler, true_condition, labels); | 600 EmitBranchOnCondition(compiler, true_condition, labels); |
| 575 } | 601 } |
| 576 | 602 |
| 577 | 603 |
| 578 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, | 604 LocationSummary* TestSmiInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 579 bool opt) const { | |
| 580 const intptr_t kNumInputs = 2; | 605 const intptr_t kNumInputs = 2; |
| 581 const intptr_t kNumTemps = 0; | 606 const intptr_t kNumTemps = 0; |
| 582 LocationSummary* locs = new(zone) LocationSummary( | 607 LocationSummary* locs = new (zone) |
| 583 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 608 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 584 locs->set_in(0, Location::RequiresRegister()); | 609 locs->set_in(0, Location::RequiresRegister()); |
| 585 // Only one input can be a constant operand. The case of two constant | 610 // Only one input can be a constant operand. The case of two constant |
| 586 // operands should be handled by constant propagation. | 611 // operands should be handled by constant propagation. |
| 587 locs->set_in(1, Location::RegisterOrConstant(right())); | 612 locs->set_in(1, Location::RegisterOrConstant(right())); |
| 588 return locs; | 613 return locs; |
| 589 } | 614 } |
| 590 | 615 |
| 591 | 616 |
| 592 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 617 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 593 BranchLabels labels) { | 618 BranchLabels labels) { |
| 594 Register left_reg = locs()->in(0).reg(); | 619 Register left_reg = locs()->in(0).reg(); |
| 595 Location right = locs()->in(1); | 620 Location right = locs()->in(1); |
| 596 if (right.IsConstant()) { | 621 if (right.IsConstant()) { |
| 597 ASSERT(right.constant().IsSmi()); | 622 ASSERT(right.constant().IsSmi()); |
| 598 const int64_t imm = | 623 const int64_t imm = reinterpret_cast<int64_t>(right.constant().raw()); |
| 599 reinterpret_cast<int64_t>(right.constant().raw()); | |
| 600 __ TestImmediate(left_reg, Immediate(imm)); | 624 __ TestImmediate(left_reg, Immediate(imm)); |
| 601 } else { | 625 } else { |
| 602 __ testq(left_reg, right.reg()); | 626 __ testq(left_reg, right.reg()); |
| 603 } | 627 } |
| 604 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; | 628 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; |
| 605 return true_condition; | 629 return true_condition; |
| 606 } | 630 } |
| 607 | 631 |
| 608 | 632 |
| 609 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 633 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 610 // Never emitted outside of the BranchInstr. | 634 // Never emitted outside of the BranchInstr. |
| 611 UNREACHABLE(); | 635 UNREACHABLE(); |
| 612 } | 636 } |
| 613 | 637 |
| 614 | 638 |
| 615 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 639 void TestSmiInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 616 BranchInstr* branch) { | 640 BranchInstr* branch) { |
| 617 BranchLabels labels = compiler->CreateBranchLabels(branch); | 641 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 618 Condition true_condition = EmitComparisonCode(compiler, labels); | 642 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 619 EmitBranchOnCondition(compiler, true_condition, labels); | 643 EmitBranchOnCondition(compiler, true_condition, labels); |
| 620 } | 644 } |
| 621 | 645 |
| 622 | 646 |
| 623 | |
| 624 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, | 647 LocationSummary* TestCidsInstr::MakeLocationSummary(Zone* zone, |
| 625 bool opt) const { | 648 bool opt) const { |
| 626 const intptr_t kNumInputs = 1; | 649 const intptr_t kNumInputs = 1; |
| 627 const intptr_t kNumTemps = 1; | 650 const intptr_t kNumTemps = 1; |
| 628 LocationSummary* locs = new(zone) LocationSummary( | 651 LocationSummary* locs = new (zone) |
| 629 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 652 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 630 locs->set_in(0, Location::RequiresRegister()); | 653 locs->set_in(0, Location::RequiresRegister()); |
| 631 locs->set_temp(0, Location::RequiresRegister()); | 654 locs->set_temp(0, Location::RequiresRegister()); |
| 632 locs->set_out(0, Location::RequiresRegister()); | 655 locs->set_out(0, Location::RequiresRegister()); |
| 633 return locs; | 656 return locs; |
| 634 } | 657 } |
| 635 | 658 |
| 636 | 659 |
| 637 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 660 Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 638 BranchLabels labels) { | 661 BranchLabels labels) { |
| 639 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); | 662 ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT)); |
| 640 Register val_reg = locs()->in(0).reg(); | 663 Register val_reg = locs()->in(0).reg(); |
| 641 Register cid_reg = locs()->temp(0).reg(); | 664 Register cid_reg = locs()->temp(0).reg(); |
| 642 | 665 |
| 643 Label* deopt = CanDeoptimize() | 666 Label* deopt = |
| 644 ? compiler->AddDeoptStub(deopt_id(), | 667 CanDeoptimize() |
| 645 ICData::kDeoptTestCids, | 668 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptTestCids, |
| 646 licm_hoisted_ ? ICData::kHoisted : 0) | 669 licm_hoisted_ ? ICData::kHoisted : 0) |
| 647 : NULL; | 670 : NULL; |
| 648 | 671 |
| 649 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; | 672 const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0; |
| 650 const ZoneGrowableArray<intptr_t>& data = cid_results(); | 673 const ZoneGrowableArray<intptr_t>& data = cid_results(); |
| 651 ASSERT(data[0] == kSmiCid); | 674 ASSERT(data[0] == kSmiCid); |
| 652 bool result = data[1] == true_result; | 675 bool result = data[1] == true_result; |
| 653 __ testq(val_reg, Immediate(kSmiTagMask)); | 676 __ testq(val_reg, Immediate(kSmiTagMask)); |
| 654 __ j(ZERO, result ? labels.true_label : labels.false_label); | 677 __ j(ZERO, result ? labels.true_label : labels.false_label); |
| 655 __ LoadClassId(cid_reg, val_reg); | 678 __ LoadClassId(cid_reg, val_reg); |
| 656 for (intptr_t i = 2; i < data.length(); i += 2) { | 679 for (intptr_t i = 2; i < data.length(); i += 2) { |
| 657 const intptr_t test_cid = data[i]; | 680 const intptr_t test_cid = data[i]; |
| 658 ASSERT(test_cid != kSmiCid); | 681 ASSERT(test_cid != kSmiCid); |
| 659 result = data[i + 1] == true_result; | 682 result = data[i + 1] == true_result; |
| 660 __ cmpq(cid_reg, Immediate(test_cid)); | 683 __ cmpq(cid_reg, Immediate(test_cid)); |
| 661 __ j(EQUAL, result ? labels.true_label : labels.false_label); | 684 __ j(EQUAL, result ? labels.true_label : labels.false_label); |
| 662 } | 685 } |
| 663 // No match found, deoptimize or false. | 686 // No match found, deoptimize or false. |
| 664 if (deopt == NULL) { | 687 if (deopt == NULL) { |
| 665 Label* target = result ? labels.false_label : labels.true_label; | 688 Label* target = result ? labels.false_label : labels.true_label; |
| 666 if (target != labels.fall_through) { | 689 if (target != labels.fall_through) { |
| 667 __ jmp(target); | 690 __ jmp(target); |
| 668 } | 691 } |
| 669 } else { | 692 } else { |
| 670 __ jmp(deopt); | 693 __ jmp(deopt); |
| 671 } | 694 } |
| 672 // Dummy result as the last instruction is a jump, any conditional | 695 // Dummy result as the last instruction is a jump, any conditional |
| 673 // branch using the result will therefore be skipped. | 696 // branch using the result will therefore be skipped. |
| 674 return ZERO; | 697 return ZERO; |
| 675 } | 698 } |
| 676 | 699 |
| 677 | 700 |
| 678 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 701 void TestCidsInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 679 BranchInstr* branch) { | 702 BranchInstr* branch) { |
| 680 BranchLabels labels = compiler->CreateBranchLabels(branch); | 703 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 681 EmitComparisonCode(compiler, labels); | 704 EmitComparisonCode(compiler, labels); |
| 682 } | 705 } |
| 683 | 706 |
| 684 | 707 |
| 685 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 708 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 686 Register result_reg = locs()->out(0).reg(); | 709 Register result_reg = locs()->out(0).reg(); |
| 687 Label is_true, is_false, done; | 710 Label is_true, is_false, done; |
| 688 BranchLabels labels = { &is_true, &is_false, &is_false }; | 711 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 689 EmitComparisonCode(compiler, labels); | 712 EmitComparisonCode(compiler, labels); |
| 690 __ Bind(&is_false); | 713 __ Bind(&is_false); |
| 691 __ LoadObject(result_reg, Bool::False()); | 714 __ LoadObject(result_reg, Bool::False()); |
| 692 __ jmp(&done, Assembler::kNearJump); | 715 __ jmp(&done, Assembler::kNearJump); |
| 693 __ Bind(&is_true); | 716 __ Bind(&is_true); |
| 694 __ LoadObject(result_reg, Bool::True()); | 717 __ LoadObject(result_reg, Bool::True()); |
| 695 __ Bind(&done); | 718 __ Bind(&done); |
| 696 } | 719 } |
| 697 | 720 |
| 698 | 721 |
| 699 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 722 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
| 700 bool opt) const { | 723 bool opt) const { |
| 701 const intptr_t kNumInputs = 2; | 724 const intptr_t kNumInputs = 2; |
| 702 const intptr_t kNumTemps = 0; | 725 const intptr_t kNumTemps = 0; |
| 703 if (operation_cid() == kDoubleCid) { | 726 if (operation_cid() == kDoubleCid) { |
| 704 LocationSummary* summary = new(zone) LocationSummary( | 727 LocationSummary* summary = new (zone) |
| 705 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 728 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 706 summary->set_in(0, Location::RequiresFpuRegister()); | 729 summary->set_in(0, Location::RequiresFpuRegister()); |
| 707 summary->set_in(1, Location::RequiresFpuRegister()); | 730 summary->set_in(1, Location::RequiresFpuRegister()); |
| 708 summary->set_out(0, Location::RequiresRegister()); | 731 summary->set_out(0, Location::RequiresRegister()); |
| 709 return summary; | 732 return summary; |
| 710 } else if (operation_cid() == kMintCid) { | 733 } else if (operation_cid() == kMintCid) { |
| 711 LocationSummary* summary = new(zone) LocationSummary( | 734 LocationSummary* summary = new (zone) |
| 712 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 735 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 713 summary->set_in(0, Location::RequiresRegister()); | 736 summary->set_in(0, Location::RequiresRegister()); |
| 714 summary->set_in(1, Location::RequiresRegister()); | 737 summary->set_in(1, Location::RequiresRegister()); |
| 715 summary->set_out(0, Location::RequiresRegister()); | 738 summary->set_out(0, Location::RequiresRegister()); |
| 716 return summary; | 739 return summary; |
| 717 } | 740 } |
| 718 ASSERT(operation_cid() == kSmiCid); | 741 ASSERT(operation_cid() == kSmiCid); |
| 719 LocationSummary* summary = new(zone) LocationSummary( | 742 LocationSummary* summary = new (zone) |
| 720 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 743 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 721 summary->set_in(0, Location::RegisterOrConstant(left())); | 744 summary->set_in(0, Location::RegisterOrConstant(left())); |
| 722 // Only one input can be a constant operand. The case of two constant | 745 // Only one input can be a constant operand. The case of two constant |
| 723 // operands should be handled by constant propagation. | 746 // operands should be handled by constant propagation. |
| 724 summary->set_in(1, summary->in(0).IsConstant() | 747 summary->set_in(1, summary->in(0).IsConstant() |
| 725 ? Location::RequiresRegister() | 748 ? Location::RequiresRegister() |
| 726 : Location::RegisterOrConstant(right())); | 749 : Location::RegisterOrConstant(right())); |
| 727 summary->set_out(0, Location::RequiresRegister()); | 750 summary->set_out(0, Location::RequiresRegister()); |
| 728 return summary; | 751 return summary; |
| 729 } | 752 } |
| 730 | 753 |
| 731 | 754 |
| 732 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 755 Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 733 BranchLabels labels) { | 756 BranchLabels labels) { |
| 734 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { | 757 if ((operation_cid() == kSmiCid) || (operation_cid() == kMintCid)) { |
| 735 return EmitInt64ComparisonOp(compiler, *locs(), kind()); | 758 return EmitInt64ComparisonOp(compiler, *locs(), kind()); |
| 736 } else { | 759 } else { |
| 737 ASSERT(operation_cid() == kDoubleCid); | 760 ASSERT(operation_cid() == kDoubleCid); |
| 738 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); | 761 return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels); |
| 739 } | 762 } |
| 740 } | 763 } |
| 741 | 764 |
| 742 | 765 |
| 743 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 766 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 744 Label is_true, is_false; | 767 Label is_true, is_false; |
| 745 BranchLabels labels = { &is_true, &is_false, &is_false }; | 768 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 746 Condition true_condition = EmitComparisonCode(compiler, labels); | 769 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 747 EmitBranchOnCondition(compiler, true_condition, labels); | 770 EmitBranchOnCondition(compiler, true_condition, labels); |
| 748 | 771 |
| 749 Register result = locs()->out(0).reg(); | 772 Register result = locs()->out(0).reg(); |
| 750 Label done; | 773 Label done; |
| 751 __ Bind(&is_false); | 774 __ Bind(&is_false); |
| 752 __ LoadObject(result, Bool::False()); | 775 __ LoadObject(result, Bool::False()); |
| 753 __ jmp(&done); | 776 __ jmp(&done); |
| 754 __ Bind(&is_true); | 777 __ Bind(&is_true); |
| 755 __ LoadObject(result, Bool::True()); | 778 __ LoadObject(result, Bool::True()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 773 | 796 |
| 774 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 797 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 775 SetupNative(); | 798 SetupNative(); |
| 776 Register result = locs()->out(0).reg(); | 799 Register result = locs()->out(0).reg(); |
| 777 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 800 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
| 778 | 801 |
| 779 // Push the result place holder initialized to NULL. | 802 // Push the result place holder initialized to NULL. |
| 780 __ PushObject(Object::null_object()); | 803 __ PushObject(Object::null_object()); |
| 781 // Pass a pointer to the first argument in RAX. | 804 // Pass a pointer to the first argument in RAX. |
| 782 if (!function().HasOptionalParameters()) { | 805 if (!function().HasOptionalParameters()) { |
| 783 __ leaq(RAX, Address(RBP, (kParamEndSlotFromFp + | 806 __ leaq(RAX, |
| 784 function().NumParameters()) * kWordSize)); | 807 Address(RBP, (kParamEndSlotFromFp + function().NumParameters()) * |
| 808 kWordSize)); |
| 785 } else { | 809 } else { |
| 786 __ leaq(RAX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); | 810 __ leaq(RAX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); |
| 787 } | 811 } |
| 788 __ LoadImmediate(R10, Immediate(argc_tag)); | 812 __ LoadImmediate(R10, Immediate(argc_tag)); |
| 789 const StubEntry* stub_entry; | 813 const StubEntry* stub_entry; |
| 790 if (link_lazily()) { | 814 if (link_lazily()) { |
| 791 stub_entry = StubCode::CallBootstrapCFunction_entry(); | 815 stub_entry = StubCode::CallBootstrapCFunction_entry(); |
| 792 ExternalLabel label(NativeEntry::LinkNativeCallEntry()); | 816 ExternalLabel label(NativeEntry::LinkNativeCallEntry()); |
| 793 __ LoadNativeEntry(RBX, &label, kPatchable); | 817 __ LoadNativeEntry(RBX, &label, kPatchable); |
| 794 } else { | 818 } else { |
| 795 stub_entry = (is_bootstrap_native()) ? | 819 stub_entry = (is_bootstrap_native()) |
| 796 StubCode::CallBootstrapCFunction_entry() : | 820 ? StubCode::CallBootstrapCFunction_entry() |
| 797 StubCode::CallNativeCFunction_entry(); | 821 : StubCode::CallNativeCFunction_entry(); |
| 798 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); | 822 const ExternalLabel label(reinterpret_cast<uword>(native_c_function())); |
| 799 __ LoadNativeEntry(RBX, &label, kNotPatchable); | 823 __ LoadNativeEntry(RBX, &label, kNotPatchable); |
| 800 } | 824 } |
| 801 compiler->GenerateCall(token_pos(), | 825 compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther, |
| 802 *stub_entry, | |
| 803 RawPcDescriptors::kOther, | |
| 804 locs()); | 826 locs()); |
| 805 __ popq(result); | 827 __ popq(result); |
| 806 } | 828 } |
| 807 | 829 |
| 808 | 830 |
| 809 static bool CanBeImmediateIndex(Value* index, intptr_t cid) { | 831 static bool CanBeImmediateIndex(Value* index, intptr_t cid) { |
| 810 if (!index->definition()->IsConstant()) return false; | 832 if (!index->definition()->IsConstant()) return false; |
| 811 const Object& constant = index->definition()->AsConstant()->value(); | 833 const Object& constant = index->definition()->AsConstant()->value(); |
| 812 if (!constant.IsSmi()) return false; | 834 if (!constant.IsSmi()) return false; |
| 813 const Smi& smi_const = Smi::Cast(constant); | 835 const Smi& smi_const = Smi::Cast(constant); |
| 814 const intptr_t scale = Instance::ElementSizeFor(cid); | 836 const intptr_t scale = Instance::ElementSizeFor(cid); |
| 815 const intptr_t data_offset = Instance::DataOffsetFor(cid); | 837 const intptr_t data_offset = Instance::DataOffsetFor(cid); |
| 816 const int64_t disp = smi_const.AsInt64Value() * scale + data_offset; | 838 const int64_t disp = smi_const.AsInt64Value() * scale + data_offset; |
| 817 return Utils::IsInt(32, disp); | 839 return Utils::IsInt(32, disp); |
| 818 } | 840 } |
| 819 | 841 |
| 820 | 842 |
| 821 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( | 843 LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary( |
| 822 Zone* zone, bool opt) const { | 844 Zone* zone, |
| 845 bool opt) const { |
| 823 const intptr_t kNumInputs = 1; | 846 const intptr_t kNumInputs = 1; |
| 824 // TODO(fschneider): Allow immediate operands for the char code. | 847 // TODO(fschneider): Allow immediate operands for the char code. |
| 825 return LocationSummary::Make(zone, | 848 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 826 kNumInputs, | |
| 827 Location::RequiresRegister(), | |
| 828 LocationSummary::kNoCall); | 849 LocationSummary::kNoCall); |
| 829 } | 850 } |
| 830 | 851 |
| 831 | 852 |
| 832 void OneByteStringFromCharCodeInstr::EmitNativeCode( | 853 void OneByteStringFromCharCodeInstr::EmitNativeCode( |
| 833 FlowGraphCompiler* compiler) { | 854 FlowGraphCompiler* compiler) { |
| 834 ASSERT(compiler->is_optimizing()); | 855 ASSERT(compiler->is_optimizing()); |
| 835 Register char_code = locs()->in(0).reg(); | 856 Register char_code = locs()->in(0).reg(); |
| 836 Register result = locs()->out(0).reg(); | 857 Register result = locs()->out(0).reg(); |
| 837 | 858 |
| 838 __ movq(result, Address(THR, Thread::predefined_symbols_address_offset())); | 859 __ movq(result, Address(THR, Thread::predefined_symbols_address_offset())); |
| 839 __ movq(result, Address(result, | 860 __ movq(result, Address(result, char_code, |
| 840 char_code, | |
| 841 TIMES_HALF_WORD_SIZE, // Char code is a smi. | 861 TIMES_HALF_WORD_SIZE, // Char code is a smi. |
| 842 Symbols::kNullCharCodeSymbolOffset * kWordSize)); | 862 Symbols::kNullCharCodeSymbolOffset * kWordSize)); |
| 843 } | 863 } |
| 844 | 864 |
| 845 | 865 |
| 846 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 866 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
| 847 bool opt) const { | 867 bool opt) const { |
| 848 const intptr_t kNumInputs = 1; | 868 const intptr_t kNumInputs = 1; |
| 849 return LocationSummary::Make(zone, | 869 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 850 kNumInputs, | |
| 851 Location::RequiresRegister(), | |
| 852 LocationSummary::kNoCall); | 870 LocationSummary::kNoCall); |
| 853 } | 871 } |
| 854 | 872 |
| 855 | 873 |
| 856 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 874 void StringToCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 857 ASSERT(cid_ == kOneByteStringCid); | 875 ASSERT(cid_ == kOneByteStringCid); |
| 858 Register str = locs()->in(0).reg(); | 876 Register str = locs()->in(0).reg(); |
| 859 Register result = locs()->out(0).reg(); | 877 Register result = locs()->out(0).reg(); |
| 860 Label is_one, done; | 878 Label is_one, done; |
| 861 __ movq(result, FieldAddress(str, String::length_offset())); | 879 __ movq(result, FieldAddress(str, String::length_offset())); |
| 862 __ cmpq(result, Immediate(Smi::RawValue(1))); | 880 __ cmpq(result, Immediate(Smi::RawValue(1))); |
| 863 __ j(EQUAL, &is_one, Assembler::kNearJump); | 881 __ j(EQUAL, &is_one, Assembler::kNearJump); |
| 864 __ movq(result, Immediate(Smi::RawValue(-1))); | 882 __ movq(result, Immediate(Smi::RawValue(-1))); |
| 865 __ jmp(&done); | 883 __ jmp(&done); |
| 866 __ Bind(&is_one); | 884 __ Bind(&is_one); |
| 867 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); | 885 __ movzxb(result, FieldAddress(str, OneByteString::data_offset())); |
| 868 __ SmiTag(result); | 886 __ SmiTag(result); |
| 869 __ Bind(&done); | 887 __ Bind(&done); |
| 870 } | 888 } |
| 871 | 889 |
| 872 | 890 |
| 873 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, | 891 LocationSummary* StringInterpolateInstr::MakeLocationSummary(Zone* zone, |
| 874 bool opt) const { | 892 bool opt) const { |
| 875 const intptr_t kNumInputs = 1; | 893 const intptr_t kNumInputs = 1; |
| 876 const intptr_t kNumTemps = 0; | 894 const intptr_t kNumTemps = 0; |
| 877 LocationSummary* summary = new(zone) LocationSummary( | 895 LocationSummary* summary = new (zone) |
| 878 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 896 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 879 summary->set_in(0, Location::RegisterLocation(RAX)); | 897 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 880 summary->set_out(0, Location::RegisterLocation(RAX)); | 898 summary->set_out(0, Location::RegisterLocation(RAX)); |
| 881 return summary; | 899 return summary; |
| 882 } | 900 } |
| 883 | 901 |
| 884 | 902 |
| 885 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 903 void StringInterpolateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 886 Register array = locs()->in(0).reg(); | 904 Register array = locs()->in(0).reg(); |
| 887 __ pushq(array); | 905 __ pushq(array); |
| 888 const int kNumberOfArguments = 1; | 906 const int kNumberOfArguments = 1; |
| 889 const Array& kNoArgumentNames = Object::null_array(); | 907 const Array& kNoArgumentNames = Object::null_array(); |
| 890 compiler->GenerateStaticCall(deopt_id(), | 908 compiler->GenerateStaticCall(deopt_id(), token_pos(), CallFunction(), |
| 891 token_pos(), | 909 kNumberOfArguments, kNoArgumentNames, locs(), |
| 892 CallFunction(), | |
| 893 kNumberOfArguments, | |
| 894 kNoArgumentNames, | |
| 895 locs(), | |
| 896 ICData::Handle()); | 910 ICData::Handle()); |
| 897 ASSERT(locs()->out(0).reg() == RAX); | 911 ASSERT(locs()->out(0).reg() == RAX); |
| 898 } | 912 } |
| 899 | 913 |
| 900 | 914 |
| 901 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, | 915 LocationSummary* LoadUntaggedInstr::MakeLocationSummary(Zone* zone, |
| 902 bool opt) const { | 916 bool opt) const { |
| 903 const intptr_t kNumInputs = 1; | 917 const intptr_t kNumInputs = 1; |
| 904 return LocationSummary::Make(zone, | 918 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 905 kNumInputs, | |
| 906 Location::RequiresRegister(), | |
| 907 LocationSummary::kNoCall); | 919 LocationSummary::kNoCall); |
| 908 } | 920 } |
| 909 | 921 |
| 910 | 922 |
| 911 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 923 void LoadUntaggedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 912 Register obj = locs()->in(0).reg(); | 924 Register obj = locs()->in(0).reg(); |
| 913 Register result = locs()->out(0).reg(); | 925 Register result = locs()->out(0).reg(); |
| 914 if (object()->definition()->representation() == kUntagged) { | 926 if (object()->definition()->representation() == kUntagged) { |
| 915 __ movq(result, Address(obj, offset())); | 927 __ movq(result, Address(obj, offset())); |
| 916 } else { | 928 } else { |
| 917 ASSERT(object()->definition()->representation() == kTagged); | 929 ASSERT(object()->definition()->representation() == kTagged); |
| 918 __ movq(result, FieldAddress(obj, offset())); | 930 __ movq(result, FieldAddress(obj, offset())); |
| 919 } | 931 } |
| 920 } | 932 } |
| 921 | 933 |
| 922 | 934 |
| 923 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, | 935 LocationSummary* LoadClassIdInstr::MakeLocationSummary(Zone* zone, |
| 924 bool opt) const { | 936 bool opt) const { |
| 925 const intptr_t kNumInputs = 1; | 937 const intptr_t kNumInputs = 1; |
| 926 return LocationSummary::Make(zone, | 938 return LocationSummary::Make(zone, kNumInputs, Location::RequiresRegister(), |
| 927 kNumInputs, | |
| 928 Location::RequiresRegister(), | |
| 929 LocationSummary::kNoCall); | 939 LocationSummary::kNoCall); |
| 930 } | 940 } |
| 931 | 941 |
| 932 | 942 |
| 933 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 943 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 934 const Register object = locs()->in(0).reg(); | 944 const Register object = locs()->in(0).reg(); |
| 935 const Register result = locs()->out(0).reg(); | 945 const Register result = locs()->out(0).reg(); |
| 936 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); | 946 const AbstractType& value_type = *this->object()->Type()->ToAbstractType(); |
| 937 if (CompileType::Smi().IsAssignableTo(value_type) || | 947 if (CompileType::Smi().IsAssignableTo(value_type) || |
| 938 value_type.IsTypeParameter()) { | 948 value_type.IsTypeParameter()) { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 UNIMPLEMENTED(); | 1041 UNIMPLEMENTED(); |
| 1032 return kTagged; | 1042 return kTagged; |
| 1033 } | 1043 } |
| 1034 } | 1044 } |
| 1035 | 1045 |
| 1036 | 1046 |
| 1037 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, | 1047 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1038 bool opt) const { | 1048 bool opt) const { |
| 1039 const intptr_t kNumInputs = 2; | 1049 const intptr_t kNumInputs = 2; |
| 1040 const intptr_t kNumTemps = 0; | 1050 const intptr_t kNumTemps = 0; |
| 1041 LocationSummary* locs = new(zone) LocationSummary( | 1051 LocationSummary* locs = new (zone) |
| 1042 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1052 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1043 locs->set_in(0, Location::RequiresRegister()); | 1053 locs->set_in(0, Location::RequiresRegister()); |
| 1044 // The smi index is either untagged (element size == 1), or it is left smi | 1054 // The smi index is either untagged (element size == 1), or it is left smi |
| 1045 // tagged (for all element sizes > 1). | 1055 // tagged (for all element sizes > 1). |
| 1046 if (index_scale() == 1) { | 1056 if (index_scale() == 1) { |
| 1047 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1057 locs->set_in(1, |
| 1048 ? Location::Constant(index()->definition()->AsConstant()) | 1058 CanBeImmediateIndex(index(), class_id()) |
| 1049 : Location::WritableRegister()); | 1059 ? Location::Constant(index()->definition()->AsConstant()) |
| 1060 : Location::WritableRegister()); |
| 1050 } else { | 1061 } else { |
| 1051 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1062 locs->set_in(1, |
| 1052 ? Location::Constant(index()->definition()->AsConstant()) | 1063 CanBeImmediateIndex(index(), class_id()) |
| 1053 : Location::RequiresRegister()); | 1064 ? Location::Constant(index()->definition()->AsConstant()) |
| 1065 : Location::RequiresRegister()); |
| 1054 } | 1066 } |
| 1055 if ((representation() == kUnboxedDouble) || | 1067 if ((representation() == kUnboxedDouble) || |
| 1056 (representation() == kUnboxedFloat32x4) || | 1068 (representation() == kUnboxedFloat32x4) || |
| 1057 (representation() == kUnboxedInt32x4) || | 1069 (representation() == kUnboxedInt32x4) || |
| 1058 (representation() == kUnboxedFloat64x2)) { | 1070 (representation() == kUnboxedFloat64x2)) { |
| 1059 locs->set_out(0, Location::RequiresFpuRegister()); | 1071 locs->set_out(0, Location::RequiresFpuRegister()); |
| 1060 } else { | 1072 } else { |
| 1061 locs->set_out(0, Location::RequiresRegister()); | 1073 locs->set_out(0, Location::RequiresRegister()); |
| 1062 } | 1074 } |
| 1063 return locs; | 1075 return locs; |
| 1064 } | 1076 } |
| 1065 | 1077 |
| 1066 | 1078 |
| 1067 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1079 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1068 // The array register points to the backing store for external arrays. | 1080 // The array register points to the backing store for external arrays. |
| 1069 const Register array = locs()->in(0).reg(); | 1081 const Register array = locs()->in(0).reg(); |
| 1070 const Location index = locs()->in(1); | 1082 const Location index = locs()->in(1); |
| 1071 | 1083 |
| 1072 Address element_address = index.IsRegister() | 1084 Address element_address = |
| 1073 ? Assembler::ElementAddressForRegIndex( | 1085 index.IsRegister() |
| 1074 IsExternal(), class_id(), index_scale(), array, index.reg()) | 1086 ? Assembler::ElementAddressForRegIndex( |
| 1075 : Assembler::ElementAddressForIntIndex( | 1087 IsExternal(), class_id(), index_scale(), array, index.reg()) |
| 1076 IsExternal(), class_id(), index_scale(), | 1088 : Assembler::ElementAddressForIntIndex( |
| 1077 array, Smi::Cast(index.constant()).Value()); | 1089 IsExternal(), class_id(), index_scale(), array, |
| 1090 Smi::Cast(index.constant()).Value()); |
| 1078 | 1091 |
| 1079 if ((representation() == kUnboxedDouble) || | 1092 if ((representation() == kUnboxedDouble) || |
| 1080 (representation() == kUnboxedFloat32x4) || | 1093 (representation() == kUnboxedFloat32x4) || |
| 1081 (representation() == kUnboxedInt32x4) || | 1094 (representation() == kUnboxedInt32x4) || |
| 1082 (representation() == kUnboxedFloat64x2)) { | 1095 (representation() == kUnboxedFloat64x2)) { |
| 1083 if ((index_scale() == 1) && index.IsRegister()) { | 1096 if ((index_scale() == 1) && index.IsRegister()) { |
| 1084 __ SmiUntag(index.reg()); | 1097 __ SmiUntag(index.reg()); |
| 1085 } | 1098 } |
| 1086 | 1099 |
| 1087 XmmRegister result = locs()->out(0).fpu_reg(); | 1100 XmmRegister result = locs()->out(0).fpu_reg(); |
| 1088 if (class_id() == kTypedDataFloat32ArrayCid) { | 1101 if (class_id() == kTypedDataFloat32ArrayCid) { |
| 1089 // Load single precision float. | 1102 // Load single precision float. |
| 1090 __ movss(result, element_address); | 1103 __ movss(result, element_address); |
| 1091 } else if (class_id() == kTypedDataFloat64ArrayCid) { | 1104 } else if (class_id() == kTypedDataFloat64ArrayCid) { |
| 1092 __ movsd(result, element_address); | 1105 __ movsd(result, element_address); |
| 1093 } else { | 1106 } else { |
| 1094 ASSERT((class_id() == kTypedDataInt32x4ArrayCid) || | 1107 ASSERT((class_id() == kTypedDataInt32x4ArrayCid) || |
| 1095 (class_id() == kTypedDataFloat32x4ArrayCid) || | 1108 (class_id() == kTypedDataFloat32x4ArrayCid) || |
| 1096 (class_id() == kTypedDataFloat64x2ArrayCid)); | 1109 (class_id() == kTypedDataFloat64x2ArrayCid)); |
| 1097 __ movups(result, element_address); | 1110 __ movups(result, element_address); |
| 1098 } | 1111 } |
| 1099 return; | 1112 return; |
| 1100 } | 1113 } |
| 1101 | 1114 |
| 1102 if ((representation() == kUnboxedUint32) || | 1115 if ((representation() == kUnboxedUint32) || |
| 1103 (representation() == kUnboxedInt32)) { | 1116 (representation() == kUnboxedInt32)) { |
| 1104 if ((index_scale() == 1) && index.IsRegister()) { | 1117 if ((index_scale() == 1) && index.IsRegister()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1116 break; | 1129 break; |
| 1117 default: | 1130 default: |
| 1118 UNREACHABLE(); | 1131 UNREACHABLE(); |
| 1119 } | 1132 } |
| 1120 return; | 1133 return; |
| 1121 } | 1134 } |
| 1122 | 1135 |
| 1123 if (representation() == kUnboxedMint) { | 1136 if (representation() == kUnboxedMint) { |
| 1124 ASSERT(class_id() == kTypedDataInt64ArrayCid); | 1137 ASSERT(class_id() == kTypedDataInt64ArrayCid); |
| 1125 if ((index_scale() == 1) && index.IsRegister()) { | 1138 if ((index_scale() == 1) && index.IsRegister()) { |
| 1126 __ SmiUntag(index.reg()); | 1139 __ SmiUntag(index.reg()); |
| 1127 } | 1140 } |
| 1128 Register result = locs()->out(0).reg(); | 1141 Register result = locs()->out(0).reg(); |
| 1129 __ movq(result, element_address); | 1142 __ movq(result, element_address); |
| 1130 return; | 1143 return; |
| 1131 } | 1144 } |
| 1132 | 1145 |
| 1133 ASSERT(representation() == kTagged); | 1146 ASSERT(representation() == kTagged); |
| 1134 | 1147 |
| 1135 if ((index_scale() == 1) && index.IsRegister()) { | 1148 if ((index_scale() == 1) && index.IsRegister()) { |
| 1136 __ SmiUntag(index.reg()); | 1149 __ SmiUntag(index.reg()); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1165 __ movq(result, element_address); | 1178 __ movq(result, element_address); |
| 1166 break; | 1179 break; |
| 1167 } | 1180 } |
| 1168 } | 1181 } |
| 1169 | 1182 |
| 1170 | 1183 |
| 1171 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, | 1184 LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone, |
| 1172 bool opt) const { | 1185 bool opt) const { |
| 1173 const intptr_t kNumInputs = 2; | 1186 const intptr_t kNumInputs = 2; |
| 1174 const intptr_t kNumTemps = 0; | 1187 const intptr_t kNumTemps = 0; |
| 1175 LocationSummary* summary = new(zone) LocationSummary( | 1188 LocationSummary* summary = new (zone) |
| 1176 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1189 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1177 summary->set_in(0, Location::RequiresRegister()); | 1190 summary->set_in(0, Location::RequiresRegister()); |
| 1178 // 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 |
| 1179 // tagged (for all element sizes > 1). | 1192 // tagged (for all element sizes > 1). |
| 1180 summary->set_in(1, index_scale() == 1 ? Location::WritableRegister() | 1193 summary->set_in(1, index_scale() == 1 ? Location::WritableRegister() |
| 1181 : Location::RequiresRegister()); | 1194 : Location::RequiresRegister()); |
| 1182 summary->set_out(0, Location::RequiresRegister()); | 1195 summary->set_out(0, Location::RequiresRegister()); |
| 1183 return summary; | 1196 return summary; |
| 1184 } | 1197 } |
| 1185 | 1198 |
| 1186 | 1199 |
| 1187 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1200 void LoadCodeUnitsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1188 // The string register points to the backing store for external strings. | 1201 // The string register points to the backing store for external strings. |
| 1189 const Register str = locs()->in(0).reg(); | 1202 const Register str = locs()->in(0).reg(); |
| 1190 const Location index = locs()->in(1); | 1203 const Location index = locs()->in(1); |
| 1191 | 1204 |
| 1192 Address element_address = Assembler::ElementAddressForRegIndex( | 1205 Address element_address = Assembler::ElementAddressForRegIndex( |
| 1193 IsExternal(), class_id(), index_scale(), str, index.reg()); | 1206 IsExternal(), class_id(), index_scale(), str, index.reg()); |
| 1194 | 1207 |
| 1195 if ((index_scale() == 1)) { | 1208 if ((index_scale() == 1)) { |
| 1196 __ SmiUntag(index.reg()); | 1209 __ SmiUntag(index.reg()); |
| 1197 } | 1210 } |
| 1198 Register result = locs()->out(0).reg(); | 1211 Register result = locs()->out(0).reg(); |
| 1199 switch (class_id()) { | 1212 switch (class_id()) { |
| 1200 case kOneByteStringCid: | 1213 case kOneByteStringCid: |
| 1201 case kExternalOneByteStringCid: | 1214 case kExternalOneByteStringCid: |
| 1202 switch (element_count()) { | 1215 switch (element_count()) { |
| 1203 case 1: __ movzxb(result, element_address); break; | 1216 case 1: |
| 1204 case 2: __ movzxw(result, element_address); break; | 1217 __ movzxb(result, element_address); |
| 1205 case 4: __ movl(result, element_address); break; | 1218 break; |
| 1206 default: UNREACHABLE(); | 1219 case 2: |
| 1220 __ movzxw(result, element_address); |
| 1221 break; |
| 1222 case 4: |
| 1223 __ movl(result, element_address); |
| 1224 break; |
| 1225 default: |
| 1226 UNREACHABLE(); |
| 1207 } | 1227 } |
| 1208 __ SmiTag(result); | 1228 __ SmiTag(result); |
| 1209 break; | 1229 break; |
| 1210 case kTwoByteStringCid: | 1230 case kTwoByteStringCid: |
| 1211 case kExternalTwoByteStringCid: | 1231 case kExternalTwoByteStringCid: |
| 1212 switch (element_count()) { | 1232 switch (element_count()) { |
| 1213 case 1: __ movzxw(result, element_address); break; | 1233 case 1: |
| 1214 case 2: __ movl(result, element_address); break; | 1234 __ movzxw(result, element_address); |
| 1215 default: UNREACHABLE(); | 1235 break; |
| 1236 case 2: |
| 1237 __ movl(result, element_address); |
| 1238 break; |
| 1239 default: |
| 1240 UNREACHABLE(); |
| 1216 } | 1241 } |
| 1217 __ SmiTag(result); | 1242 __ SmiTag(result); |
| 1218 break; | 1243 break; |
| 1219 default: | 1244 default: |
| 1220 UNREACHABLE(); | 1245 UNREACHABLE(); |
| 1221 break; | 1246 break; |
| 1222 } | 1247 } |
| 1223 } | 1248 } |
| 1224 | 1249 |
| 1225 | 1250 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1258 UNIMPLEMENTED(); | 1283 UNIMPLEMENTED(); |
| 1259 return kTagged; | 1284 return kTagged; |
| 1260 } | 1285 } |
| 1261 } | 1286 } |
| 1262 | 1287 |
| 1263 | 1288 |
| 1264 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, | 1289 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
| 1265 bool opt) const { | 1290 bool opt) const { |
| 1266 const intptr_t kNumInputs = 3; | 1291 const intptr_t kNumInputs = 3; |
| 1267 const intptr_t kNumTemps = 0; | 1292 const intptr_t kNumTemps = 0; |
| 1268 LocationSummary* locs = new(zone) LocationSummary( | 1293 LocationSummary* locs = new (zone) |
| 1269 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1294 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1270 locs->set_in(0, Location::RequiresRegister()); | 1295 locs->set_in(0, Location::RequiresRegister()); |
| 1271 // The smi index is either untagged (element size == 1), or it is left smi | 1296 // The smi index is either untagged (element size == 1), or it is left smi |
| 1272 // tagged (for all element sizes > 1). | 1297 // tagged (for all element sizes > 1). |
| 1273 if (index_scale() == 1) { | 1298 if (index_scale() == 1) { |
| 1274 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1299 locs->set_in(1, |
| 1275 ? Location::Constant(index()->definition()->AsConstant()) | 1300 CanBeImmediateIndex(index(), class_id()) |
| 1276 : Location::WritableRegister()); | 1301 ? Location::Constant(index()->definition()->AsConstant()) |
| 1302 : Location::WritableRegister()); |
| 1277 } else { | 1303 } else { |
| 1278 locs->set_in(1, CanBeImmediateIndex(index(), class_id()) | 1304 locs->set_in(1, |
| 1279 ? Location::Constant(index()->definition()->AsConstant()) | 1305 CanBeImmediateIndex(index(), class_id()) |
| 1280 : Location::RequiresRegister()); | 1306 ? Location::Constant(index()->definition()->AsConstant()) |
| 1307 : Location::RequiresRegister()); |
| 1281 } | 1308 } |
| 1282 switch (class_id()) { | 1309 switch (class_id()) { |
| 1283 case kArrayCid: | 1310 case kArrayCid: |
| 1284 locs->set_in(2, ShouldEmitStoreBarrier() | 1311 locs->set_in(2, ShouldEmitStoreBarrier() |
| 1285 ? Location::WritableRegister() | 1312 ? Location::WritableRegister() |
| 1286 : Location::RegisterOrConstant(value())); | 1313 : Location::RegisterOrConstant(value())); |
| 1287 break; | 1314 break; |
| 1288 case kExternalTypedDataUint8ArrayCid: | 1315 case kExternalTypedDataUint8ArrayCid: |
| 1289 case kExternalTypedDataUint8ClampedArrayCid: | 1316 case kExternalTypedDataUint8ClampedArrayCid: |
| 1290 case kTypedDataInt8ArrayCid: | 1317 case kTypedDataInt8ArrayCid: |
| 1291 case kTypedDataUint8ArrayCid: | 1318 case kTypedDataUint8ArrayCid: |
| 1292 case kTypedDataUint8ClampedArrayCid: | 1319 case kTypedDataUint8ClampedArrayCid: |
| 1293 case kOneByteStringCid: | 1320 case kOneByteStringCid: |
| 1294 // TODO(fschneider): Add location constraint for byte registers (RAX, | 1321 // TODO(fschneider): Add location constraint for byte registers (RAX, |
| 1295 // RBX, RCX, RDX) instead of using a fixed register. | 1322 // RBX, RCX, RDX) instead of using a fixed register. |
| 1296 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); | 1323 locs->set_in(2, Location::FixedRegisterOrSmiConstant(value(), RAX)); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1321 } | 1348 } |
| 1322 return locs; | 1349 return locs; |
| 1323 } | 1350 } |
| 1324 | 1351 |
| 1325 | 1352 |
| 1326 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1353 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1327 // The array register points to the backing store for external arrays. | 1354 // The array register points to the backing store for external arrays. |
| 1328 const Register array = locs()->in(0).reg(); | 1355 const Register array = locs()->in(0).reg(); |
| 1329 const Location index = locs()->in(1); | 1356 const Location index = locs()->in(1); |
| 1330 | 1357 |
| 1331 Address element_address = index.IsRegister() | 1358 Address element_address = |
| 1332 ? Assembler::ElementAddressForRegIndex( | 1359 index.IsRegister() |
| 1333 IsExternal(), class_id(), index_scale(), array, index.reg()) | 1360 ? Assembler::ElementAddressForRegIndex( |
| 1334 : Assembler::ElementAddressForIntIndex( | 1361 IsExternal(), class_id(), index_scale(), array, index.reg()) |
| 1335 IsExternal(), class_id(), index_scale(), | 1362 : Assembler::ElementAddressForIntIndex( |
| 1336 array, Smi::Cast(index.constant()).Value()); | 1363 IsExternal(), class_id(), index_scale(), array, |
| 1364 Smi::Cast(index.constant()).Value()); |
| 1337 | 1365 |
| 1338 if ((index_scale() == 1) && index.IsRegister()) { | 1366 if ((index_scale() == 1) && index.IsRegister()) { |
| 1339 __ SmiUntag(index.reg()); | 1367 __ SmiUntag(index.reg()); |
| 1340 } | 1368 } |
| 1341 switch (class_id()) { | 1369 switch (class_id()) { |
| 1342 case kArrayCid: | 1370 case kArrayCid: |
| 1343 if (ShouldEmitStoreBarrier()) { | 1371 if (ShouldEmitStoreBarrier()) { |
| 1344 Register value = locs()->in(2).reg(); | 1372 Register value = locs()->in(2).reg(); |
| 1345 __ StoreIntoObject(array, element_address, value); | 1373 __ StoreIntoObject(array, element_address, value); |
| 1346 } else if (locs()->in(2).IsConstant()) { | 1374 } else if (locs()->in(2).IsConstant()) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1369 case kExternalTypedDataUint8ClampedArrayCid: { | 1397 case kExternalTypedDataUint8ClampedArrayCid: { |
| 1370 if (locs()->in(2).IsConstant()) { | 1398 if (locs()->in(2).IsConstant()) { |
| 1371 const Smi& constant = Smi::Cast(locs()->in(2).constant()); | 1399 const Smi& constant = Smi::Cast(locs()->in(2).constant()); |
| 1372 intptr_t value = constant.Value(); | 1400 intptr_t value = constant.Value(); |
| 1373 // Clamp to 0x0 or 0xFF respectively. | 1401 // Clamp to 0x0 or 0xFF respectively. |
| 1374 if (value > 0xFF) { | 1402 if (value > 0xFF) { |
| 1375 value = 0xFF; | 1403 value = 0xFF; |
| 1376 } else if (value < 0) { | 1404 } else if (value < 0) { |
| 1377 value = 0; | 1405 value = 0; |
| 1378 } | 1406 } |
| 1379 __ movb(element_address, | 1407 __ movb(element_address, Immediate(static_cast<int8_t>(value))); |
| 1380 Immediate(static_cast<int8_t>(value))); | |
| 1381 } else { | 1408 } else { |
| 1382 ASSERT(locs()->in(2).reg() == RAX); | 1409 ASSERT(locs()->in(2).reg() == RAX); |
| 1383 Label store_value, store_0xff; | 1410 Label store_value, store_0xff; |
| 1384 __ SmiUntag(RAX); | 1411 __ SmiUntag(RAX); |
| 1385 __ CompareImmediate(RAX, Immediate(0xFF)); | 1412 __ CompareImmediate(RAX, Immediate(0xFF)); |
| 1386 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); | 1413 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); |
| 1387 // Clamp to 0x0 or 0xFF respectively. | 1414 // Clamp to 0x0 or 0xFF respectively. |
| 1388 __ j(GREATER, &store_0xff); | 1415 __ j(GREATER, &store_0xff); |
| 1389 __ xorq(RAX, RAX); | 1416 __ xorq(RAX, RAX); |
| 1390 __ jmp(&store_value, Assembler::kNearJump); | 1417 __ jmp(&store_value, Assembler::kNearJump); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1432 | 1459 |
| 1433 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, | 1460 LocationSummary* GuardFieldClassInstr::MakeLocationSummary(Zone* zone, |
| 1434 bool opt) const { | 1461 bool opt) const { |
| 1435 const intptr_t kNumInputs = 1; | 1462 const intptr_t kNumInputs = 1; |
| 1436 | 1463 |
| 1437 const intptr_t value_cid = value()->Type()->ToCid(); | 1464 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1438 const intptr_t field_cid = field().guarded_cid(); | 1465 const intptr_t field_cid = field().guarded_cid(); |
| 1439 | 1466 |
| 1440 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); | 1467 const bool emit_full_guard = !opt || (field_cid == kIllegalCid); |
| 1441 const bool needs_value_cid_temp_reg = | 1468 const bool needs_value_cid_temp_reg = |
| 1442 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); | 1469 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); |
| 1443 const bool needs_field_temp_reg = emit_full_guard; | 1470 const bool needs_field_temp_reg = emit_full_guard; |
| 1444 | 1471 |
| 1445 intptr_t num_temps = 0; | 1472 intptr_t num_temps = 0; |
| 1446 if (needs_value_cid_temp_reg) { | 1473 if (needs_value_cid_temp_reg) { |
| 1447 num_temps++; | 1474 num_temps++; |
| 1448 } | 1475 } |
| 1449 if (needs_field_temp_reg) { | 1476 if (needs_field_temp_reg) { |
| 1450 num_temps++; | 1477 num_temps++; |
| 1451 } | 1478 } |
| 1452 | 1479 |
| 1453 LocationSummary* summary = new(zone) LocationSummary( | 1480 LocationSummary* summary = new (zone) |
| 1454 zone, kNumInputs, num_temps, LocationSummary::kNoCall); | 1481 LocationSummary(zone, kNumInputs, num_temps, LocationSummary::kNoCall); |
| 1455 summary->set_in(0, Location::RequiresRegister()); | 1482 summary->set_in(0, Location::RequiresRegister()); |
| 1456 | 1483 |
| 1457 for (intptr_t i = 0; i < num_temps; i++) { | 1484 for (intptr_t i = 0; i < num_temps; i++) { |
| 1458 summary->set_temp(i, Location::RequiresRegister()); | 1485 summary->set_temp(i, Location::RequiresRegister()); |
| 1459 } | 1486 } |
| 1460 | 1487 |
| 1461 | 1488 |
| 1462 return summary; | 1489 return summary; |
| 1463 } | 1490 } |
| 1464 | 1491 |
| 1465 | 1492 |
| 1466 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1493 void GuardFieldClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1467 ASSERT(sizeof(classid_t) == kInt32Size); | 1494 ASSERT(sizeof(classid_t) == kInt32Size); |
| 1468 const intptr_t value_cid = value()->Type()->ToCid(); | 1495 const intptr_t value_cid = value()->Type()->ToCid(); |
| 1469 const intptr_t field_cid = field().guarded_cid(); | 1496 const intptr_t field_cid = field().guarded_cid(); |
| 1470 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; | 1497 const intptr_t nullability = field().is_nullable() ? kNullCid : kIllegalCid; |
| 1471 | 1498 |
| 1472 if (field_cid == kDynamicCid) { | 1499 if (field_cid == kDynamicCid) { |
| 1473 if (Compiler::IsBackgroundCompilation()) { | 1500 if (Compiler::IsBackgroundCompilation()) { |
| 1474 // Field state changed while compiling. | 1501 // Field state changed while compiling. |
| 1475 Compiler::AbortBackgroundCompilation(deopt_id(), | 1502 Compiler::AbortBackgroundCompilation( |
| 1503 deopt_id(), |
| 1476 "GuardFieldClassInstr: field state changed while compiling"); | 1504 "GuardFieldClassInstr: field state changed while compiling"); |
| 1477 } | 1505 } |
| 1478 ASSERT(!compiler->is_optimizing()); | 1506 ASSERT(!compiler->is_optimizing()); |
| 1479 return; // Nothing to emit. | 1507 return; // Nothing to emit. |
| 1480 } | 1508 } |
| 1481 | 1509 |
| 1482 const bool emit_full_guard = | 1510 const bool emit_full_guard = |
| 1483 !compiler->is_optimizing() || (field_cid == kIllegalCid); | 1511 !compiler->is_optimizing() || (field_cid == kIllegalCid); |
| 1484 | 1512 |
| 1485 const bool needs_value_cid_temp_reg = | 1513 const bool needs_value_cid_temp_reg = |
| 1486 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); | 1514 (value_cid == kDynamicCid) && (emit_full_guard || (field_cid != kSmiCid)); |
| 1487 | 1515 |
| 1488 const bool needs_field_temp_reg = emit_full_guard; | 1516 const bool needs_field_temp_reg = emit_full_guard; |
| 1489 | 1517 |
| 1490 const Register value_reg = locs()->in(0).reg(); | 1518 const Register value_reg = locs()->in(0).reg(); |
| 1491 | 1519 |
| 1492 const Register value_cid_reg = needs_value_cid_temp_reg ? | 1520 const Register value_cid_reg = |
| 1493 locs()->temp(0).reg() : kNoRegister; | 1521 needs_value_cid_temp_reg ? locs()->temp(0).reg() : kNoRegister; |
| 1494 | 1522 |
| 1495 const Register field_reg = needs_field_temp_reg ? | 1523 const Register field_reg = needs_field_temp_reg |
| 1496 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; | 1524 ? locs()->temp(locs()->temp_count() - 1).reg() |
| 1525 : kNoRegister; |
| 1497 | 1526 |
| 1498 Label ok, fail_label; | 1527 Label ok, fail_label; |
| 1499 | 1528 |
| 1500 Label* deopt = compiler->is_optimizing() ? | 1529 Label* deopt = |
| 1501 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1530 compiler->is_optimizing() |
| 1531 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1532 : NULL; |
| 1502 | 1533 |
| 1503 Label* fail = (deopt != NULL) ? deopt : &fail_label; | 1534 Label* fail = (deopt != NULL) ? deopt : &fail_label; |
| 1504 | 1535 |
| 1505 if (emit_full_guard) { | 1536 if (emit_full_guard) { |
| 1506 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1537 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
| 1507 | 1538 |
| 1508 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); | 1539 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); |
| 1509 FieldAddress field_nullability_operand( | 1540 FieldAddress field_nullability_operand(field_reg, |
| 1510 field_reg, Field::is_nullable_offset()); | 1541 Field::is_nullable_offset()); |
| 1511 | 1542 |
| 1512 if (value_cid == kDynamicCid) { | 1543 if (value_cid == kDynamicCid) { |
| 1513 LoadValueCid(compiler, value_cid_reg, value_reg); | 1544 LoadValueCid(compiler, value_cid_reg, value_reg); |
| 1514 | 1545 |
| 1515 __ cmpl(value_cid_reg, field_cid_operand); | 1546 __ cmpl(value_cid_reg, field_cid_operand); |
| 1516 __ j(EQUAL, &ok); | 1547 __ j(EQUAL, &ok); |
| 1517 __ cmpl(value_cid_reg, field_nullability_operand); | 1548 __ cmpl(value_cid_reg, field_nullability_operand); |
| 1518 } else if (value_cid == kNullCid) { | 1549 } else if (value_cid == kNullCid) { |
| 1519 __ cmpl(field_nullability_operand, Immediate(value_cid)); | 1550 __ cmpl(field_nullability_operand, Immediate(value_cid)); |
| 1520 } else { | 1551 } else { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1589 } | 1620 } |
| 1590 __ Bind(&ok); | 1621 __ Bind(&ok); |
| 1591 } | 1622 } |
| 1592 | 1623 |
| 1593 | 1624 |
| 1594 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, | 1625 LocationSummary* GuardFieldLengthInstr::MakeLocationSummary(Zone* zone, |
| 1595 bool opt) const { | 1626 bool opt) const { |
| 1596 const intptr_t kNumInputs = 1; | 1627 const intptr_t kNumInputs = 1; |
| 1597 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1628 if (!opt || (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
| 1598 const intptr_t kNumTemps = 3; | 1629 const intptr_t kNumTemps = 3; |
| 1599 LocationSummary* summary = new(zone) LocationSummary( | 1630 LocationSummary* summary = new (zone) |
| 1600 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1631 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1601 summary->set_in(0, Location::RequiresRegister()); | 1632 summary->set_in(0, Location::RequiresRegister()); |
| 1602 // We need temporaries for field object, length offset and expected length. | 1633 // We need temporaries for field object, length offset and expected length. |
| 1603 summary->set_temp(0, Location::RequiresRegister()); | 1634 summary->set_temp(0, Location::RequiresRegister()); |
| 1604 summary->set_temp(1, Location::RequiresRegister()); | 1635 summary->set_temp(1, Location::RequiresRegister()); |
| 1605 summary->set_temp(2, Location::RequiresRegister()); | 1636 summary->set_temp(2, Location::RequiresRegister()); |
| 1606 return summary; | 1637 return summary; |
| 1607 } else { | 1638 } else { |
| 1608 LocationSummary* summary = new(zone) LocationSummary( | 1639 LocationSummary* summary = new (zone) |
| 1609 zone, kNumInputs, 0, LocationSummary::kNoCall); | 1640 LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 1610 summary->set_in(0, Location::RequiresRegister()); | 1641 summary->set_in(0, Location::RequiresRegister()); |
| 1611 return summary; | 1642 return summary; |
| 1612 } | 1643 } |
| 1613 UNREACHABLE(); | 1644 UNREACHABLE(); |
| 1614 } | 1645 } |
| 1615 | 1646 |
| 1616 | 1647 |
| 1617 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1648 void GuardFieldLengthInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1618 if (field().guarded_list_length() == Field::kNoFixedLength) { | 1649 if (field().guarded_list_length() == Field::kNoFixedLength) { |
| 1619 if (Compiler::IsBackgroundCompilation()) { | 1650 if (Compiler::IsBackgroundCompilation()) { |
| 1620 // Field state changed while compiling. | 1651 // Field state changed while compiling. |
| 1621 Compiler::AbortBackgroundCompilation(deopt_id(), | 1652 Compiler::AbortBackgroundCompilation( |
| 1653 deopt_id(), |
| 1622 "GuardFieldLengthInstr: field state changed while compiling"); | 1654 "GuardFieldLengthInstr: field state changed while compiling"); |
| 1623 } | 1655 } |
| 1624 ASSERT(!compiler->is_optimizing()); | 1656 ASSERT(!compiler->is_optimizing()); |
| 1625 return; // Nothing to emit. | 1657 return; // Nothing to emit. |
| 1626 } | 1658 } |
| 1627 | 1659 |
| 1628 Label* deopt = compiler->is_optimizing() ? | 1660 Label* deopt = |
| 1629 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1661 compiler->is_optimizing() |
| 1662 ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) |
| 1663 : NULL; |
| 1630 | 1664 |
| 1631 const Register value_reg = locs()->in(0).reg(); | 1665 const Register value_reg = locs()->in(0).reg(); |
| 1632 | 1666 |
| 1633 if (!compiler->is_optimizing() || | 1667 if (!compiler->is_optimizing() || |
| 1634 (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1668 (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
| 1635 const Register field_reg = locs()->temp(0).reg(); | 1669 const Register field_reg = locs()->temp(0).reg(); |
| 1636 const Register offset_reg = locs()->temp(1).reg(); | 1670 const Register offset_reg = locs()->temp(1).reg(); |
| 1637 const Register length_reg = locs()->temp(2).reg(); | 1671 const Register length_reg = locs()->temp(2).reg(); |
| 1638 | 1672 |
| 1639 Label ok; | 1673 Label ok; |
| 1640 | 1674 |
| 1641 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); | 1675 __ LoadObject(field_reg, Field::ZoneHandle(field().Original())); |
| 1642 | 1676 |
| 1643 __ movsxb(offset_reg, FieldAddress(field_reg, | 1677 __ movsxb( |
| 1644 Field::guarded_list_length_in_object_offset_offset())); | 1678 offset_reg, |
| 1645 __ movq(length_reg, FieldAddress(field_reg, | 1679 FieldAddress(field_reg, |
| 1646 Field::guarded_list_length_offset())); | 1680 Field::guarded_list_length_in_object_offset_offset())); |
| 1681 __ movq(length_reg, |
| 1682 FieldAddress(field_reg, Field::guarded_list_length_offset())); |
| 1647 | 1683 |
| 1648 __ cmpq(offset_reg, Immediate(0)); | 1684 __ cmpq(offset_reg, Immediate(0)); |
| 1649 __ j(NEGATIVE, &ok); | 1685 __ j(NEGATIVE, &ok); |
| 1650 | 1686 |
| 1651 // Load the length from the value. GuardFieldClass already verified that | 1687 // Load the length from the value. GuardFieldClass already verified that |
| 1652 // value's class matches guarded class id of the field. | 1688 // value's class matches guarded class id of the field. |
| 1653 // offset_reg contains offset already corrected by -kHeapObjectTag that is | 1689 // offset_reg contains offset already corrected by -kHeapObjectTag that is |
| 1654 // why we use Address instead of FieldAddress. | 1690 // why we use Address instead of FieldAddress. |
| 1655 __ cmpq(length_reg, Address(value_reg, offset_reg, TIMES_1, 0)); | 1691 __ cmpq(length_reg, Address(value_reg, offset_reg, TIMES_1, 0)); |
| 1656 | 1692 |
| 1657 if (deopt == NULL) { | 1693 if (deopt == NULL) { |
| 1658 __ j(EQUAL, &ok); | 1694 __ j(EQUAL, &ok); |
| 1659 | 1695 |
| 1660 __ pushq(field_reg); | 1696 __ pushq(field_reg); |
| 1661 __ pushq(value_reg); | 1697 __ pushq(value_reg); |
| 1662 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); | 1698 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); |
| 1663 __ Drop(2); // Drop the field and the value. | 1699 __ Drop(2); // Drop the field and the value. |
| 1664 } else { | 1700 } else { |
| 1665 __ j(NOT_EQUAL, deopt); | 1701 __ j(NOT_EQUAL, deopt); |
| 1666 } | 1702 } |
| 1667 | 1703 |
| 1668 __ Bind(&ok); | 1704 __ Bind(&ok); |
| 1669 } else { | 1705 } else { |
| 1670 ASSERT(compiler->is_optimizing()); | 1706 ASSERT(compiler->is_optimizing()); |
| 1671 ASSERT(field().guarded_list_length() >= 0); | 1707 ASSERT(field().guarded_list_length() >= 0); |
| 1672 ASSERT(field().guarded_list_length_in_object_offset() != | 1708 ASSERT(field().guarded_list_length_in_object_offset() != |
| 1673 Field::kUnknownLengthOffset); | 1709 Field::kUnknownLengthOffset); |
| 1674 | 1710 |
| 1675 __ CompareImmediate( | 1711 __ CompareImmediate( |
| 1676 FieldAddress(value_reg, | 1712 FieldAddress(value_reg, field().guarded_list_length_in_object_offset()), |
| 1677 field().guarded_list_length_in_object_offset()), | 1713 Immediate(Smi::RawValue(field().guarded_list_length()))); |
| 1678 Immediate(Smi::RawValue(field().guarded_list_length()))); | |
| 1679 __ j(NOT_EQUAL, deopt); | 1714 __ j(NOT_EQUAL, deopt); |
| 1680 } | 1715 } |
| 1681 } | 1716 } |
| 1682 | 1717 |
| 1683 | 1718 |
| 1684 class BoxAllocationSlowPath : public SlowPathCode { | 1719 class BoxAllocationSlowPath : public SlowPathCode { |
| 1685 public: | 1720 public: |
| 1686 BoxAllocationSlowPath(Instruction* instruction, | 1721 BoxAllocationSlowPath(Instruction* instruction, |
| 1687 const Class& cls, | 1722 const Class& cls, |
| 1688 Register result) | 1723 Register result) |
| 1689 : instruction_(instruction), | 1724 : instruction_(instruction), cls_(cls), result_(result) {} |
| 1690 cls_(cls), | |
| 1691 result_(result) { } | |
| 1692 | 1725 |
| 1693 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1726 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1694 if (Assembler::EmittingComments()) { | 1727 if (Assembler::EmittingComments()) { |
| 1695 __ Comment("%s slow path allocation of %s", | 1728 __ Comment("%s slow path allocation of %s", instruction_->DebugName(), |
| 1696 instruction_->DebugName(), | |
| 1697 String::Handle(cls_.ScrubbedName()).ToCString()); | 1729 String::Handle(cls_.ScrubbedName()).ToCString()); |
| 1698 } | 1730 } |
| 1699 __ Bind(entry_label()); | 1731 __ Bind(entry_label()); |
| 1700 const Code& stub = Code::ZoneHandle(compiler->zone(), | 1732 const Code& stub = Code::ZoneHandle( |
| 1701 StubCode::GetAllocationStubForClass(cls_)); | 1733 compiler->zone(), StubCode::GetAllocationStubForClass(cls_)); |
| 1702 const StubEntry stub_entry(stub); | 1734 const StubEntry stub_entry(stub); |
| 1703 | 1735 |
| 1704 LocationSummary* locs = instruction_->locs(); | 1736 LocationSummary* locs = instruction_->locs(); |
| 1705 | 1737 |
| 1706 locs->live_registers()->Remove(Location::RegisterLocation(result_)); | 1738 locs->live_registers()->Remove(Location::RegisterLocation(result_)); |
| 1707 | 1739 |
| 1708 compiler->SaveLiveRegisters(locs); | 1740 compiler->SaveLiveRegisters(locs); |
| 1709 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. | 1741 compiler->GenerateCall(TokenPosition::kNoSource, // No token position. |
| 1710 stub_entry, | 1742 stub_entry, RawPcDescriptors::kOther, locs); |
| 1711 RawPcDescriptors::kOther, | |
| 1712 locs); | |
| 1713 compiler->AddStubCallTarget(stub); | 1743 compiler->AddStubCallTarget(stub); |
| 1714 __ MoveRegister(result_, RAX); | 1744 __ MoveRegister(result_, RAX); |
| 1715 compiler->RestoreLiveRegisters(locs); | 1745 compiler->RestoreLiveRegisters(locs); |
| 1716 __ jmp(exit_label()); | 1746 __ jmp(exit_label()); |
| 1717 } | 1747 } |
| 1718 | 1748 |
| 1719 static void Allocate(FlowGraphCompiler* compiler, | 1749 static void Allocate(FlowGraphCompiler* compiler, |
| 1720 Instruction* instruction, | 1750 Instruction* instruction, |
| 1721 const Class& cls, | 1751 const Class& cls, |
| 1722 Register result, | 1752 Register result, |
| 1723 Register temp) { | 1753 Register temp) { |
| 1724 if (compiler->intrinsic_mode()) { | 1754 if (compiler->intrinsic_mode()) { |
| 1725 __ TryAllocate(cls, | 1755 __ TryAllocate(cls, compiler->intrinsic_slow_path_label(), |
| 1726 compiler->intrinsic_slow_path_label(), | 1756 Assembler::kFarJump, result, temp); |
| 1727 Assembler::kFarJump, | |
| 1728 result, | |
| 1729 temp); | |
| 1730 } else { | 1757 } else { |
| 1731 BoxAllocationSlowPath* slow_path = | 1758 BoxAllocationSlowPath* slow_path = |
| 1732 new BoxAllocationSlowPath(instruction, cls, result); | 1759 new BoxAllocationSlowPath(instruction, cls, result); |
| 1733 compiler->AddSlowPathCode(slow_path); | 1760 compiler->AddSlowPathCode(slow_path); |
| 1734 | 1761 |
| 1735 __ TryAllocate(cls, | 1762 __ TryAllocate(cls, slow_path->entry_label(), Assembler::kFarJump, result, |
| 1736 slow_path->entry_label(), | |
| 1737 Assembler::kFarJump, | |
| 1738 result, | |
| 1739 temp); | 1763 temp); |
| 1740 __ Bind(slow_path->exit_label()); | 1764 __ Bind(slow_path->exit_label()); |
| 1741 } | 1765 } |
| 1742 } | 1766 } |
| 1743 | 1767 |
| 1744 private: | 1768 private: |
| 1745 Instruction* instruction_; | 1769 Instruction* instruction_; |
| 1746 const Class& cls_; | 1770 const Class& cls_; |
| 1747 const Register result_; | 1771 const Register result_; |
| 1748 }; | 1772 }; |
| 1749 | 1773 |
| 1750 | 1774 |
| 1751 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, | 1775 LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone, |
| 1752 bool opt) const { | 1776 bool opt) const { |
| 1753 const intptr_t kNumInputs = 2; | 1777 const intptr_t kNumInputs = 2; |
| 1754 const intptr_t kNumTemps = | 1778 const intptr_t kNumTemps = |
| 1755 (IsUnboxedStore() && opt) ? 2 : | 1779 (IsUnboxedStore() && opt) ? 2 : ((IsPotentialUnboxedStore()) ? 3 : 0); |
| 1756 ((IsPotentialUnboxedStore()) ? 3 : 0); | 1780 LocationSummary* summary = new (zone) |
| 1757 LocationSummary* summary = new(zone) LocationSummary( | 1781 LocationSummary(zone, kNumInputs, kNumTemps, |
| 1758 zone, kNumInputs, kNumTemps, | 1782 ((IsUnboxedStore() && opt && is_initialization()) || |
| 1759 ((IsUnboxedStore() && opt && is_initialization()) || | 1783 IsPotentialUnboxedStore()) |
| 1760 IsPotentialUnboxedStore()) | 1784 ? LocationSummary::kCallOnSlowPath |
| 1761 ? LocationSummary::kCallOnSlowPath | 1785 : LocationSummary::kNoCall); |
| 1762 : LocationSummary::kNoCall); | |
| 1763 | 1786 |
| 1764 summary->set_in(0, Location::RequiresRegister()); | 1787 summary->set_in(0, Location::RequiresRegister()); |
| 1765 if (IsUnboxedStore() && opt) { | 1788 if (IsUnboxedStore() && opt) { |
| 1766 summary->set_in(1, Location::RequiresFpuRegister()); | 1789 summary->set_in(1, Location::RequiresFpuRegister()); |
| 1767 summary->set_temp(0, Location::RequiresRegister()); | 1790 summary->set_temp(0, Location::RequiresRegister()); |
| 1768 summary->set_temp(1, Location::RequiresRegister()); | 1791 summary->set_temp(1, Location::RequiresRegister()); |
| 1769 } else if (IsPotentialUnboxedStore()) { | 1792 } else if (IsPotentialUnboxedStore()) { |
| 1770 summary->set_in(1, ShouldEmitStoreBarrier() | 1793 summary->set_in(1, ShouldEmitStoreBarrier() ? Location::WritableRegister() |
| 1771 ? Location::WritableRegister() | 1794 : Location::RequiresRegister()); |
| 1772 : Location::RequiresRegister()); | |
| 1773 summary->set_temp(0, Location::RequiresRegister()); | 1795 summary->set_temp(0, Location::RequiresRegister()); |
| 1774 summary->set_temp(1, Location::RequiresRegister()); | 1796 summary->set_temp(1, Location::RequiresRegister()); |
| 1775 summary->set_temp(2, opt ? Location::RequiresFpuRegister() | 1797 summary->set_temp(2, opt ? Location::RequiresFpuRegister() |
| 1776 : Location::FpuRegisterLocation(XMM1)); | 1798 : Location::FpuRegisterLocation(XMM1)); |
| 1777 } else { | 1799 } else { |
| 1778 summary->set_in(1, ShouldEmitStoreBarrier() | 1800 summary->set_in(1, ShouldEmitStoreBarrier() |
| 1779 ? Location::WritableRegister() | 1801 ? Location::WritableRegister() |
| 1780 : Location::RegisterOrConstant(value())); | 1802 : Location::RegisterOrConstant(value())); |
| 1781 } | 1803 } |
| 1782 return summary; | 1804 return summary; |
| 1783 } | 1805 } |
| 1784 | 1806 |
| 1785 | 1807 |
| 1786 static void EnsureMutableBox(FlowGraphCompiler* compiler, | 1808 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
| 1787 StoreInstanceFieldInstr* instruction, | 1809 StoreInstanceFieldInstr* instruction, |
| 1788 Register box_reg, | 1810 Register box_reg, |
| 1789 const Class& cls, | 1811 const Class& cls, |
| 1790 Register instance_reg, | 1812 Register instance_reg, |
| 1791 intptr_t offset, | 1813 intptr_t offset, |
| 1792 Register temp) { | 1814 Register temp) { |
| 1793 Label done; | 1815 Label done; |
| 1794 __ movq(box_reg, FieldAddress(instance_reg, offset)); | 1816 __ movq(box_reg, FieldAddress(instance_reg, offset)); |
| 1795 __ CompareObject(box_reg, Object::null_object()); | 1817 __ CompareObject(box_reg, Object::null_object()); |
| 1796 __ j(NOT_EQUAL, &done); | 1818 __ j(NOT_EQUAL, &done); |
| 1797 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); | 1819 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg, temp); |
| 1798 __ movq(temp, box_reg); | 1820 __ movq(temp, box_reg); |
| 1799 __ StoreIntoObject(instance_reg, | 1821 __ StoreIntoObject(instance_reg, FieldAddress(instance_reg, offset), temp); |
| 1800 FieldAddress(instance_reg, offset), | |
| 1801 temp); | |
| 1802 | 1822 |
| 1803 __ Bind(&done); | 1823 __ Bind(&done); |
| 1804 } | 1824 } |
| 1805 | 1825 |
| 1806 | 1826 |
| 1807 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1827 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1808 ASSERT(sizeof(classid_t) == kInt32Size); | 1828 ASSERT(sizeof(classid_t) == kInt32Size); |
| 1809 Label skip_store; | 1829 Label skip_store; |
| 1810 | 1830 |
| 1811 Register instance_reg = locs()->in(0).reg(); | 1831 Register instance_reg = locs()->in(0).reg(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1828 case kFloat64x2Cid: | 1848 case kFloat64x2Cid: |
| 1829 cls = &compiler->float64x2_class(); | 1849 cls = &compiler->float64x2_class(); |
| 1830 break; | 1850 break; |
| 1831 default: | 1851 default: |
| 1832 UNREACHABLE(); | 1852 UNREACHABLE(); |
| 1833 } | 1853 } |
| 1834 | 1854 |
| 1835 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2); | 1855 BoxAllocationSlowPath::Allocate(compiler, this, *cls, temp, temp2); |
| 1836 __ movq(temp2, temp); | 1856 __ movq(temp2, temp); |
| 1837 __ StoreIntoObject(instance_reg, | 1857 __ StoreIntoObject(instance_reg, |
| 1838 FieldAddress(instance_reg, offset_in_bytes_), | 1858 FieldAddress(instance_reg, offset_in_bytes_), temp2); |
| 1839 temp2); | |
| 1840 } else { | 1859 } else { |
| 1841 __ movq(temp, FieldAddress(instance_reg, offset_in_bytes_)); | 1860 __ movq(temp, FieldAddress(instance_reg, offset_in_bytes_)); |
| 1842 } | 1861 } |
| 1843 switch (cid) { | 1862 switch (cid) { |
| 1844 case kDoubleCid: | 1863 case kDoubleCid: |
| 1845 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); | 1864 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); |
| 1846 __ movsd(FieldAddress(temp, Double::value_offset()), value); | 1865 __ movsd(FieldAddress(temp, Double::value_offset()), value); |
| 1847 break; | 1866 break; |
| 1848 case kFloat32x4Cid: | 1867 case kFloat32x4Cid: |
| 1849 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr"); | 1868 __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr"); |
| 1850 __ movups(FieldAddress(temp, Float32x4::value_offset()), value); | 1869 __ movups(FieldAddress(temp, Float32x4::value_offset()), value); |
| 1851 break; | 1870 break; |
| 1852 case kFloat64x2Cid: | 1871 case kFloat64x2Cid: |
| 1853 __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr"); | 1872 __ Comment("UnboxedFloat64x2StoreInstanceFieldInstr"); |
| 1854 __ movups(FieldAddress(temp, Float64x2::value_offset()), value); | 1873 __ movups(FieldAddress(temp, Float64x2::value_offset()), value); |
| 1855 break; | 1874 break; |
| 1856 default: | 1875 default: |
| 1857 UNREACHABLE(); | 1876 UNREACHABLE(); |
| 1858 } | 1877 } |
| 1859 return; | 1878 return; |
| 1860 } | 1879 } |
| 1861 | 1880 |
| 1862 if (IsPotentialUnboxedStore()) { | 1881 if (IsPotentialUnboxedStore()) { |
| 1863 Register value_reg = locs()->in(1).reg(); | 1882 Register value_reg = locs()->in(1).reg(); |
| 1864 Register temp = locs()->temp(0).reg(); | 1883 Register temp = locs()->temp(0).reg(); |
| 1865 Register temp2 = locs()->temp(1).reg(); | 1884 Register temp2 = locs()->temp(1).reg(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1901 // Fall through. | 1920 // Fall through. |
| 1902 __ jmp(&store_pointer); | 1921 __ jmp(&store_pointer); |
| 1903 | 1922 |
| 1904 if (!compiler->is_optimizing()) { | 1923 if (!compiler->is_optimizing()) { |
| 1905 locs()->live_registers()->Add(locs()->in(0)); | 1924 locs()->live_registers()->Add(locs()->in(0)); |
| 1906 locs()->live_registers()->Add(locs()->in(1)); | 1925 locs()->live_registers()->Add(locs()->in(1)); |
| 1907 } | 1926 } |
| 1908 | 1927 |
| 1909 { | 1928 { |
| 1910 __ Bind(&store_double); | 1929 __ Bind(&store_double); |
| 1911 EnsureMutableBox(compiler, | 1930 EnsureMutableBox(compiler, this, temp, compiler->double_class(), |
| 1912 this, | 1931 instance_reg, offset_in_bytes_, temp2); |
| 1913 temp, | |
| 1914 compiler->double_class(), | |
| 1915 instance_reg, | |
| 1916 offset_in_bytes_, | |
| 1917 temp2); | |
| 1918 __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset())); | 1932 __ movsd(fpu_temp, FieldAddress(value_reg, Double::value_offset())); |
| 1919 __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp); | 1933 __ movsd(FieldAddress(temp, Double::value_offset()), fpu_temp); |
| 1920 __ jmp(&skip_store); | 1934 __ jmp(&skip_store); |
| 1921 } | 1935 } |
| 1922 | 1936 |
| 1923 { | 1937 { |
| 1924 __ Bind(&store_float32x4); | 1938 __ Bind(&store_float32x4); |
| 1925 EnsureMutableBox(compiler, | 1939 EnsureMutableBox(compiler, this, temp, compiler->float32x4_class(), |
| 1926 this, | 1940 instance_reg, offset_in_bytes_, temp2); |
| 1927 temp, | |
| 1928 compiler->float32x4_class(), | |
| 1929 instance_reg, | |
| 1930 offset_in_bytes_, | |
| 1931 temp2); | |
| 1932 __ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset())); | 1941 __ movups(fpu_temp, FieldAddress(value_reg, Float32x4::value_offset())); |
| 1933 __ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp); | 1942 __ movups(FieldAddress(temp, Float32x4::value_offset()), fpu_temp); |
| 1934 __ jmp(&skip_store); | 1943 __ jmp(&skip_store); |
| 1935 } | 1944 } |
| 1936 | 1945 |
| 1937 { | 1946 { |
| 1938 __ Bind(&store_float64x2); | 1947 __ Bind(&store_float64x2); |
| 1939 EnsureMutableBox(compiler, | 1948 EnsureMutableBox(compiler, this, temp, compiler->float64x2_class(), |
| 1940 this, | 1949 instance_reg, offset_in_bytes_, temp2); |
| 1941 temp, | |
| 1942 compiler->float64x2_class(), | |
| 1943 instance_reg, | |
| 1944 offset_in_bytes_, | |
| 1945 temp2); | |
| 1946 __ movups(fpu_temp, FieldAddress(value_reg, Float64x2::value_offset())); | 1950 __ movups(fpu_temp, FieldAddress(value_reg, Float64x2::value_offset())); |
| 1947 __ movups(FieldAddress(temp, Float64x2::value_offset()), fpu_temp); | 1951 __ movups(FieldAddress(temp, Float64x2::value_offset()), fpu_temp); |
| 1948 __ jmp(&skip_store); | 1952 __ jmp(&skip_store); |
| 1949 } | 1953 } |
| 1950 | 1954 |
| 1951 __ Bind(&store_pointer); | 1955 __ Bind(&store_pointer); |
| 1952 } | 1956 } |
| 1953 | 1957 |
| 1954 if (ShouldEmitStoreBarrier()) { | 1958 if (ShouldEmitStoreBarrier()) { |
| 1955 Register value_reg = locs()->in(1).reg(); | 1959 Register value_reg = locs()->in(1).reg(); |
| 1956 __ StoreIntoObject(instance_reg, | 1960 __ StoreIntoObject(instance_reg, |
| 1957 FieldAddress(instance_reg, offset_in_bytes_), | 1961 FieldAddress(instance_reg, offset_in_bytes_), value_reg, |
| 1958 value_reg, | |
| 1959 CanValueBeSmi()); | 1962 CanValueBeSmi()); |
| 1960 } else { | 1963 } else { |
| 1961 if (locs()->in(1).IsConstant()) { | 1964 if (locs()->in(1).IsConstant()) { |
| 1962 __ StoreIntoObjectNoBarrier(instance_reg, | 1965 __ StoreIntoObjectNoBarrier(instance_reg, |
| 1963 FieldAddress(instance_reg, offset_in_bytes_), | 1966 FieldAddress(instance_reg, offset_in_bytes_), |
| 1964 locs()->in(1).constant()); | 1967 locs()->in(1).constant()); |
| 1965 } else { | 1968 } else { |
| 1966 Register value_reg = locs()->in(1).reg(); | 1969 Register value_reg = locs()->in(1).reg(); |
| 1967 __ StoreIntoObjectNoBarrier(instance_reg, | 1970 __ StoreIntoObjectNoBarrier(instance_reg, |
| 1968 FieldAddress(instance_reg, offset_in_bytes_), | 1971 FieldAddress(instance_reg, offset_in_bytes_), |
| 1969 value_reg); | 1972 value_reg); |
| 1970 } | 1973 } |
| 1971 } | 1974 } |
| 1972 __ Bind(&skip_store); | 1975 __ Bind(&skip_store); |
| 1973 } | 1976 } |
| 1974 | 1977 |
| 1975 | 1978 |
| 1976 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, | 1979 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 1977 bool opt) const { | 1980 bool opt) const { |
| 1978 const intptr_t kNumInputs = 1; | 1981 const intptr_t kNumInputs = 1; |
| 1979 const intptr_t kNumTemps = 0; | 1982 const intptr_t kNumTemps = 0; |
| 1980 LocationSummary* summary = new(zone) LocationSummary( | 1983 LocationSummary* summary = new (zone) |
| 1981 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1984 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1982 summary->set_in(0, Location::RequiresRegister()); | 1985 summary->set_in(0, Location::RequiresRegister()); |
| 1983 summary->set_out(0, Location::RequiresRegister()); | 1986 summary->set_out(0, Location::RequiresRegister()); |
| 1984 return summary; | 1987 return summary; |
| 1985 } | 1988 } |
| 1986 | 1989 |
| 1987 | 1990 |
| 1988 // When the parser is building an implicit static getter for optimization, | 1991 // When the parser is building an implicit static getter for optimization, |
| 1989 // it can generate a function body where deoptimization ids do not line up | 1992 // it can generate a function body where deoptimization ids do not line up |
| 1990 // with the unoptimized code. | 1993 // with the unoptimized code. |
| 1991 // | 1994 // |
| 1992 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. | 1995 // This is safe only so long as LoadStaticFieldInstr cannot deoptimize. |
| 1993 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1996 void LoadStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1994 Register field = locs()->in(0).reg(); | 1997 Register field = locs()->in(0).reg(); |
| 1995 Register result = locs()->out(0).reg(); | 1998 Register result = locs()->out(0).reg(); |
| 1996 __ movq(result, FieldAddress(field, Field::static_value_offset())); | 1999 __ movq(result, FieldAddress(field, Field::static_value_offset())); |
| 1997 } | 2000 } |
| 1998 | 2001 |
| 1999 | 2002 |
| 2000 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2003 LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2001 bool opt) const { | 2004 bool opt) const { |
| 2002 LocationSummary* locs = new(zone) LocationSummary( | 2005 LocationSummary* locs = |
| 2003 zone, 1, 1, LocationSummary::kNoCall); | 2006 new (zone) LocationSummary(zone, 1, 1, LocationSummary::kNoCall); |
| 2004 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() | 2007 locs->set_in(0, value()->NeedsStoreBuffer() ? Location::WritableRegister() |
| 2005 : Location::RequiresRegister()); | 2008 : Location::RequiresRegister()); |
| 2006 locs->set_temp(0, Location::RequiresRegister()); | 2009 locs->set_temp(0, Location::RequiresRegister()); |
| 2007 return locs; | 2010 return locs; |
| 2008 } | 2011 } |
| 2009 | 2012 |
| 2010 | 2013 |
| 2011 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2014 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2012 Register value = locs()->in(0).reg(); | 2015 Register value = locs()->in(0).reg(); |
| 2013 Register temp = locs()->temp(0).reg(); | 2016 Register temp = locs()->temp(0).reg(); |
| 2014 | 2017 |
| 2015 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); | 2018 __ LoadObject(temp, Field::ZoneHandle(Z, field().Original())); |
| 2016 if (this->value()->NeedsStoreBuffer()) { | 2019 if (this->value()->NeedsStoreBuffer()) { |
| 2017 __ StoreIntoObject(temp, | 2020 __ StoreIntoObject(temp, FieldAddress(temp, Field::static_value_offset()), |
| 2018 FieldAddress(temp, Field::static_value_offset()), | 2021 value, CanValueBeSmi()); |
| 2019 value, | |
| 2020 CanValueBeSmi()); | |
| 2021 } else { | 2022 } else { |
| 2022 __ StoreIntoObjectNoBarrier( | 2023 __ StoreIntoObjectNoBarrier( |
| 2023 temp, FieldAddress(temp, Field::static_value_offset()), value); | 2024 temp, FieldAddress(temp, Field::static_value_offset()), value); |
| 2024 } | 2025 } |
| 2025 } | 2026 } |
| 2026 | 2027 |
| 2027 | 2028 |
| 2028 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, | 2029 LocationSummary* InstanceOfInstr::MakeLocationSummary(Zone* zone, |
| 2029 bool opt) const { | 2030 bool opt) const { |
| 2030 const intptr_t kNumInputs = 2; | 2031 const intptr_t kNumInputs = 2; |
| 2031 const intptr_t kNumTemps = 0; | 2032 const intptr_t kNumTemps = 0; |
| 2032 LocationSummary* summary = new(zone) LocationSummary( | 2033 LocationSummary* summary = new (zone) |
| 2033 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2034 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2034 summary->set_in(0, Location::RegisterLocation(RAX)); | 2035 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 2035 summary->set_in(1, Location::RegisterLocation(RDX)); | 2036 summary->set_in(1, Location::RegisterLocation(RDX)); |
| 2036 summary->set_out(0, Location::RegisterLocation(RAX)); | 2037 summary->set_out(0, Location::RegisterLocation(RAX)); |
| 2037 return summary; | 2038 return summary; |
| 2038 } | 2039 } |
| 2039 | 2040 |
| 2040 | 2041 |
| 2041 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2042 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2042 ASSERT(locs()->in(0).reg() == RAX); // Value. | 2043 ASSERT(locs()->in(0).reg() == RAX); // Value. |
| 2043 ASSERT(locs()->in(1).reg() == RDX); // Instantiator type arguments. | 2044 ASSERT(locs()->in(1).reg() == RDX); // Instantiator type arguments. |
| 2044 | 2045 |
| 2045 compiler->GenerateInstanceOf(token_pos(), | 2046 compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), negate_result(), |
| 2046 deopt_id(), | |
| 2047 type(), | |
| 2048 negate_result(), | |
| 2049 locs()); | 2047 locs()); |
| 2050 ASSERT(locs()->out(0).reg() == RAX); | 2048 ASSERT(locs()->out(0).reg() == RAX); |
| 2051 } | 2049 } |
| 2052 | 2050 |
| 2053 | 2051 |
| 2054 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and | 2052 // TODO(srdjan): In case of constant inputs make CreateArray kNoCall and |
| 2055 // use slow path stub. | 2053 // use slow path stub. |
| 2056 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, | 2054 LocationSummary* CreateArrayInstr::MakeLocationSummary(Zone* zone, |
| 2057 bool opt) const { | 2055 bool opt) const { |
| 2058 const intptr_t kNumInputs = 2; | 2056 const intptr_t kNumInputs = 2; |
| 2059 const intptr_t kNumTemps = 0; | 2057 const intptr_t kNumTemps = 0; |
| 2060 LocationSummary* locs = new(zone) LocationSummary( | 2058 LocationSummary* locs = new (zone) |
| 2061 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2059 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2062 locs->set_in(0, Location::RegisterLocation(RBX)); | 2060 locs->set_in(0, Location::RegisterLocation(RBX)); |
| 2063 locs->set_in(1, Location::RegisterLocation(R10)); | 2061 locs->set_in(1, Location::RegisterLocation(R10)); |
| 2064 locs->set_out(0, Location::RegisterLocation(RAX)); | 2062 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2065 return locs; | 2063 return locs; |
| 2066 } | 2064 } |
| 2067 | 2065 |
| 2068 | 2066 |
| 2069 // Inlines array allocation for known constant values. | 2067 // Inlines array allocation for known constant values. |
| 2070 static void InlineArrayAllocation(FlowGraphCompiler* compiler, | 2068 static void InlineArrayAllocation(FlowGraphCompiler* compiler, |
| 2071 intptr_t num_elements, | 2069 intptr_t num_elements, |
| 2072 Label* slow_path, | 2070 Label* slow_path, |
| 2073 Label* done) { | 2071 Label* done) { |
| 2074 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. | 2072 const int kInlineArraySize = 12; // Same as kInlineInstanceSize. |
| 2075 const Register kLengthReg = R10; | 2073 const Register kLengthReg = R10; |
| 2076 const Register kElemTypeReg = RBX; | 2074 const Register kElemTypeReg = RBX; |
| 2077 const intptr_t instance_size = Array::InstanceSize(num_elements); | 2075 const intptr_t instance_size = Array::InstanceSize(num_elements); |
| 2078 | 2076 |
| 2079 __ TryAllocateArray(kArrayCid, instance_size, slow_path, Assembler::kFarJump, | 2077 __ TryAllocateArray(kArrayCid, instance_size, slow_path, Assembler::kFarJump, |
| 2080 RAX, // instance | 2078 RAX, // instance |
| 2081 RCX, // end address | 2079 RCX, // end address |
| 2082 R13); // temp | 2080 R13); // temp |
| 2083 | 2081 |
| 2084 // RAX: new object start as a tagged pointer. | 2082 // RAX: new object start as a tagged pointer. |
| 2085 // Store the type argument field. | 2083 // Store the type argument field. |
| 2086 __ StoreIntoObjectNoBarrier(RAX, | 2084 __ StoreIntoObjectNoBarrier( |
| 2087 FieldAddress(RAX, Array::type_arguments_offset()), | 2085 RAX, FieldAddress(RAX, Array::type_arguments_offset()), kElemTypeReg); |
| 2088 kElemTypeReg); | |
| 2089 | 2086 |
| 2090 // Set the length field. | 2087 // Set the length field. |
| 2091 __ StoreIntoObjectNoBarrier(RAX, | 2088 __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, Array::length_offset()), |
| 2092 FieldAddress(RAX, Array::length_offset()), | |
| 2093 kLengthReg); | 2089 kLengthReg); |
| 2094 | 2090 |
| 2095 // Initialize all array elements to raw_null. | 2091 // Initialize all array elements to raw_null. |
| 2096 // RAX: new object start as a tagged pointer. | 2092 // RAX: new object start as a tagged pointer. |
| 2097 // RCX: new object end address. | 2093 // RCX: new object end address. |
| 2098 // RDI: iterator which initially points to the start of the variable | 2094 // RDI: iterator which initially points to the start of the variable |
| 2099 // data area to be initialized. | 2095 // data area to be initialized. |
| 2100 if (num_elements > 0) { | 2096 if (num_elements > 0) { |
| 2101 const intptr_t array_size = instance_size - sizeof(RawArray); | 2097 const intptr_t array_size = instance_size - sizeof(RawArray); |
| 2102 __ LoadObject(R12, Object::null_object()); | 2098 __ LoadObject(R12, Object::null_object()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2122 | 2118 |
| 2123 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2119 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2124 // Allocate the array. R10 = length, RBX = element type. | 2120 // Allocate the array. R10 = length, RBX = element type. |
| 2125 const Register kLengthReg = R10; | 2121 const Register kLengthReg = R10; |
| 2126 const Register kElemTypeReg = RBX; | 2122 const Register kElemTypeReg = RBX; |
| 2127 const Register kResultReg = RAX; | 2123 const Register kResultReg = RAX; |
| 2128 ASSERT(locs()->in(0).reg() == kElemTypeReg); | 2124 ASSERT(locs()->in(0).reg() == kElemTypeReg); |
| 2129 ASSERT(locs()->in(1).reg() == kLengthReg); | 2125 ASSERT(locs()->in(1).reg() == kLengthReg); |
| 2130 | 2126 |
| 2131 Label slow_path, done; | 2127 Label slow_path, done; |
| 2132 if (compiler->is_optimizing() && | 2128 if (compiler->is_optimizing() && !FLAG_precompiled_mode && |
| 2133 !FLAG_precompiled_mode && | |
| 2134 num_elements()->BindsToConstant() && | 2129 num_elements()->BindsToConstant() && |
| 2135 num_elements()->BoundConstant().IsSmi()) { | 2130 num_elements()->BoundConstant().IsSmi()) { |
| 2136 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); | 2131 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); |
| 2137 if ((length >= 0) && (length <= Array::kMaxElements)) { | 2132 if ((length >= 0) && (length <= Array::kMaxElements)) { |
| 2138 Label slow_path, done; | 2133 Label slow_path, done; |
| 2139 InlineArrayAllocation(compiler, length, &slow_path, &done); | 2134 InlineArrayAllocation(compiler, length, &slow_path, &done); |
| 2140 __ Bind(&slow_path); | 2135 __ Bind(&slow_path); |
| 2141 __ PushObject(Object::null_object()); // Make room for the result. | 2136 __ PushObject(Object::null_object()); // Make room for the result. |
| 2142 __ pushq(kLengthReg); | 2137 __ pushq(kLengthReg); |
| 2143 __ pushq(kElemTypeReg); | 2138 __ pushq(kElemTypeReg); |
| 2144 compiler->GenerateRuntimeCall(token_pos(), | 2139 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2145 deopt_id(), | 2140 kAllocateArrayRuntimeEntry, 2, locs()); |
| 2146 kAllocateArrayRuntimeEntry, | |
| 2147 2, | |
| 2148 locs()); | |
| 2149 __ Drop(2); | 2141 __ Drop(2); |
| 2150 __ popq(kResultReg); | 2142 __ popq(kResultReg); |
| 2151 __ Bind(&done); | 2143 __ Bind(&done); |
| 2152 return; | 2144 return; |
| 2153 } | 2145 } |
| 2154 } | 2146 } |
| 2155 | 2147 |
| 2156 __ Bind(&slow_path); | 2148 __ Bind(&slow_path); |
| 2157 const Code& stub = Code::ZoneHandle(compiler->zone(), | 2149 const Code& stub = Code::ZoneHandle(compiler->zone(), |
| 2158 StubCode::AllocateArray_entry()->code()); | 2150 StubCode::AllocateArray_entry()->code()); |
| 2159 compiler->AddStubCallTarget(stub); | 2151 compiler->AddStubCallTarget(stub); |
| 2160 compiler->GenerateCall(token_pos(), | 2152 compiler->GenerateCall(token_pos(), *StubCode::AllocateArray_entry(), |
| 2161 *StubCode::AllocateArray_entry(), | 2153 RawPcDescriptors::kOther, locs()); |
| 2162 RawPcDescriptors::kOther, | |
| 2163 locs()); | |
| 2164 __ Bind(&done); | 2154 __ Bind(&done); |
| 2165 ASSERT(locs()->out(0).reg() == kResultReg); | 2155 ASSERT(locs()->out(0).reg() == kResultReg); |
| 2166 } | 2156 } |
| 2167 | 2157 |
| 2168 | 2158 |
| 2169 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, | 2159 LocationSummary* LoadFieldInstr::MakeLocationSummary(Zone* zone, |
| 2170 bool opt) const { | 2160 bool opt) const { |
| 2171 const intptr_t kNumInputs = 1; | 2161 const intptr_t kNumInputs = 1; |
| 2172 const intptr_t kNumTemps = | 2162 const intptr_t kNumTemps = |
| 2173 (IsUnboxedLoad() && opt) ? 1 : | 2163 (IsUnboxedLoad() && opt) ? 1 : ((IsPotentialUnboxedLoad()) ? 2 : 0); |
| 2174 ((IsPotentialUnboxedLoad()) ? 2 : 0); | 2164 LocationSummary* locs = new (zone) LocationSummary( |
| 2175 LocationSummary* locs = new(zone) LocationSummary( | 2165 zone, kNumInputs, kNumTemps, (opt && !IsPotentialUnboxedLoad()) |
| 2176 zone, kNumInputs, kNumTemps, | 2166 ? LocationSummary::kNoCall |
| 2177 (opt && !IsPotentialUnboxedLoad()) | 2167 : LocationSummary::kCallOnSlowPath); |
| 2178 ? LocationSummary::kNoCall | |
| 2179 : LocationSummary::kCallOnSlowPath); | |
| 2180 | 2168 |
| 2181 locs->set_in(0, Location::RequiresRegister()); | 2169 locs->set_in(0, Location::RequiresRegister()); |
| 2182 | 2170 |
| 2183 if (IsUnboxedLoad() && opt) { | 2171 if (IsUnboxedLoad() && opt) { |
| 2184 locs->set_temp(0, Location::RequiresRegister()); | 2172 locs->set_temp(0, Location::RequiresRegister()); |
| 2185 } else if (IsPotentialUnboxedLoad()) { | 2173 } else if (IsPotentialUnboxedLoad()) { |
| 2186 locs->set_temp(0, opt ? Location::RequiresFpuRegister() | 2174 locs->set_temp(0, opt ? Location::RequiresFpuRegister() |
| 2187 : Location::FpuRegisterLocation(XMM1)); | 2175 : Location::FpuRegisterLocation(XMM1)); |
| 2188 locs->set_temp(1, Location::RequiresRegister()); | 2176 locs->set_temp(1, Location::RequiresRegister()); |
| 2189 } | 2177 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2250 | 2238 |
| 2251 // Fall through. | 2239 // Fall through. |
| 2252 __ jmp(&load_pointer); | 2240 __ jmp(&load_pointer); |
| 2253 | 2241 |
| 2254 if (!compiler->is_optimizing()) { | 2242 if (!compiler->is_optimizing()) { |
| 2255 locs()->live_registers()->Add(locs()->in(0)); | 2243 locs()->live_registers()->Add(locs()->in(0)); |
| 2256 } | 2244 } |
| 2257 | 2245 |
| 2258 { | 2246 { |
| 2259 __ Bind(&load_double); | 2247 __ Bind(&load_double); |
| 2260 BoxAllocationSlowPath::Allocate( | 2248 BoxAllocationSlowPath::Allocate(compiler, this, compiler->double_class(), |
| 2261 compiler, this, compiler->double_class(), result, temp); | 2249 result, temp); |
| 2262 __ movq(temp, FieldAddress(instance_reg, offset_in_bytes())); | 2250 __ movq(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| 2263 __ movsd(value, FieldAddress(temp, Double::value_offset())); | 2251 __ movsd(value, FieldAddress(temp, Double::value_offset())); |
| 2264 __ movsd(FieldAddress(result, Double::value_offset()), value); | 2252 __ movsd(FieldAddress(result, Double::value_offset()), value); |
| 2265 __ jmp(&done); | 2253 __ jmp(&done); |
| 2266 } | 2254 } |
| 2267 | 2255 |
| 2268 { | 2256 { |
| 2269 __ Bind(&load_float32x4); | 2257 __ Bind(&load_float32x4); |
| 2270 BoxAllocationSlowPath::Allocate( | 2258 BoxAllocationSlowPath::Allocate( |
| 2271 compiler, this, compiler->float32x4_class(), result, temp); | 2259 compiler, this, compiler->float32x4_class(), result, temp); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2289 } | 2277 } |
| 2290 __ movq(result, FieldAddress(instance_reg, offset_in_bytes())); | 2278 __ movq(result, FieldAddress(instance_reg, offset_in_bytes())); |
| 2291 __ Bind(&done); | 2279 __ Bind(&done); |
| 2292 } | 2280 } |
| 2293 | 2281 |
| 2294 | 2282 |
| 2295 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, | 2283 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone, |
| 2296 bool opt) const { | 2284 bool opt) const { |
| 2297 const intptr_t kNumInputs = 1; | 2285 const intptr_t kNumInputs = 1; |
| 2298 const intptr_t kNumTemps = 0; | 2286 const intptr_t kNumTemps = 0; |
| 2299 LocationSummary* locs = new(zone) LocationSummary( | 2287 LocationSummary* locs = new (zone) |
| 2300 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2288 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2301 locs->set_in(0, Location::RegisterLocation(RAX)); | 2289 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 2302 locs->set_out(0, Location::RegisterLocation(RAX)); | 2290 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2303 return locs; | 2291 return locs; |
| 2304 } | 2292 } |
| 2305 | 2293 |
| 2306 | 2294 |
| 2307 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2295 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2308 Register instantiator_reg = locs()->in(0).reg(); | 2296 Register instantiator_reg = locs()->in(0).reg(); |
| 2309 Register result_reg = locs()->out(0).reg(); | 2297 Register result_reg = locs()->out(0).reg(); |
| 2310 | 2298 |
| 2311 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2299 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
| 2312 // A runtime call to instantiate the type is required. | 2300 // A runtime call to instantiate the type is required. |
| 2313 __ PushObject(Object::null_object()); // Make room for the result. | 2301 __ PushObject(Object::null_object()); // Make room for the result. |
| 2314 __ PushObject(type()); | 2302 __ PushObject(type()); |
| 2315 __ pushq(instantiator_reg); // Push instantiator type arguments. | 2303 __ pushq(instantiator_reg); // Push instantiator type arguments. |
| 2316 compiler->GenerateRuntimeCall(token_pos(), | 2304 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2317 deopt_id(), | 2305 kInstantiateTypeRuntimeEntry, 2, locs()); |
| 2318 kInstantiateTypeRuntimeEntry, | 2306 __ Drop(2); // Drop instantiator and uninstantiated type. |
| 2319 2, | |
| 2320 locs()); | |
| 2321 __ Drop(2); // Drop instantiator and uninstantiated type. | |
| 2322 __ popq(result_reg); // Pop instantiated type. | 2307 __ popq(result_reg); // Pop instantiated type. |
| 2323 ASSERT(instantiator_reg == result_reg); | 2308 ASSERT(instantiator_reg == result_reg); |
| 2324 } | 2309 } |
| 2325 | 2310 |
| 2326 | 2311 |
| 2327 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( | 2312 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary( |
| 2328 Zone* zone, bool opt) const { | 2313 Zone* zone, |
| 2314 bool opt) const { |
| 2329 const intptr_t kNumInputs = 1; | 2315 const intptr_t kNumInputs = 1; |
| 2330 const intptr_t kNumTemps = 0; | 2316 const intptr_t kNumTemps = 0; |
| 2331 LocationSummary* locs = new(zone) LocationSummary( | 2317 LocationSummary* locs = new (zone) |
| 2332 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2318 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2333 locs->set_in(0, Location::RegisterLocation(RAX)); | 2319 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 2334 locs->set_out(0, Location::RegisterLocation(RAX)); | 2320 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2335 return locs; | 2321 return locs; |
| 2336 } | 2322 } |
| 2337 | 2323 |
| 2338 | 2324 |
| 2339 void InstantiateTypeArgumentsInstr::EmitNativeCode( | 2325 void InstantiateTypeArgumentsInstr::EmitNativeCode( |
| 2340 FlowGraphCompiler* compiler) { | 2326 FlowGraphCompiler* compiler) { |
| 2341 Register instantiator_reg = locs()->in(0).reg(); | 2327 Register instantiator_reg = locs()->in(0).reg(); |
| 2342 Register result_reg = locs()->out(0).reg(); | 2328 Register result_reg = locs()->out(0).reg(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2377 __ Bind(&found); | 2363 __ Bind(&found); |
| 2378 __ movq(RAX, Address(RDI, 1 * kWordSize)); // Cached instantiated args. | 2364 __ movq(RAX, Address(RDI, 1 * kWordSize)); // Cached instantiated args. |
| 2379 __ jmp(&type_arguments_instantiated, Assembler::kNearJump); | 2365 __ jmp(&type_arguments_instantiated, Assembler::kNearJump); |
| 2380 | 2366 |
| 2381 __ Bind(&slow_case); | 2367 __ Bind(&slow_case); |
| 2382 // Instantiate non-null type arguments. | 2368 // Instantiate non-null type arguments. |
| 2383 // A runtime call to instantiate the type arguments is required. | 2369 // A runtime call to instantiate the type arguments is required. |
| 2384 __ PushObject(Object::null_object()); // Make room for the result. | 2370 __ PushObject(Object::null_object()); // Make room for the result. |
| 2385 __ PushObject(type_arguments()); | 2371 __ PushObject(type_arguments()); |
| 2386 __ pushq(instantiator_reg); // Push instantiator type arguments. | 2372 __ pushq(instantiator_reg); // Push instantiator type arguments. |
| 2387 compiler->GenerateRuntimeCall(token_pos(), | 2373 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2388 deopt_id(), | 2374 kInstantiateTypeArgumentsRuntimeEntry, 2, |
| 2389 kInstantiateTypeArgumentsRuntimeEntry, | |
| 2390 2, | |
| 2391 locs()); | 2375 locs()); |
| 2392 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 2376 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 2393 __ popq(result_reg); // Pop instantiated type arguments. | 2377 __ popq(result_reg); // Pop instantiated type arguments. |
| 2394 __ Bind(&type_arguments_instantiated); | 2378 __ Bind(&type_arguments_instantiated); |
| 2395 ASSERT(instantiator_reg == result_reg); | 2379 ASSERT(instantiator_reg == result_reg); |
| 2396 } | 2380 } |
| 2397 | 2381 |
| 2398 | 2382 |
| 2399 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( | 2383 LocationSummary* AllocateUninitializedContextInstr::MakeLocationSummary( |
| 2400 Zone* zone, | 2384 Zone* zone, |
| 2401 bool opt) const { | 2385 bool opt) const { |
| 2402 ASSERT(opt); | 2386 ASSERT(opt); |
| 2403 const intptr_t kNumInputs = 0; | 2387 const intptr_t kNumInputs = 0; |
| 2404 const intptr_t kNumTemps = 2; | 2388 const intptr_t kNumTemps = 2; |
| 2405 LocationSummary* locs = new(zone) LocationSummary( | 2389 LocationSummary* locs = new (zone) LocationSummary( |
| 2406 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2390 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2407 locs->set_temp(0, Location::RegisterLocation(R10)); | 2391 locs->set_temp(0, Location::RegisterLocation(R10)); |
| 2408 locs->set_temp(1, Location::RegisterLocation(R13)); | 2392 locs->set_temp(1, Location::RegisterLocation(R13)); |
| 2409 locs->set_out(0, Location::RegisterLocation(RAX)); | 2393 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2410 return locs; | 2394 return locs; |
| 2411 } | 2395 } |
| 2412 | 2396 |
| 2413 | 2397 |
| 2414 class AllocateContextSlowPath : public SlowPathCode { | 2398 class AllocateContextSlowPath : public SlowPathCode { |
| 2415 public: | 2399 public: |
| 2416 explicit AllocateContextSlowPath( | 2400 explicit AllocateContextSlowPath( |
| 2417 AllocateUninitializedContextInstr* instruction) | 2401 AllocateUninitializedContextInstr* instruction) |
| 2418 : instruction_(instruction) { } | 2402 : instruction_(instruction) {} |
| 2419 | 2403 |
| 2420 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2404 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2421 __ Comment("AllocateContextSlowPath"); | 2405 __ Comment("AllocateContextSlowPath"); |
| 2422 __ Bind(entry_label()); | 2406 __ Bind(entry_label()); |
| 2423 | 2407 |
| 2424 LocationSummary* locs = instruction_->locs(); | 2408 LocationSummary* locs = instruction_->locs(); |
| 2425 locs->live_registers()->Remove(locs->out(0)); | 2409 locs->live_registers()->Remove(locs->out(0)); |
| 2426 | 2410 |
| 2427 compiler->SaveLiveRegisters(locs); | 2411 compiler->SaveLiveRegisters(locs); |
| 2428 | 2412 |
| 2429 __ LoadImmediate(R10, Immediate(instruction_->num_context_variables())); | 2413 __ LoadImmediate(R10, Immediate(instruction_->num_context_variables())); |
| 2430 const Code& stub = Code::ZoneHandle( | 2414 const Code& stub = Code::ZoneHandle( |
| 2431 compiler->zone(), StubCode::AllocateContext_entry()->code()); | 2415 compiler->zone(), StubCode::AllocateContext_entry()->code()); |
| 2432 compiler->AddStubCallTarget(stub); | 2416 compiler->AddStubCallTarget(stub); |
| 2433 compiler->GenerateCall(instruction_->token_pos(), | 2417 compiler->GenerateCall(instruction_->token_pos(), |
| 2434 *StubCode::AllocateContext_entry(), | 2418 *StubCode::AllocateContext_entry(), |
| 2435 RawPcDescriptors::kOther, | 2419 RawPcDescriptors::kOther, locs); |
| 2436 locs); | |
| 2437 ASSERT(instruction_->locs()->out(0).reg() == RAX); | 2420 ASSERT(instruction_->locs()->out(0).reg() == RAX); |
| 2438 compiler->RestoreLiveRegisters(instruction_->locs()); | 2421 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2439 __ jmp(exit_label()); | 2422 __ jmp(exit_label()); |
| 2440 } | 2423 } |
| 2441 | 2424 |
| 2442 private: | 2425 private: |
| 2443 AllocateUninitializedContextInstr* instruction_; | 2426 AllocateUninitializedContextInstr* instruction_; |
| 2444 }; | 2427 }; |
| 2445 | 2428 |
| 2446 | 2429 |
| 2447 void AllocateUninitializedContextInstr::EmitNativeCode( | 2430 void AllocateUninitializedContextInstr::EmitNativeCode( |
| 2448 FlowGraphCompiler* compiler) { | 2431 FlowGraphCompiler* compiler) { |
| 2449 ASSERT(compiler->is_optimizing()); | 2432 ASSERT(compiler->is_optimizing()); |
| 2450 Register temp = locs()->temp(0).reg(); | 2433 Register temp = locs()->temp(0).reg(); |
| 2451 Register result = locs()->out(0).reg(); | 2434 Register result = locs()->out(0).reg(); |
| 2452 // Try allocate the object. | 2435 // Try allocate the object. |
| 2453 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); | 2436 AllocateContextSlowPath* slow_path = new AllocateContextSlowPath(this); |
| 2454 compiler->AddSlowPathCode(slow_path); | 2437 compiler->AddSlowPathCode(slow_path); |
| 2455 intptr_t instance_size = Context::InstanceSize(num_context_variables()); | 2438 intptr_t instance_size = Context::InstanceSize(num_context_variables()); |
| 2456 | 2439 |
| 2457 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), | 2440 __ TryAllocateArray(kContextCid, instance_size, slow_path->entry_label(), |
| 2458 Assembler::kFarJump, | 2441 Assembler::kFarJump, |
| 2459 result, // instance | 2442 result, // instance |
| 2460 temp, // end address | 2443 temp, // end address |
| 2461 locs()->temp(1).reg()); | 2444 locs()->temp(1).reg()); |
| 2462 | 2445 |
| 2463 // Setup up number of context variables field. | 2446 // Setup up number of context variables field. |
| 2464 __ movq(FieldAddress(result, Context::num_variables_offset()), | 2447 __ movq(FieldAddress(result, Context::num_variables_offset()), |
| 2465 Immediate(num_context_variables())); | 2448 Immediate(num_context_variables())); |
| 2466 | 2449 |
| 2467 __ Bind(slow_path->exit_label()); | 2450 __ Bind(slow_path->exit_label()); |
| 2468 } | 2451 } |
| 2469 | 2452 |
| 2470 | 2453 |
| 2471 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, | 2454 LocationSummary* AllocateContextInstr::MakeLocationSummary(Zone* zone, |
| 2472 bool opt) const { | 2455 bool opt) const { |
| 2473 const intptr_t kNumInputs = 0; | 2456 const intptr_t kNumInputs = 0; |
| 2474 const intptr_t kNumTemps = 1; | 2457 const intptr_t kNumTemps = 1; |
| 2475 LocationSummary* locs = new(zone) LocationSummary( | 2458 LocationSummary* locs = new (zone) |
| 2476 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2459 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2477 locs->set_temp(0, Location::RegisterLocation(R10)); | 2460 locs->set_temp(0, Location::RegisterLocation(R10)); |
| 2478 locs->set_out(0, Location::RegisterLocation(RAX)); | 2461 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2479 return locs; | 2462 return locs; |
| 2480 } | 2463 } |
| 2481 | 2464 |
| 2482 | 2465 |
| 2483 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2466 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2484 ASSERT(locs()->temp(0).reg() == R10); | 2467 ASSERT(locs()->temp(0).reg() == R10); |
| 2485 ASSERT(locs()->out(0).reg() == RAX); | 2468 ASSERT(locs()->out(0).reg() == RAX); |
| 2486 | 2469 |
| 2487 __ LoadImmediate(R10, Immediate(num_context_variables())); | 2470 __ LoadImmediate(R10, Immediate(num_context_variables())); |
| 2488 compiler->GenerateCall(token_pos(), | 2471 compiler->GenerateCall(token_pos(), *StubCode::AllocateContext_entry(), |
| 2489 *StubCode::AllocateContext_entry(), | 2472 RawPcDescriptors::kOther, locs()); |
| 2490 RawPcDescriptors::kOther, | |
| 2491 locs()); | |
| 2492 } | 2473 } |
| 2493 | 2474 |
| 2494 | 2475 |
| 2495 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2476 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2496 bool opt) const { | 2477 bool opt) const { |
| 2497 const intptr_t kNumInputs = 1; | 2478 const intptr_t kNumInputs = 1; |
| 2498 const intptr_t kNumTemps = 1; | 2479 const intptr_t kNumTemps = 1; |
| 2499 LocationSummary* locs = new(zone) LocationSummary( | 2480 LocationSummary* locs = new (zone) |
| 2500 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2481 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2501 locs->set_in(0, Location::RegisterLocation(RAX)); | 2482 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 2502 locs->set_temp(0, Location::RegisterLocation(RCX)); | 2483 locs->set_temp(0, Location::RegisterLocation(RCX)); |
| 2503 return locs; | 2484 return locs; |
| 2504 } | 2485 } |
| 2505 | 2486 |
| 2506 | 2487 |
| 2507 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2488 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2508 Register field = locs()->in(0).reg(); | 2489 Register field = locs()->in(0).reg(); |
| 2509 Register temp = locs()->temp(0).reg(); | 2490 Register temp = locs()->temp(0).reg(); |
| 2510 | 2491 |
| 2511 Label call_runtime, no_call; | 2492 Label call_runtime, no_call; |
| 2512 | 2493 |
| 2513 __ movq(temp, FieldAddress(field, Field::static_value_offset())); | 2494 __ movq(temp, FieldAddress(field, Field::static_value_offset())); |
| 2514 __ CompareObject(temp, Object::sentinel()); | 2495 __ CompareObject(temp, Object::sentinel()); |
| 2515 __ j(EQUAL, &call_runtime); | 2496 __ j(EQUAL, &call_runtime); |
| 2516 | 2497 |
| 2517 __ CompareObject(temp, Object::transition_sentinel()); | 2498 __ CompareObject(temp, Object::transition_sentinel()); |
| 2518 __ j(NOT_EQUAL, &no_call); | 2499 __ j(NOT_EQUAL, &no_call); |
| 2519 | 2500 |
| 2520 __ Bind(&call_runtime); | 2501 __ Bind(&call_runtime); |
| 2521 __ PushObject(Object::null_object()); // Make room for (unused) result. | 2502 __ PushObject(Object::null_object()); // Make room for (unused) result. |
| 2522 __ pushq(field); | 2503 __ pushq(field); |
| 2523 compiler->GenerateRuntimeCall(token_pos(), | 2504 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2524 deopt_id(), | 2505 kInitStaticFieldRuntimeEntry, 1, locs()); |
| 2525 kInitStaticFieldRuntimeEntry, | |
| 2526 1, | |
| 2527 locs()); | |
| 2528 __ Drop(2); // Remove argument and unused result. | 2506 __ Drop(2); // Remove argument and unused result. |
| 2529 __ Bind(&no_call); | 2507 __ Bind(&no_call); |
| 2530 } | 2508 } |
| 2531 | 2509 |
| 2532 | 2510 |
| 2533 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2511 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
| 2534 bool opt) const { | 2512 bool opt) const { |
| 2535 const intptr_t kNumInputs = 1; | 2513 const intptr_t kNumInputs = 1; |
| 2536 const intptr_t kNumTemps = 0; | 2514 const intptr_t kNumTemps = 0; |
| 2537 LocationSummary* locs = new(zone) LocationSummary( | 2515 LocationSummary* locs = new (zone) |
| 2538 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2516 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2539 locs->set_in(0, Location::RegisterLocation(RAX)); | 2517 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 2540 locs->set_out(0, Location::RegisterLocation(RAX)); | 2518 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2541 return locs; | 2519 return locs; |
| 2542 } | 2520 } |
| 2543 | 2521 |
| 2544 | 2522 |
| 2545 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2523 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2546 Register context_value = locs()->in(0).reg(); | 2524 Register context_value = locs()->in(0).reg(); |
| 2547 Register result = locs()->out(0).reg(); | 2525 Register result = locs()->out(0).reg(); |
| 2548 | 2526 |
| 2549 __ PushObject(Object::null_object()); // Make room for the result. | 2527 __ PushObject(Object::null_object()); // Make room for the result. |
| 2550 __ pushq(context_value); | 2528 __ pushq(context_value); |
| 2551 compiler->GenerateRuntimeCall(token_pos(), | 2529 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), |
| 2552 deopt_id(), | 2530 kCloneContextRuntimeEntry, 1, locs()); |
| 2553 kCloneContextRuntimeEntry, | |
| 2554 1, | |
| 2555 locs()); | |
| 2556 __ popq(result); // Remove argument. | 2531 __ popq(result); // Remove argument. |
| 2557 __ popq(result); // Get result (cloned context). | 2532 __ popq(result); // Get result (cloned context). |
| 2558 } | 2533 } |
| 2559 | 2534 |
| 2560 | 2535 |
| 2561 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2536 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
| 2562 bool opt) const { | 2537 bool opt) const { |
| 2563 UNREACHABLE(); | 2538 UNREACHABLE(); |
| 2564 return NULL; | 2539 return NULL; |
| 2565 } | 2540 } |
| 2566 | 2541 |
| 2567 | 2542 |
| 2568 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2543 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2569 __ Bind(compiler->GetJumpLabel(this)); | 2544 __ Bind(compiler->GetJumpLabel(this)); |
| 2570 compiler->AddExceptionHandler(catch_try_index(), | 2545 compiler->AddExceptionHandler(catch_try_index(), try_index(), |
| 2571 try_index(), | |
| 2572 compiler->assembler()->CodeSize(), | 2546 compiler->assembler()->CodeSize(), |
| 2573 catch_handler_types_, | 2547 catch_handler_types_, needs_stacktrace()); |
| 2574 needs_stacktrace()); | |
| 2575 // On lazy deoptimization we patch the optimized code here to enter the | 2548 // On lazy deoptimization we patch the optimized code here to enter the |
| 2576 // deoptimization stub. | 2549 // deoptimization stub. |
| 2577 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); | 2550 const intptr_t deopt_id = Thread::ToDeoptAfter(GetDeoptId()); |
| 2578 if (compiler->is_optimizing()) { | 2551 if (compiler->is_optimizing()) { |
| 2579 compiler->AddDeoptIndexAtCall(deopt_id); | 2552 compiler->AddDeoptIndexAtCall(deopt_id); |
| 2580 } else { | 2553 } else { |
| 2581 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 2554 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id, |
| 2582 deopt_id, | |
| 2583 TokenPosition::kNoSource); | 2555 TokenPosition::kNoSource); |
| 2584 } | 2556 } |
| 2585 if (HasParallelMove()) { | 2557 if (HasParallelMove()) { |
| 2586 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2558 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 2587 } | 2559 } |
| 2588 | 2560 |
| 2589 // Restore RSP from RBP as we are coming from a throw and the code for | 2561 // Restore RSP from RBP as we are coming from a throw and the code for |
| 2590 // popping arguments has not been run. | 2562 // popping arguments has not been run. |
| 2591 const intptr_t fp_sp_dist = | 2563 const intptr_t fp_sp_dist = |
| 2592 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 2564 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2637 __ movq(Address(RBP, stacktrace_var().index() * kWordSize), | 2609 __ movq(Address(RBP, stacktrace_var().index() * kWordSize), |
| 2638 kStackTraceObjectReg); | 2610 kStackTraceObjectReg); |
| 2639 } | 2611 } |
| 2640 } | 2612 } |
| 2641 | 2613 |
| 2642 | 2614 |
| 2643 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, | 2615 LocationSummary* CheckStackOverflowInstr::MakeLocationSummary(Zone* zone, |
| 2644 bool opt) const { | 2616 bool opt) const { |
| 2645 const intptr_t kNumInputs = 0; | 2617 const intptr_t kNumInputs = 0; |
| 2646 const intptr_t kNumTemps = 1; | 2618 const intptr_t kNumTemps = 1; |
| 2647 LocationSummary* summary = new(zone) LocationSummary( | 2619 LocationSummary* summary = new (zone) LocationSummary( |
| 2648 zone, kNumInputs, | 2620 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2649 kNumTemps, | |
| 2650 LocationSummary::kCallOnSlowPath); | |
| 2651 summary->set_temp(0, Location::RequiresRegister()); | 2621 summary->set_temp(0, Location::RequiresRegister()); |
| 2652 return summary; | 2622 return summary; |
| 2653 } | 2623 } |
| 2654 | 2624 |
| 2655 | 2625 |
| 2656 class CheckStackOverflowSlowPath : public SlowPathCode { | 2626 class CheckStackOverflowSlowPath : public SlowPathCode { |
| 2657 public: | 2627 public: |
| 2658 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2628 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
| 2659 : instruction_(instruction) { } | 2629 : instruction_(instruction) {} |
| 2660 | 2630 |
| 2661 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2631 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2662 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { | 2632 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { |
| 2663 __ Comment("CheckStackOverflowSlowPathOsr"); | 2633 __ Comment("CheckStackOverflowSlowPathOsr"); |
| 2664 __ Bind(osr_entry_label()); | 2634 __ Bind(osr_entry_label()); |
| 2665 __ movq(Address(THR, Thread::stack_overflow_flags_offset()), | 2635 __ movq(Address(THR, Thread::stack_overflow_flags_offset()), |
| 2666 Immediate(Thread::kOsrRequest)); | 2636 Immediate(Thread::kOsrRequest)); |
| 2667 } | 2637 } |
| 2668 __ Comment("CheckStackOverflowSlowPath"); | 2638 __ Comment("CheckStackOverflowSlowPath"); |
| 2669 __ Bind(entry_label()); | 2639 __ Bind(entry_label()); |
| 2670 compiler->SaveLiveRegisters(instruction_->locs()); | 2640 compiler->SaveLiveRegisters(instruction_->locs()); |
| 2671 // pending_deoptimization_env_ is needed to generate a runtime call that | 2641 // pending_deoptimization_env_ is needed to generate a runtime call that |
| 2672 // may throw an exception. | 2642 // may throw an exception. |
| 2673 ASSERT(compiler->pending_deoptimization_env_ == NULL); | 2643 ASSERT(compiler->pending_deoptimization_env_ == NULL); |
| 2674 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); | 2644 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |
| 2675 compiler->pending_deoptimization_env_ = env; | 2645 compiler->pending_deoptimization_env_ = env; |
| 2676 compiler->GenerateRuntimeCall(instruction_->token_pos(), | 2646 compiler->GenerateRuntimeCall( |
| 2677 instruction_->deopt_id(), | 2647 instruction_->token_pos(), instruction_->deopt_id(), |
| 2678 kStackOverflowRuntimeEntry, | 2648 kStackOverflowRuntimeEntry, 0, instruction_->locs()); |
| 2679 0, | |
| 2680 instruction_->locs()); | |
| 2681 | 2649 |
| 2682 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { | 2650 if (FLAG_use_osr && !compiler->is_optimizing() && instruction_->in_loop()) { |
| 2683 // In unoptimized code, record loop stack checks as possible OSR entries. | 2651 // In unoptimized code, record loop stack checks as possible OSR entries. |
| 2684 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, | 2652 compiler->AddCurrentDescriptor(RawPcDescriptors::kOsrEntry, |
| 2685 instruction_->deopt_id(), | 2653 instruction_->deopt_id(), |
| 2686 TokenPosition::kNoSource); | 2654 TokenPosition::kNoSource); |
| 2687 } | 2655 } |
| 2688 compiler->pending_deoptimization_env_ = NULL; | 2656 compiler->pending_deoptimization_env_ = NULL; |
| 2689 compiler->RestoreLiveRegisters(instruction_->locs()); | 2657 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2690 __ jmp(exit_label()); | 2658 __ jmp(exit_label()); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2727 __ Bind(slow_path->exit_label()); | 2695 __ Bind(slow_path->exit_label()); |
| 2728 } | 2696 } |
| 2729 | 2697 |
| 2730 | 2698 |
| 2731 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2699 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
| 2732 BinarySmiOpInstr* shift_left) { | 2700 BinarySmiOpInstr* shift_left) { |
| 2733 const LocationSummary& locs = *shift_left->locs(); | 2701 const LocationSummary& locs = *shift_left->locs(); |
| 2734 Register left = locs.in(0).reg(); | 2702 Register left = locs.in(0).reg(); |
| 2735 Register result = locs.out(0).reg(); | 2703 Register result = locs.out(0).reg(); |
| 2736 ASSERT(left == result); | 2704 ASSERT(left == result); |
| 2737 Label* deopt = shift_left->CanDeoptimize() ? | 2705 Label* deopt = shift_left->CanDeoptimize() |
| 2738 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | 2706 ? compiler->AddDeoptStub(shift_left->deopt_id(), |
| 2739 : NULL; | 2707 ICData::kDeoptBinarySmiOp) |
| 2708 : NULL; |
| 2740 if (locs.in(1).IsConstant()) { | 2709 if (locs.in(1).IsConstant()) { |
| 2741 const Object& constant = locs.in(1).constant(); | 2710 const Object& constant = locs.in(1).constant(); |
| 2742 ASSERT(constant.IsSmi()); | 2711 ASSERT(constant.IsSmi()); |
| 2743 // shlq operation masks the count to 6 bits. | 2712 // shlq operation masks the count to 6 bits. |
| 2744 const intptr_t kCountLimit = 0x3F; | 2713 const intptr_t kCountLimit = 0x3F; |
| 2745 const intptr_t value = Smi::Cast(constant).Value(); | 2714 const intptr_t value = Smi::Cast(constant).Value(); |
| 2746 ASSERT((0 < value) && (value < kCountLimit)); | 2715 ASSERT((0 < value) && (value < kCountLimit)); |
| 2747 if (shift_left->can_overflow()) { | 2716 if (shift_left->can_overflow()) { |
| 2748 if (value == 1) { | 2717 if (value == 1) { |
| 2749 // Use overflow flag. | 2718 // Use overflow flag. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2775 const intptr_t left_int = Smi::Cast(obj).Value(); | 2744 const intptr_t left_int = Smi::Cast(obj).Value(); |
| 2776 if (left_int == 0) { | 2745 if (left_int == 0) { |
| 2777 __ CompareImmediate(right, Immediate(0)); | 2746 __ CompareImmediate(right, Immediate(0)); |
| 2778 __ j(NEGATIVE, deopt); | 2747 __ j(NEGATIVE, deopt); |
| 2779 return; | 2748 return; |
| 2780 } | 2749 } |
| 2781 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); | 2750 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); |
| 2782 const bool right_needs_check = | 2751 const bool right_needs_check = |
| 2783 !RangeUtils::IsWithin(right_range, 0, max_right - 1); | 2752 !RangeUtils::IsWithin(right_range, 0, max_right - 1); |
| 2784 if (right_needs_check) { | 2753 if (right_needs_check) { |
| 2785 __ CompareImmediate(right, | 2754 __ CompareImmediate( |
| 2786 Immediate(reinterpret_cast<int64_t>(Smi::New(max_right)))); | 2755 right, Immediate(reinterpret_cast<int64_t>(Smi::New(max_right)))); |
| 2787 __ j(ABOVE_EQUAL, deopt); | 2756 __ j(ABOVE_EQUAL, deopt); |
| 2788 } | 2757 } |
| 2789 __ SmiUntag(right); | 2758 __ SmiUntag(right); |
| 2790 __ shlq(left, right); | 2759 __ shlq(left, right); |
| 2791 } | 2760 } |
| 2792 return; | 2761 return; |
| 2793 } | 2762 } |
| 2794 | 2763 |
| 2795 const bool right_needs_check = | 2764 const bool right_needs_check = |
| 2796 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); | 2765 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); |
| 2797 ASSERT(right == RCX); // Count must be in RCX | 2766 ASSERT(right == RCX); // Count must be in RCX |
| 2798 if (!shift_left->can_overflow()) { | 2767 if (!shift_left->can_overflow()) { |
| 2799 if (right_needs_check) { | 2768 if (right_needs_check) { |
| 2800 const bool right_may_be_negative = | 2769 const bool right_may_be_negative = |
| 2801 (right_range == NULL) || !right_range->IsPositive(); | 2770 (right_range == NULL) || !right_range->IsPositive(); |
| 2802 if (right_may_be_negative) { | 2771 if (right_may_be_negative) { |
| 2803 ASSERT(shift_left->CanDeoptimize()); | 2772 ASSERT(shift_left->CanDeoptimize()); |
| 2804 __ CompareImmediate(right, Immediate(0)); | 2773 __ CompareImmediate(right, Immediate(0)); |
| 2805 __ j(NEGATIVE, deopt); | 2774 __ j(NEGATIVE, deopt); |
| 2806 } | 2775 } |
| 2807 Label done, is_not_zero; | 2776 Label done, is_not_zero; |
| 2808 __ CompareImmediate(right, | 2777 __ CompareImmediate( |
| 2809 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); | 2778 right, Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); |
| 2810 __ j(BELOW, &is_not_zero, Assembler::kNearJump); | 2779 __ j(BELOW, &is_not_zero, Assembler::kNearJump); |
| 2811 __ xorq(left, left); | 2780 __ xorq(left, left); |
| 2812 __ jmp(&done, Assembler::kNearJump); | 2781 __ jmp(&done, Assembler::kNearJump); |
| 2813 __ Bind(&is_not_zero); | 2782 __ Bind(&is_not_zero); |
| 2814 __ SmiUntag(right); | 2783 __ SmiUntag(right); |
| 2815 __ shlq(left, right); | 2784 __ shlq(left, right); |
| 2816 __ Bind(&done); | 2785 __ Bind(&done); |
| 2817 } else { | 2786 } else { |
| 2818 __ SmiUntag(right); | 2787 __ SmiUntag(right); |
| 2819 __ shlq(left, right); | 2788 __ shlq(left, right); |
| 2820 } | 2789 } |
| 2821 } else { | 2790 } else { |
| 2822 if (right_needs_check) { | 2791 if (right_needs_check) { |
| 2823 ASSERT(shift_left->CanDeoptimize()); | 2792 ASSERT(shift_left->CanDeoptimize()); |
| 2824 __ CompareImmediate(right, | 2793 __ CompareImmediate( |
| 2825 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); | 2794 right, Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); |
| 2826 __ j(ABOVE_EQUAL, deopt); | 2795 __ j(ABOVE_EQUAL, deopt); |
| 2827 } | 2796 } |
| 2828 // Left is not a constant. | 2797 // Left is not a constant. |
| 2829 Register temp = locs.temp(0).reg(); | 2798 Register temp = locs.temp(0).reg(); |
| 2830 // Check if count too large for handling it inlined. | 2799 // Check if count too large for handling it inlined. |
| 2831 __ movq(temp, left); | 2800 __ movq(temp, left); |
| 2832 __ SmiUntag(right); | 2801 __ SmiUntag(right); |
| 2833 // Overflow test (preserve temp and right); | 2802 // Overflow test (preserve temp and right); |
| 2834 __ shlq(left, right); | 2803 __ shlq(left, right); |
| 2835 __ sarq(left, right); | 2804 __ sarq(left, right); |
| 2836 __ cmpq(left, temp); | 2805 __ cmpq(left, temp); |
| 2837 __ j(NOT_EQUAL, deopt); // Overflow. | 2806 __ j(NOT_EQUAL, deopt); // Overflow. |
| 2838 // Shift for result now we know there is no overflow. | 2807 // Shift for result now we know there is no overflow. |
| 2839 __ shlq(left, right); | 2808 __ shlq(left, right); |
| 2840 } | 2809 } |
| 2841 } | 2810 } |
| 2842 | 2811 |
| 2843 | 2812 |
| 2844 class CheckedSmiSlowPath : public SlowPathCode { | 2813 class CheckedSmiSlowPath : public SlowPathCode { |
| 2845 public: | 2814 public: |
| 2846 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) | 2815 CheckedSmiSlowPath(CheckedSmiOpInstr* instruction, intptr_t try_index) |
| 2847 : instruction_(instruction), try_index_(try_index) { } | 2816 : instruction_(instruction), try_index_(try_index) {} |
| 2848 | 2817 |
| 2849 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2818 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2850 if (Assembler::EmittingComments()) { | 2819 if (Assembler::EmittingComments()) { |
| 2851 __ Comment("slow path smi operation"); | 2820 __ Comment("slow path smi operation"); |
| 2852 } | 2821 } |
| 2853 __ Bind(entry_label()); | 2822 __ Bind(entry_label()); |
| 2854 LocationSummary* locs = instruction_->locs(); | 2823 LocationSummary* locs = instruction_->locs(); |
| 2855 Register result = locs->out(0).reg(); | 2824 Register result = locs->out(0).reg(); |
| 2856 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 2825 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
| 2857 | 2826 |
| 2858 compiler->SaveLiveRegisters(locs); | 2827 compiler->SaveLiveRegisters(locs); |
| 2859 __ pushq(locs->in(0).reg()); | 2828 __ pushq(locs->in(0).reg()); |
| 2860 __ pushq(locs->in(1).reg()); | 2829 __ pushq(locs->in(1).reg()); |
| 2861 compiler->EmitMegamorphicInstanceCall( | 2830 compiler->EmitMegamorphicInstanceCall( |
| 2862 *instruction_->call()->ic_data(), | 2831 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
| 2863 instruction_->call()->ArgumentCount(), | 2832 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
| 2864 instruction_->call()->deopt_id(), | 2833 locs, try_index_, |
| 2865 instruction_->call()->token_pos(), | |
| 2866 locs, | |
| 2867 try_index_, | |
| 2868 /* slow_path_argument_count = */ 2); | 2834 /* slow_path_argument_count = */ 2); |
| 2869 __ MoveRegister(result, RAX); | 2835 __ MoveRegister(result, RAX); |
| 2870 compiler->RestoreLiveRegisters(locs); | 2836 compiler->RestoreLiveRegisters(locs); |
| 2871 __ jmp(exit_label()); | 2837 __ jmp(exit_label()); |
| 2872 } | 2838 } |
| 2873 | 2839 |
| 2874 private: | 2840 private: |
| 2875 CheckedSmiOpInstr* instruction_; | 2841 CheckedSmiOpInstr* instruction_; |
| 2876 intptr_t try_index_; | 2842 intptr_t try_index_; |
| 2877 }; | 2843 }; |
| 2878 | 2844 |
| 2879 | 2845 |
| 2880 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, | 2846 LocationSummary* CheckedSmiOpInstr::MakeLocationSummary(Zone* zone, |
| 2881 bool opt) const { | 2847 bool opt) const { |
| 2882 const intptr_t kNumInputs = 2; | 2848 const intptr_t kNumInputs = 2; |
| 2883 const intptr_t kNumTemps = 0; | 2849 const intptr_t kNumTemps = 0; |
| 2884 LocationSummary* summary = new(zone) LocationSummary( | 2850 LocationSummary* summary = new (zone) LocationSummary( |
| 2885 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2851 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 2886 summary->set_in(0, Location::RequiresRegister()); | 2852 summary->set_in(0, Location::RequiresRegister()); |
| 2887 summary->set_in(1, Location::RequiresRegister()); | 2853 summary->set_in(1, Location::RequiresRegister()); |
| 2888 switch (op_kind()) { | 2854 switch (op_kind()) { |
| 2889 case Token::kADD: | 2855 case Token::kADD: |
| 2890 case Token::kSUB: | 2856 case Token::kSUB: |
| 2891 case Token::kMUL: | 2857 case Token::kMUL: |
| 2892 summary->set_out(0, Location::RequiresRegister()); | 2858 summary->set_out(0, Location::RequiresRegister()); |
| 2893 break; | 2859 break; |
| 2894 case Token::kBIT_OR: | 2860 case Token::kBIT_OR: |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2964 | 2930 |
| 2965 class CheckedSmiComparisonSlowPath : public SlowPathCode { | 2931 class CheckedSmiComparisonSlowPath : public SlowPathCode { |
| 2966 public: | 2932 public: |
| 2967 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, | 2933 CheckedSmiComparisonSlowPath(CheckedSmiComparisonInstr* instruction, |
| 2968 intptr_t try_index, | 2934 intptr_t try_index, |
| 2969 BranchLabels labels, | 2935 BranchLabels labels, |
| 2970 bool merged = false) | 2936 bool merged = false) |
| 2971 : instruction_(instruction), | 2937 : instruction_(instruction), |
| 2972 try_index_(try_index), | 2938 try_index_(try_index), |
| 2973 labels_(labels), | 2939 labels_(labels), |
| 2974 merged_(merged) { } | 2940 merged_(merged) {} |
| 2975 | 2941 |
| 2976 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2942 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2977 if (Assembler::EmittingComments()) { | 2943 if (Assembler::EmittingComments()) { |
| 2978 __ Comment("slow path smi comparison"); | 2944 __ Comment("slow path smi comparison"); |
| 2979 } | 2945 } |
| 2980 __ Bind(entry_label()); | 2946 __ Bind(entry_label()); |
| 2981 LocationSummary* locs = instruction_->locs(); | 2947 LocationSummary* locs = instruction_->locs(); |
| 2982 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); | 2948 Register result = merged_ ? locs->temp(0).reg() : locs->out(0).reg(); |
| 2983 locs->live_registers()->Remove(Location::RegisterLocation(result)); | 2949 locs->live_registers()->Remove(Location::RegisterLocation(result)); |
| 2984 | 2950 |
| 2985 compiler->SaveLiveRegisters(locs); | 2951 compiler->SaveLiveRegisters(locs); |
| 2986 __ pushq(locs->in(0).reg()); | 2952 __ pushq(locs->in(0).reg()); |
| 2987 __ pushq(locs->in(1).reg()); | 2953 __ pushq(locs->in(1).reg()); |
| 2988 compiler->EmitMegamorphicInstanceCall( | 2954 compiler->EmitMegamorphicInstanceCall( |
| 2989 *instruction_->call()->ic_data(), | 2955 *instruction_->call()->ic_data(), instruction_->call()->ArgumentCount(), |
| 2990 instruction_->call()->ArgumentCount(), | 2956 instruction_->call()->deopt_id(), instruction_->call()->token_pos(), |
| 2991 instruction_->call()->deopt_id(), | 2957 locs, try_index_, |
| 2992 instruction_->call()->token_pos(), | |
| 2993 locs, | |
| 2994 try_index_, | |
| 2995 /* slow_path_argument_count = */ 2); | 2958 /* slow_path_argument_count = */ 2); |
| 2996 __ MoveRegister(result, RAX); | 2959 __ MoveRegister(result, RAX); |
| 2997 compiler->RestoreLiveRegisters(locs); | 2960 compiler->RestoreLiveRegisters(locs); |
| 2998 if (merged_) { | 2961 if (merged_) { |
| 2999 __ CompareObject(result, Bool::True()); | 2962 __ CompareObject(result, Bool::True()); |
| 3000 __ j(EQUAL, instruction_->is_negated() | 2963 __ j(EQUAL, instruction_->is_negated() ? labels_.false_label |
| 3001 ? labels_.false_label : labels_.true_label); | 2964 : labels_.true_label); |
| 3002 __ jmp(instruction_->is_negated() | 2965 __ jmp(instruction_->is_negated() ? labels_.true_label |
| 3003 ? labels_.true_label : labels_.false_label); | 2966 : labels_.false_label); |
| 3004 } else { | 2967 } else { |
| 3005 __ jmp(exit_label()); | 2968 __ jmp(exit_label()); |
| 3006 } | 2969 } |
| 3007 } | 2970 } |
| 3008 | 2971 |
| 3009 private: | 2972 private: |
| 3010 CheckedSmiComparisonInstr* instruction_; | 2973 CheckedSmiComparisonInstr* instruction_; |
| 3011 intptr_t try_index_; | 2974 intptr_t try_index_; |
| 3012 BranchLabels labels_; | 2975 BranchLabels labels_; |
| 3013 bool merged_; | 2976 bool merged_; |
| 3014 }; | 2977 }; |
| 3015 | 2978 |
| 3016 | 2979 |
| 3017 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( | 2980 LocationSummary* CheckedSmiComparisonInstr::MakeLocationSummary( |
| 3018 Zone* zone, bool opt) const { | 2981 Zone* zone, |
| 2982 bool opt) const { |
| 3019 const intptr_t kNumInputs = 2; | 2983 const intptr_t kNumInputs = 2; |
| 3020 const intptr_t kNumTemps = 1; | 2984 const intptr_t kNumTemps = 1; |
| 3021 LocationSummary* summary = new(zone) LocationSummary( | 2985 LocationSummary* summary = new (zone) LocationSummary( |
| 3022 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 2986 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3023 summary->set_in(0, Location::RequiresRegister()); | 2987 summary->set_in(0, Location::RequiresRegister()); |
| 3024 summary->set_in(1, Location::RequiresRegister()); | 2988 summary->set_in(1, Location::RequiresRegister()); |
| 3025 summary->set_temp(0, Location::RequiresRegister()); | 2989 summary->set_temp(0, Location::RequiresRegister()); |
| 3026 summary->set_out(0, Location::RequiresRegister()); | 2990 summary->set_out(0, Location::RequiresRegister()); |
| 3027 return summary; | 2991 return summary; |
| 3028 } | 2992 } |
| 3029 | 2993 |
| 3030 | 2994 |
| 3031 Condition CheckedSmiComparisonInstr::EmitComparisonCode( | 2995 Condition CheckedSmiComparisonInstr::EmitComparisonCode( |
| 3032 FlowGraphCompiler* compiler, BranchLabels labels) { | 2996 FlowGraphCompiler* compiler, |
| 2997 BranchLabels labels) { |
| 3033 return EmitInt64ComparisonOp(compiler, *locs(), kind()); | 2998 return EmitInt64ComparisonOp(compiler, *locs(), kind()); |
| 3034 } | 2999 } |
| 3035 | 3000 |
| 3036 | 3001 |
| 3037 #define EMIT_SMI_CHECK \ | 3002 #define EMIT_SMI_CHECK \ |
| 3038 intptr_t left_cid = left()->Type()->ToCid(); \ | 3003 intptr_t left_cid = left()->Type()->ToCid(); \ |
| 3039 intptr_t right_cid = right()->Type()->ToCid(); \ | 3004 intptr_t right_cid = right()->Type()->ToCid(); \ |
| 3040 Register left = locs()->in(0).reg(); \ | 3005 Register left = locs()->in(0).reg(); \ |
| 3041 Register right = locs()->in(1).reg(); \ | 3006 Register right = locs()->in(1).reg(); \ |
| 3042 if (this->left()->definition() == this->right()->definition()) { \ | 3007 if (this->left()->definition() == this->right()->definition()) { \ |
| 3043 __ testq(left, Immediate(kSmiTagMask)); \ | 3008 __ testq(left, Immediate(kSmiTagMask)); \ |
| 3044 } else if (left_cid == kSmiCid) { \ | 3009 } else if (left_cid == kSmiCid) { \ |
| 3045 __ testq(right, Immediate(kSmiTagMask)); \ | 3010 __ testq(right, Immediate(kSmiTagMask)); \ |
| 3046 } else if (right_cid == kSmiCid) { \ | 3011 } else if (right_cid == kSmiCid) { \ |
| 3047 __ testq(left, Immediate(kSmiTagMask)); \ | 3012 __ testq(left, Immediate(kSmiTagMask)); \ |
| 3048 } else { \ | 3013 } else { \ |
| 3049 __ movq(TMP, left); \ | 3014 __ movq(TMP, left); \ |
| 3050 __ orq(TMP, right); \ | 3015 __ orq(TMP, right); \ |
| 3051 __ testq(TMP, Immediate(kSmiTagMask)); \ | 3016 __ testq(TMP, Immediate(kSmiTagMask)); \ |
| 3052 } \ | 3017 } \ |
| 3053 __ j(NOT_ZERO, slow_path->entry_label()) | 3018 __ j(NOT_ZERO, slow_path->entry_label()) |
| 3054 | 3019 |
| 3055 | 3020 |
| 3056 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 3021 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 3057 BranchInstr* branch) { | 3022 BranchInstr* branch) { |
| 3058 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3023 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 3059 CheckedSmiComparisonSlowPath* slow_path = | 3024 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
| 3060 new CheckedSmiComparisonSlowPath(this, | 3025 this, compiler->CurrentTryIndex(), labels, |
| 3061 compiler->CurrentTryIndex(), | 3026 /* merged = */ true); |
| 3062 labels, | |
| 3063 /* merged = */ true); | |
| 3064 compiler->AddSlowPathCode(slow_path); | 3027 compiler->AddSlowPathCode(slow_path); |
| 3065 EMIT_SMI_CHECK; | 3028 EMIT_SMI_CHECK; |
| 3066 Condition true_condition = EmitComparisonCode(compiler, labels); | 3029 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3067 EmitBranchOnCondition(compiler, true_condition, labels); | 3030 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3068 __ Bind(slow_path->exit_label()); | 3031 __ Bind(slow_path->exit_label()); |
| 3069 } | 3032 } |
| 3070 | 3033 |
| 3071 | 3034 |
| 3072 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3035 void CheckedSmiComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3073 Label true_label, false_label, done; | 3036 Label true_label, false_label, done; |
| 3074 BranchLabels labels = { &true_label, &false_label, &false_label }; | 3037 BranchLabels labels = {&true_label, &false_label, &false_label}; |
| 3075 CheckedSmiComparisonSlowPath* slow_path = | 3038 CheckedSmiComparisonSlowPath* slow_path = new CheckedSmiComparisonSlowPath( |
| 3076 new CheckedSmiComparisonSlowPath(this, | 3039 this, compiler->CurrentTryIndex(), labels, |
| 3077 compiler->CurrentTryIndex(), | 3040 /* merged = */ false); |
| 3078 labels, | |
| 3079 /* merged = */ false); | |
| 3080 compiler->AddSlowPathCode(slow_path); | 3041 compiler->AddSlowPathCode(slow_path); |
| 3081 EMIT_SMI_CHECK; | 3042 EMIT_SMI_CHECK; |
| 3082 Condition true_condition = EmitComparisonCode(compiler, labels); | 3043 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3083 EmitBranchOnCondition(compiler, true_condition, labels); | 3044 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3084 Register result = locs()->out(0).reg(); | 3045 Register result = locs()->out(0).reg(); |
| 3085 __ Bind(&false_label); | 3046 __ Bind(&false_label); |
| 3086 __ LoadObject(result, Bool::False()); | 3047 __ LoadObject(result, Bool::False()); |
| 3087 __ jmp(&done); | 3048 __ jmp(&done); |
| 3088 __ Bind(&true_label); | 3049 __ Bind(&true_label); |
| 3089 __ LoadObject(result, Bool::True()); | 3050 __ LoadObject(result, Bool::True()); |
| 3090 __ Bind(&done); | 3051 __ Bind(&done); |
| 3091 __ Bind(slow_path->exit_label()); | 3052 __ Bind(slow_path->exit_label()); |
| 3092 } | 3053 } |
| 3093 | 3054 |
| 3094 | 3055 |
| 3095 static bool CanBeImmediate(const Object& constant) { | 3056 static bool CanBeImmediate(const Object& constant) { |
| 3096 return constant.IsSmi() && | 3057 return constant.IsSmi() && |
| 3097 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); | 3058 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); |
| 3098 } | 3059 } |
| 3099 | 3060 |
| 3100 static bool IsSmiValue(const Object& constant, intptr_t value) { | 3061 static bool IsSmiValue(const Object& constant, intptr_t value) { |
| 3101 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); | 3062 return constant.IsSmi() && (Smi::Cast(constant).Value() == value); |
| 3102 } | 3063 } |
| 3103 | 3064 |
| 3104 | 3065 |
| 3105 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, | 3066 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 3106 bool opt) const { | 3067 bool opt) const { |
| 3107 const intptr_t kNumInputs = 2; | 3068 const intptr_t kNumInputs = 2; |
| 3108 | 3069 |
| 3109 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 3070 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
| 3110 if ((right_constant != NULL) && | 3071 if ((right_constant != NULL) && (op_kind() != Token::kTRUNCDIV) && |
| 3111 (op_kind() != Token::kTRUNCDIV) && | 3072 (op_kind() != Token::kSHL) && (op_kind() != Token::kMUL) && |
| 3112 (op_kind() != Token::kSHL) && | 3073 (op_kind() != Token::kMOD) && CanBeImmediate(right_constant->value())) { |
| 3113 (op_kind() != Token::kMUL) && | |
| 3114 (op_kind() != Token::kMOD) && | |
| 3115 CanBeImmediate(right_constant->value())) { | |
| 3116 const intptr_t kNumTemps = 0; | 3074 const intptr_t kNumTemps = 0; |
| 3117 LocationSummary* summary = new(zone) LocationSummary( | 3075 LocationSummary* summary = new (zone) |
| 3118 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3076 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3119 summary->set_in(0, Location::RequiresRegister()); | 3077 summary->set_in(0, Location::RequiresRegister()); |
| 3120 summary->set_in(1, Location::Constant(right_constant)); | 3078 summary->set_in(1, Location::Constant(right_constant)); |
| 3121 summary->set_out(0, Location::SameAsFirstInput()); | 3079 summary->set_out(0, Location::SameAsFirstInput()); |
| 3122 return summary; | 3080 return summary; |
| 3123 } | 3081 } |
| 3124 | 3082 |
| 3125 if (op_kind() == Token::kTRUNCDIV) { | 3083 if (op_kind() == Token::kTRUNCDIV) { |
| 3126 const intptr_t kNumTemps = 1; | 3084 const intptr_t kNumTemps = 1; |
| 3127 LocationSummary* summary = new(zone) LocationSummary( | 3085 LocationSummary* summary = new (zone) |
| 3128 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3086 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3129 if (RightIsPowerOfTwoConstant()) { | 3087 if (RightIsPowerOfTwoConstant()) { |
| 3130 summary->set_in(0, Location::RequiresRegister()); | 3088 summary->set_in(0, Location::RequiresRegister()); |
| 3131 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 3089 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
| 3132 summary->set_in(1, Location::Constant(right_constant)); | 3090 summary->set_in(1, Location::Constant(right_constant)); |
| 3133 summary->set_temp(0, Location::RequiresRegister()); | 3091 summary->set_temp(0, Location::RequiresRegister()); |
| 3134 summary->set_out(0, Location::SameAsFirstInput()); | 3092 summary->set_out(0, Location::SameAsFirstInput()); |
| 3135 } else { | 3093 } else { |
| 3136 // Both inputs must be writable because they will be untagged. | 3094 // Both inputs must be writable because they will be untagged. |
| 3137 summary->set_in(0, Location::RegisterLocation(RAX)); | 3095 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 3138 summary->set_in(1, Location::WritableRegister()); | 3096 summary->set_in(1, Location::WritableRegister()); |
| 3139 summary->set_out(0, Location::SameAsFirstInput()); | 3097 summary->set_out(0, Location::SameAsFirstInput()); |
| 3140 // Will be used for sign extension and division. | 3098 // Will be used for sign extension and division. |
| 3141 summary->set_temp(0, Location::RegisterLocation(RDX)); | 3099 summary->set_temp(0, Location::RegisterLocation(RDX)); |
| 3142 } | 3100 } |
| 3143 return summary; | 3101 return summary; |
| 3144 } else if (op_kind() == Token::kMOD) { | 3102 } else if (op_kind() == Token::kMOD) { |
| 3145 const intptr_t kNumTemps = 1; | 3103 const intptr_t kNumTemps = 1; |
| 3146 LocationSummary* summary = new(zone) LocationSummary( | 3104 LocationSummary* summary = new (zone) |
| 3147 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3105 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3148 // Both inputs must be writable because they will be untagged. | 3106 // Both inputs must be writable because they will be untagged. |
| 3149 summary->set_in(0, Location::RegisterLocation(RDX)); | 3107 summary->set_in(0, Location::RegisterLocation(RDX)); |
| 3150 summary->set_in(1, Location::WritableRegister()); | 3108 summary->set_in(1, Location::WritableRegister()); |
| 3151 summary->set_out(0, Location::SameAsFirstInput()); | 3109 summary->set_out(0, Location::SameAsFirstInput()); |
| 3152 // Will be used for sign extension and division. | 3110 // Will be used for sign extension and division. |
| 3153 summary->set_temp(0, Location::RegisterLocation(RAX)); | 3111 summary->set_temp(0, Location::RegisterLocation(RAX)); |
| 3154 return summary; | 3112 return summary; |
| 3155 } else if (op_kind() == Token::kSHR) { | 3113 } else if (op_kind() == Token::kSHR) { |
| 3156 const intptr_t kNumTemps = 0; | 3114 const intptr_t kNumTemps = 0; |
| 3157 LocationSummary* summary = new(zone) LocationSummary( | 3115 LocationSummary* summary = new (zone) |
| 3158 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3116 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3159 summary->set_in(0, Location::RequiresRegister()); | 3117 summary->set_in(0, Location::RequiresRegister()); |
| 3160 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 3118 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
| 3161 summary->set_out(0, Location::SameAsFirstInput()); | 3119 summary->set_out(0, Location::SameAsFirstInput()); |
| 3162 return summary; | 3120 return summary; |
| 3163 } else if (op_kind() == Token::kSHL) { | 3121 } else if (op_kind() == Token::kSHL) { |
| 3164 // Shift-by-1 overflow checking can use flags, otherwise we need a temp. | 3122 // Shift-by-1 overflow checking can use flags, otherwise we need a temp. |
| 3165 const bool shiftBy1 = | 3123 const bool shiftBy1 = |
| 3166 (right_constant != NULL) && IsSmiValue(right_constant->value(), 1); | 3124 (right_constant != NULL) && IsSmiValue(right_constant->value(), 1); |
| 3167 const intptr_t kNumTemps = (can_overflow() && !shiftBy1) ? 1 : 0; | 3125 const intptr_t kNumTemps = (can_overflow() && !shiftBy1) ? 1 : 0; |
| 3168 LocationSummary* summary = new(zone) LocationSummary( | 3126 LocationSummary* summary = new (zone) |
| 3169 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3127 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3170 summary->set_in(0, Location::RequiresRegister()); | 3128 summary->set_in(0, Location::RequiresRegister()); |
| 3171 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 3129 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
| 3172 if (kNumTemps == 1) { | 3130 if (kNumTemps == 1) { |
| 3173 summary->set_temp(0, Location::RequiresRegister()); | 3131 summary->set_temp(0, Location::RequiresRegister()); |
| 3174 } | 3132 } |
| 3175 summary->set_out(0, Location::SameAsFirstInput()); | 3133 summary->set_out(0, Location::SameAsFirstInput()); |
| 3176 return summary; | 3134 return summary; |
| 3177 } else { | 3135 } else { |
| 3178 const intptr_t kNumTemps = 0; | 3136 const intptr_t kNumTemps = 0; |
| 3179 LocationSummary* summary = new(zone) LocationSummary( | 3137 LocationSummary* summary = new (zone) |
| 3180 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3138 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3181 summary->set_in(0, Location::RequiresRegister()); | 3139 summary->set_in(0, Location::RequiresRegister()); |
| 3182 ConstantInstr* constant = right()->definition()->AsConstant(); | 3140 ConstantInstr* constant = right()->definition()->AsConstant(); |
| 3183 if (constant != NULL) { | 3141 if (constant != NULL) { |
| 3184 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | 3142 summary->set_in(1, Location::RegisterOrSmiConstant(right())); |
| 3185 } else { | 3143 } else { |
| 3186 summary->set_in(1, Location::PrefersRegister()); | 3144 summary->set_in(1, Location::PrefersRegister()); |
| 3187 } | 3145 } |
| 3188 summary->set_out(0, Location::SameAsFirstInput()); | 3146 summary->set_out(0, Location::SameAsFirstInput()); |
| 3189 return summary; | 3147 return summary; |
| 3190 } | 3148 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3259 case Token::kBIT_XOR: { | 3217 case Token::kBIT_XOR: { |
| 3260 // No overflow check. | 3218 // No overflow check. |
| 3261 __ XorImmediate(left, Immediate(imm)); | 3219 __ XorImmediate(left, Immediate(imm)); |
| 3262 break; | 3220 break; |
| 3263 } | 3221 } |
| 3264 | 3222 |
| 3265 case Token::kSHR: { | 3223 case Token::kSHR: { |
| 3266 // sarq operation masks the count to 6 bits. | 3224 // sarq operation masks the count to 6 bits. |
| 3267 const intptr_t kCountLimit = 0x3F; | 3225 const intptr_t kCountLimit = 0x3F; |
| 3268 const intptr_t value = Smi::Cast(constant).Value(); | 3226 const intptr_t value = Smi::Cast(constant).Value(); |
| 3269 __ sarq(left, Immediate( | 3227 __ sarq(left, |
| 3270 Utils::Minimum(value + kSmiTagSize, kCountLimit))); | 3228 Immediate(Utils::Minimum(value + kSmiTagSize, kCountLimit))); |
| 3271 __ SmiTag(left); | 3229 __ SmiTag(left); |
| 3272 break; | 3230 break; |
| 3273 } | 3231 } |
| 3274 | 3232 |
| 3275 default: | 3233 default: |
| 3276 UNREACHABLE(); | 3234 UNREACHABLE(); |
| 3277 break; | 3235 break; |
| 3278 } | 3236 } |
| 3279 return; | 3237 return; |
| 3280 } // locs()->in(1).IsConstant(). | 3238 } // locs()->in(1).IsConstant(). |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3386 __ SmiUntag(right); | 3344 __ SmiUntag(right); |
| 3387 __ cdq(); | 3345 __ cdq(); |
| 3388 __ idivl(right); | 3346 __ idivl(right); |
| 3389 __ movsxd(result, result); | 3347 __ movsxd(result, result); |
| 3390 __ jmp(&done); | 3348 __ jmp(&done); |
| 3391 | 3349 |
| 3392 // Divide using 64bit idiv. | 3350 // Divide using 64bit idiv. |
| 3393 __ Bind(¬_32bit); | 3351 __ Bind(¬_32bit); |
| 3394 __ SmiUntag(left); | 3352 __ SmiUntag(left); |
| 3395 __ SmiUntag(right); | 3353 __ SmiUntag(right); |
| 3396 __ cqo(); // Sign extend RAX -> RDX:RAX. | 3354 __ cqo(); // Sign extend RAX -> RDX:RAX. |
| 3397 __ idivq(right); // RAX: quotient, RDX: remainder. | 3355 __ idivq(right); // RAX: quotient, RDX: remainder. |
| 3398 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 3356 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 3399 // case we cannot tag the result. | 3357 // case we cannot tag the result. |
| 3400 __ CompareImmediate(result, Immediate(0x4000000000000000)); | 3358 __ CompareImmediate(result, Immediate(0x4000000000000000)); |
| 3401 __ j(EQUAL, deopt); | 3359 __ j(EQUAL, deopt); |
| 3402 __ Bind(&done); | 3360 __ Bind(&done); |
| 3403 __ SmiTag(result); | 3361 __ SmiTag(result); |
| 3404 break; | 3362 break; |
| 3405 } | 3363 } |
| 3406 case Token::kMOD: { | 3364 case Token::kMOD: { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3434 __ cdq(); | 3392 __ cdq(); |
| 3435 __ idivl(right); | 3393 __ idivl(right); |
| 3436 __ movsxd(result, result); | 3394 __ movsxd(result, result); |
| 3437 __ jmp(&div_done); | 3395 __ jmp(&div_done); |
| 3438 | 3396 |
| 3439 // Divide using 64bit idiv. | 3397 // Divide using 64bit idiv. |
| 3440 __ Bind(¬_32bit); | 3398 __ Bind(¬_32bit); |
| 3441 __ SmiUntag(left); | 3399 __ SmiUntag(left); |
| 3442 __ SmiUntag(right); | 3400 __ SmiUntag(right); |
| 3443 __ movq(RAX, RDX); | 3401 __ movq(RAX, RDX); |
| 3444 __ cqo(); // Sign extend RAX -> RDX:RAX. | 3402 __ cqo(); // Sign extend RAX -> RDX:RAX. |
| 3445 __ idivq(right); // RAX: quotient, RDX: remainder. | 3403 __ idivq(right); // RAX: quotient, RDX: remainder. |
| 3446 __ Bind(&div_done); | 3404 __ Bind(&div_done); |
| 3447 // res = left % right; | 3405 // res = left % right; |
| 3448 // if (res < 0) { | 3406 // if (res < 0) { |
| 3449 // if (right < 0) { | 3407 // if (right < 0) { |
| 3450 // res = res - right; | 3408 // res = res - right; |
| 3451 // } else { | 3409 // } else { |
| 3452 // res = res + right; | 3410 // res = res + right; |
| 3453 // } | 3411 // } |
| 3454 // } | 3412 // } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3516 } | 3474 } |
| 3517 } | 3475 } |
| 3518 | 3476 |
| 3519 | 3477 |
| 3520 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, | 3478 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone, |
| 3521 bool opt) const { | 3479 bool opt) const { |
| 3522 intptr_t left_cid = left()->Type()->ToCid(); | 3480 intptr_t left_cid = left()->Type()->ToCid(); |
| 3523 intptr_t right_cid = right()->Type()->ToCid(); | 3481 intptr_t right_cid = right()->Type()->ToCid(); |
| 3524 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3482 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
| 3525 const intptr_t kNumInputs = 2; | 3483 const intptr_t kNumInputs = 2; |
| 3526 const bool need_temp = (left()->definition() != right()->definition()) | 3484 const bool need_temp = (left()->definition() != right()->definition()) && |
| 3527 && (left_cid != kSmiCid) | 3485 (left_cid != kSmiCid) && (right_cid != kSmiCid); |
| 3528 && (right_cid != kSmiCid); | |
| 3529 const intptr_t kNumTemps = need_temp ? 1 : 0; | 3486 const intptr_t kNumTemps = need_temp ? 1 : 0; |
| 3530 LocationSummary* summary = new(zone) LocationSummary( | 3487 LocationSummary* summary = new (zone) |
| 3531 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3488 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3532 summary->set_in(0, Location::RequiresRegister()); | 3489 summary->set_in(0, Location::RequiresRegister()); |
| 3533 summary->set_in(1, Location::RequiresRegister()); | 3490 summary->set_in(1, Location::RequiresRegister()); |
| 3534 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); | 3491 if (need_temp) summary->set_temp(0, Location::RequiresRegister()); |
| 3535 return summary; | 3492 return summary; |
| 3536 } | 3493 } |
| 3537 | 3494 |
| 3538 | 3495 |
| 3539 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3496 void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3540 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 3497 Label* deopt = |
| 3541 ICData::kDeoptBinaryDoubleOp, | 3498 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryDoubleOp, |
| 3542 licm_hoisted_ ? ICData::kHoisted : 0); | 3499 licm_hoisted_ ? ICData::kHoisted : 0); |
| 3543 intptr_t left_cid = left()->Type()->ToCid(); | 3500 intptr_t left_cid = left()->Type()->ToCid(); |
| 3544 intptr_t right_cid = right()->Type()->ToCid(); | 3501 intptr_t right_cid = right()->Type()->ToCid(); |
| 3545 Register left = locs()->in(0).reg(); | 3502 Register left = locs()->in(0).reg(); |
| 3546 Register right = locs()->in(1).reg(); | 3503 Register right = locs()->in(1).reg(); |
| 3547 if (this->left()->definition() == this->right()->definition()) { | 3504 if (this->left()->definition() == this->right()->definition()) { |
| 3548 __ testq(left, Immediate(kSmiTagMask)); | 3505 __ testq(left, Immediate(kSmiTagMask)); |
| 3549 } else if (left_cid == kSmiCid) { | 3506 } else if (left_cid == kSmiCid) { |
| 3550 __ testq(right, Immediate(kSmiTagMask)); | 3507 __ testq(right, Immediate(kSmiTagMask)); |
| 3551 } else if (right_cid == kSmiCid) { | 3508 } else if (right_cid == kSmiCid) { |
| 3552 __ testq(left, Immediate(kSmiTagMask)); | 3509 __ testq(left, Immediate(kSmiTagMask)); |
| 3553 } else { | 3510 } else { |
| 3554 Register temp = locs()->temp(0).reg(); | 3511 Register temp = locs()->temp(0).reg(); |
| 3555 __ movq(temp, left); | 3512 __ movq(temp, left); |
| 3556 __ orq(temp, right); | 3513 __ orq(temp, right); |
| 3557 __ testq(temp, Immediate(kSmiTagMask)); | 3514 __ testq(temp, Immediate(kSmiTagMask)); |
| 3558 } | 3515 } |
| 3559 __ j(ZERO, deopt); | 3516 __ j(ZERO, deopt); |
| 3560 } | 3517 } |
| 3561 | 3518 |
| 3562 | 3519 |
| 3563 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, | 3520 LocationSummary* BoxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3564 bool opt) const { | |
| 3565 const intptr_t kNumInputs = 1; | 3521 const intptr_t kNumInputs = 1; |
| 3566 const intptr_t kNumTemps = 1; | 3522 const intptr_t kNumTemps = 1; |
| 3567 LocationSummary* summary = new(zone) LocationSummary( | 3523 LocationSummary* summary = new (zone) LocationSummary( |
| 3568 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 3524 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 3569 summary->set_in(0, Location::RequiresFpuRegister()); | 3525 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3570 summary->set_temp(0, Location::RequiresRegister()); | 3526 summary->set_temp(0, Location::RequiresRegister()); |
| 3571 summary->set_out(0, Location::RequiresRegister()); | 3527 summary->set_out(0, Location::RequiresRegister()); |
| 3572 return summary; | 3528 return summary; |
| 3573 } | 3529 } |
| 3574 | 3530 |
| 3575 | 3531 |
| 3576 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3532 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3577 Register out_reg = locs()->out(0).reg(); | 3533 Register out_reg = locs()->out(0).reg(); |
| 3578 Register temp = locs()->temp(0).reg(); | 3534 Register temp = locs()->temp(0).reg(); |
| 3579 XmmRegister value = locs()->in(0).fpu_reg(); | 3535 XmmRegister value = locs()->in(0).fpu_reg(); |
| 3580 | 3536 |
| 3581 BoxAllocationSlowPath::Allocate( | 3537 BoxAllocationSlowPath::Allocate(compiler, this, |
| 3582 compiler, this, compiler->BoxClassFor(from_representation()), out_reg, | 3538 compiler->BoxClassFor(from_representation()), |
| 3583 temp); | 3539 out_reg, temp); |
| 3584 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); | 3540 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); |
| 3585 switch (from_representation()) { | 3541 switch (from_representation()) { |
| 3586 case kUnboxedDouble: | 3542 case kUnboxedDouble: |
| 3587 __ movsd(FieldAddress(out_reg, ValueOffset()), value); | 3543 __ movsd(FieldAddress(out_reg, ValueOffset()), value); |
| 3588 break; | 3544 break; |
| 3589 case kUnboxedFloat32x4: | 3545 case kUnboxedFloat32x4: |
| 3590 case kUnboxedFloat64x2: | 3546 case kUnboxedFloat64x2: |
| 3591 case kUnboxedInt32x4: | 3547 case kUnboxedInt32x4: |
| 3592 __ movups(FieldAddress(out_reg, ValueOffset()), value); | 3548 __ movups(FieldAddress(out_reg, ValueOffset()), value); |
| 3593 break; | 3549 break; |
| 3594 default: | 3550 default: |
| 3595 UNREACHABLE(); | 3551 UNREACHABLE(); |
| 3596 break; | 3552 break; |
| 3597 } | 3553 } |
| 3598 } | 3554 } |
| 3599 | 3555 |
| 3600 | 3556 |
| 3601 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, | 3557 LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 3602 bool opt) const { | |
| 3603 const intptr_t kNumInputs = 1; | 3558 const intptr_t kNumInputs = 1; |
| 3604 const intptr_t kNumTemps = 0; | 3559 const intptr_t kNumTemps = 0; |
| 3605 const bool needs_writable_input = | 3560 const bool needs_writable_input = |
| 3606 (representation() != kUnboxedMint) && | 3561 (representation() != kUnboxedMint) && |
| 3607 (value()->Type()->ToNullableCid() != BoxCid()); | 3562 (value()->Type()->ToNullableCid() != BoxCid()); |
| 3608 LocationSummary* summary = new(zone) LocationSummary( | 3563 LocationSummary* summary = new (zone) |
| 3609 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3564 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3610 summary->set_in(0, needs_writable_input ? Location::WritableRegister() | 3565 summary->set_in(0, needs_writable_input ? Location::WritableRegister() |
| 3611 : Location::RequiresRegister()); | 3566 : Location::RequiresRegister()); |
| 3612 if (representation() == kUnboxedMint) { | 3567 if (representation() == kUnboxedMint) { |
| 3613 summary->set_out(0, Location::SameAsFirstInput()); | 3568 summary->set_out(0, Location::SameAsFirstInput()); |
| 3614 } else { | 3569 } else { |
| 3615 summary->set_out(0, Location::RequiresFpuRegister()); | 3570 summary->set_out(0, Location::RequiresFpuRegister()); |
| 3616 } | 3571 } |
| 3617 return summary; | 3572 return summary; |
| 3618 } | 3573 } |
| 3619 | 3574 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3677 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3632 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3678 const intptr_t value_cid = value()->Type()->ToCid(); | 3633 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3679 const intptr_t box_cid = BoxCid(); | 3634 const intptr_t box_cid = BoxCid(); |
| 3680 | 3635 |
| 3681 if (value_cid == box_cid) { | 3636 if (value_cid == box_cid) { |
| 3682 EmitLoadFromBox(compiler); | 3637 EmitLoadFromBox(compiler); |
| 3683 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { | 3638 } else if (CanConvertSmi() && (value_cid == kSmiCid)) { |
| 3684 EmitSmiConversion(compiler); | 3639 EmitSmiConversion(compiler); |
| 3685 } else { | 3640 } else { |
| 3686 const Register box = locs()->in(0).reg(); | 3641 const Register box = locs()->in(0).reg(); |
| 3687 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), | 3642 Label* deopt = |
| 3688 ICData::kDeoptCheckClass); | 3643 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass); |
| 3689 Label is_smi; | 3644 Label is_smi; |
| 3690 | 3645 |
| 3691 if ((value()->Type()->ToNullableCid() == box_cid) && | 3646 if ((value()->Type()->ToNullableCid() == box_cid) && |
| 3692 value()->Type()->is_nullable()) { | 3647 value()->Type()->is_nullable()) { |
| 3693 __ CompareObject(box, Object::null_object()); | 3648 __ CompareObject(box, Object::null_object()); |
| 3694 __ j(EQUAL, deopt); | 3649 __ j(EQUAL, deopt); |
| 3695 } else { | 3650 } else { |
| 3696 __ testq(box, Immediate(kSmiTagMask)); | 3651 __ testq(box, Immediate(kSmiTagMask)); |
| 3697 __ j(ZERO, CanConvertSmi() ? &is_smi : deopt); | 3652 __ j(ZERO, CanConvertSmi() ? &is_smi : deopt); |
| 3698 __ CompareClassId(box, box_cid); | 3653 __ CompareClassId(box, box_cid); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3709 __ Bind(&done); | 3664 __ Bind(&done); |
| 3710 } | 3665 } |
| 3711 } | 3666 } |
| 3712 } | 3667 } |
| 3713 | 3668 |
| 3714 | 3669 |
| 3715 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, | 3670 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 3716 bool opt) const { | 3671 bool opt) const { |
| 3717 const intptr_t kNumInputs = 1; | 3672 const intptr_t kNumInputs = 1; |
| 3718 const intptr_t kNumTemps = (!is_truncating() && CanDeoptimize()) ? 1 : 0; | 3673 const intptr_t kNumTemps = (!is_truncating() && CanDeoptimize()) ? 1 : 0; |
| 3719 LocationSummary* summary = new(zone) LocationSummary( | 3674 LocationSummary* summary = new (zone) |
| 3720 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3675 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3721 summary->set_in(0, Location::RequiresRegister()); | 3676 summary->set_in(0, Location::RequiresRegister()); |
| 3722 summary->set_out(0, Location::SameAsFirstInput()); | 3677 summary->set_out(0, Location::SameAsFirstInput()); |
| 3723 if (kNumTemps > 0) { | 3678 if (kNumTemps > 0) { |
| 3724 summary->set_temp(0, Location::RequiresRegister()); | 3679 summary->set_temp(0, Location::RequiresRegister()); |
| 3725 } | 3680 } |
| 3726 return summary; | 3681 return summary; |
| 3727 } | 3682 } |
| 3728 | 3683 |
| 3729 | 3684 |
| 3730 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3685 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3731 const intptr_t value_cid = value()->Type()->ToCid(); | 3686 const intptr_t value_cid = value()->Type()->ToCid(); |
| 3732 const Register value = locs()->in(0).reg(); | 3687 const Register value = locs()->in(0).reg(); |
| 3733 Label* deopt = CanDeoptimize() ? | 3688 Label* deopt = |
| 3734 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL; | 3689 CanDeoptimize() |
| 3690 ? compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) |
| 3691 : NULL; |
| 3735 ASSERT(value == locs()->out(0).reg()); | 3692 ASSERT(value == locs()->out(0).reg()); |
| 3736 | 3693 |
| 3737 if (value_cid == kSmiCid) { | 3694 if (value_cid == kSmiCid) { |
| 3738 __ SmiUntag(value); | 3695 __ SmiUntag(value); |
| 3739 } else if (value_cid == kMintCid) { | 3696 } else if (value_cid == kMintCid) { |
| 3740 __ movq(value, FieldAddress(value, Mint::value_offset())); | 3697 __ movq(value, FieldAddress(value, Mint::value_offset())); |
| 3741 } else if (!CanDeoptimize()) { | 3698 } else if (!CanDeoptimize()) { |
| 3742 // Type information is not conclusive, but range analysis found | 3699 // Type information is not conclusive, but range analysis found |
| 3743 // the value to be in int64 range. Therefore it must be a smi | 3700 // the value to be in int64 range. Therefore it must be a smi |
| 3744 // or mint value. | 3701 // or mint value. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3765 ASSERT(representation() == kUnboxedInt32); | 3722 ASSERT(representation() == kUnboxedInt32); |
| 3766 Register temp = locs()->temp(0).reg(); | 3723 Register temp = locs()->temp(0).reg(); |
| 3767 __ movsxd(temp, value); | 3724 __ movsxd(temp, value); |
| 3768 __ cmpq(temp, value); | 3725 __ cmpq(temp, value); |
| 3769 __ j(NOT_EQUAL, deopt); | 3726 __ j(NOT_EQUAL, deopt); |
| 3770 } | 3727 } |
| 3771 } | 3728 } |
| 3772 | 3729 |
| 3773 | 3730 |
| 3774 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, | 3731 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone, |
| 3775 bool opt) const { | 3732 bool opt) const { |
| 3776 ASSERT((from_representation() == kUnboxedInt32) || | 3733 ASSERT((from_representation() == kUnboxedInt32) || |
| 3777 (from_representation() == kUnboxedUint32)); | 3734 (from_representation() == kUnboxedUint32)); |
| 3778 const intptr_t kNumInputs = 1; | 3735 const intptr_t kNumInputs = 1; |
| 3779 const intptr_t kNumTemps = 0; | 3736 const intptr_t kNumTemps = 0; |
| 3780 LocationSummary* summary = new(zone) LocationSummary( | 3737 LocationSummary* summary = new (zone) |
| 3781 zone, | 3738 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3782 kNumInputs, | |
| 3783 kNumTemps, | |
| 3784 LocationSummary::kNoCall); | |
| 3785 summary->set_in(0, Location::RequiresRegister()); | 3739 summary->set_in(0, Location::RequiresRegister()); |
| 3786 summary->set_out(0, Location::RequiresRegister()); | 3740 summary->set_out(0, Location::RequiresRegister()); |
| 3787 return summary; | 3741 return summary; |
| 3788 } | 3742 } |
| 3789 | 3743 |
| 3790 | 3744 |
| 3791 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3745 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3792 const Register value = locs()->in(0).reg(); | 3746 const Register value = locs()->in(0).reg(); |
| 3793 const Register out = locs()->out(0).reg(); | 3747 const Register out = locs()->out(0).reg(); |
| 3794 ASSERT(value != out); | 3748 ASSERT(value != out); |
| 3795 | 3749 |
| 3796 ASSERT(kSmiTagSize == 1); | 3750 ASSERT(kSmiTagSize == 1); |
| 3797 if (from_representation() == kUnboxedInt32) { | 3751 if (from_representation() == kUnboxedInt32) { |
| 3798 __ movsxd(out, value); | 3752 __ movsxd(out, value); |
| 3799 } else { | 3753 } else { |
| 3800 ASSERT(from_representation() == kUnboxedUint32); | 3754 ASSERT(from_representation() == kUnboxedUint32); |
| 3801 __ movl(out, value); | 3755 __ movl(out, value); |
| 3802 } | 3756 } |
| 3803 __ SmiTag(out); | 3757 __ SmiTag(out); |
| 3804 } | 3758 } |
| 3805 | 3759 |
| 3806 | 3760 |
| 3807 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, | 3761 LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone, |
| 3808 bool opt) const { | 3762 bool opt) const { |
| 3809 const intptr_t kNumInputs = 1; | 3763 const intptr_t kNumInputs = 1; |
| 3810 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | 3764 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; |
| 3811 LocationSummary* summary = new(zone) LocationSummary( | 3765 LocationSummary* summary = new (zone) |
| 3812 zone, | 3766 LocationSummary(zone, kNumInputs, kNumTemps, |
| 3813 kNumInputs, | 3767 ValueFitsSmi() ? LocationSummary::kNoCall |
| 3814 kNumTemps, | 3768 : LocationSummary::kCallOnSlowPath); |
| 3815 ValueFitsSmi() ? LocationSummary::kNoCall | |
| 3816 : LocationSummary::kCallOnSlowPath); | |
| 3817 summary->set_in(0, Location::RequiresRegister()); | 3769 summary->set_in(0, Location::RequiresRegister()); |
| 3818 if (!ValueFitsSmi()) { | 3770 if (!ValueFitsSmi()) { |
| 3819 summary->set_temp(0, Location::RequiresRegister()); | 3771 summary->set_temp(0, Location::RequiresRegister()); |
| 3820 } | 3772 } |
| 3821 summary->set_out(0, Location::RequiresRegister()); | 3773 summary->set_out(0, Location::RequiresRegister()); |
| 3822 return summary; | 3774 return summary; |
| 3823 } | 3775 } |
| 3824 | 3776 |
| 3825 | 3777 |
| 3826 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3778 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3827 const Register out = locs()->out(0).reg(); | 3779 const Register out = locs()->out(0).reg(); |
| 3828 const Register value = locs()->in(0).reg(); | 3780 const Register value = locs()->in(0).reg(); |
| 3829 __ MoveRegister(out, value); | 3781 __ MoveRegister(out, value); |
| 3830 __ SmiTag(out); | 3782 __ SmiTag(out); |
| 3831 if (!ValueFitsSmi()) { | 3783 if (!ValueFitsSmi()) { |
| 3832 const Register temp = locs()->temp(0).reg(); | 3784 const Register temp = locs()->temp(0).reg(); |
| 3833 Label done; | 3785 Label done; |
| 3834 __ j(NO_OVERFLOW, &done); | 3786 __ j(NO_OVERFLOW, &done); |
| 3835 BoxAllocationSlowPath::Allocate( | 3787 BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out, |
| 3836 compiler, this, compiler->mint_class(), out, temp); | 3788 temp); |
| 3837 __ movq(FieldAddress(out, Mint::value_offset()), value); | 3789 __ movq(FieldAddress(out, Mint::value_offset()), value); |
| 3838 __ Bind(&done); | 3790 __ Bind(&done); |
| 3839 } | 3791 } |
| 3840 } | 3792 } |
| 3841 | 3793 |
| 3842 | 3794 |
| 3843 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 3795 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 3844 bool opt) const { | 3796 bool opt) const { |
| 3845 const intptr_t kNumInputs = 2; | 3797 const intptr_t kNumInputs = 2; |
| 3846 const intptr_t kNumTemps = 0; | 3798 const intptr_t kNumTemps = 0; |
| 3847 LocationSummary* summary = new(zone) LocationSummary( | 3799 LocationSummary* summary = new (zone) |
| 3848 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3800 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3849 summary->set_in(0, Location::RequiresFpuRegister()); | 3801 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3850 summary->set_in(1, Location::RequiresFpuRegister()); | 3802 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3851 summary->set_out(0, Location::SameAsFirstInput()); | 3803 summary->set_out(0, Location::SameAsFirstInput()); |
| 3852 return summary; | 3804 return summary; |
| 3853 } | 3805 } |
| 3854 | 3806 |
| 3855 | 3807 |
| 3856 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3808 void BinaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3857 XmmRegister left = locs()->in(0).fpu_reg(); | 3809 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3858 XmmRegister right = locs()->in(1).fpu_reg(); | 3810 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3859 | 3811 |
| 3860 ASSERT(locs()->out(0).fpu_reg() == left); | 3812 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3861 | 3813 |
| 3862 switch (op_kind()) { | 3814 switch (op_kind()) { |
| 3863 case Token::kADD: __ addsd(left, right); break; | 3815 case Token::kADD: |
| 3864 case Token::kSUB: __ subsd(left, right); break; | 3816 __ addsd(left, right); |
| 3865 case Token::kMUL: __ mulsd(left, right); break; | 3817 break; |
| 3866 case Token::kDIV: __ divsd(left, right); break; | 3818 case Token::kSUB: |
| 3867 default: UNREACHABLE(); | 3819 __ subsd(left, right); |
| 3820 break; |
| 3821 case Token::kMUL: |
| 3822 __ mulsd(left, right); |
| 3823 break; |
| 3824 case Token::kDIV: |
| 3825 __ divsd(left, right); |
| 3826 break; |
| 3827 default: |
| 3828 UNREACHABLE(); |
| 3868 } | 3829 } |
| 3869 } | 3830 } |
| 3870 | 3831 |
| 3871 | 3832 |
| 3872 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, | 3833 LocationSummary* DoubleTestOpInstr::MakeLocationSummary(Zone* zone, |
| 3873 bool opt) const { | 3834 bool opt) const { |
| 3874 const intptr_t kNumInputs = 1; | 3835 const intptr_t kNumInputs = 1; |
| 3875 const intptr_t kNumTemps = | 3836 const intptr_t kNumTemps = |
| 3876 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; | 3837 (op_kind() == MethodRecognizer::kDouble_getIsInfinite) ? 1 : 0; |
| 3877 LocationSummary* summary = new(zone) LocationSummary( | 3838 LocationSummary* summary = new (zone) |
| 3878 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3839 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3879 summary->set_in(0, Location::RequiresFpuRegister()); | 3840 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3880 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { | 3841 if (op_kind() == MethodRecognizer::kDouble_getIsInfinite) { |
| 3881 summary->set_temp(0, Location::RequiresRegister()); | 3842 summary->set_temp(0, Location::RequiresRegister()); |
| 3882 } | 3843 } |
| 3883 summary->set_out(0, Location::RequiresRegister()); | 3844 summary->set_out(0, Location::RequiresRegister()); |
| 3884 return summary; | 3845 return summary; |
| 3885 } | 3846 } |
| 3886 | 3847 |
| 3887 | 3848 |
| 3888 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 3849 Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3914 BranchInstr* branch) { | 3875 BranchInstr* branch) { |
| 3915 ASSERT(compiler->is_optimizing()); | 3876 ASSERT(compiler->is_optimizing()); |
| 3916 BranchLabels labels = compiler->CreateBranchLabels(branch); | 3877 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 3917 Condition true_condition = EmitComparisonCode(compiler, labels); | 3878 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3918 EmitBranchOnCondition(compiler, true_condition, labels); | 3879 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3919 } | 3880 } |
| 3920 | 3881 |
| 3921 | 3882 |
| 3922 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3883 void DoubleTestOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3923 Label is_true, is_false; | 3884 Label is_true, is_false; |
| 3924 BranchLabels labels = { &is_true, &is_false, &is_false }; | 3885 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 3925 Condition true_condition = EmitComparisonCode(compiler, labels); | 3886 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 3926 EmitBranchOnCondition(compiler, true_condition, labels); | 3887 EmitBranchOnCondition(compiler, true_condition, labels); |
| 3927 | 3888 |
| 3928 Register result = locs()->out(0).reg(); | 3889 Register result = locs()->out(0).reg(); |
| 3929 Label done; | 3890 Label done; |
| 3930 __ Bind(&is_false); | 3891 __ Bind(&is_false); |
| 3931 __ LoadObject(result, Bool::False()); | 3892 __ LoadObject(result, Bool::False()); |
| 3932 __ jmp(&done); | 3893 __ jmp(&done); |
| 3933 __ Bind(&is_true); | 3894 __ Bind(&is_true); |
| 3934 __ LoadObject(result, Bool::True()); | 3895 __ LoadObject(result, Bool::True()); |
| 3935 __ Bind(&done); | 3896 __ Bind(&done); |
| 3936 } | 3897 } |
| 3937 | 3898 |
| 3938 | 3899 |
| 3939 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, | 3900 LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 3940 bool opt) const { | 3901 bool opt) const { |
| 3941 const intptr_t kNumInputs = 2; | 3902 const intptr_t kNumInputs = 2; |
| 3942 const intptr_t kNumTemps = 0; | 3903 const intptr_t kNumTemps = 0; |
| 3943 LocationSummary* summary = new(zone) LocationSummary( | 3904 LocationSummary* summary = new (zone) |
| 3944 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3905 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3945 summary->set_in(0, Location::RequiresFpuRegister()); | 3906 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3946 summary->set_in(1, Location::RequiresFpuRegister()); | 3907 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3947 summary->set_out(0, Location::SameAsFirstInput()); | 3908 summary->set_out(0, Location::SameAsFirstInput()); |
| 3948 return summary; | 3909 return summary; |
| 3949 } | 3910 } |
| 3950 | 3911 |
| 3951 | 3912 |
| 3952 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3913 void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3953 XmmRegister left = locs()->in(0).fpu_reg(); | 3914 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3954 XmmRegister right = locs()->in(1).fpu_reg(); | 3915 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3955 | 3916 |
| 3956 ASSERT(locs()->out(0).fpu_reg() == left); | 3917 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3957 | 3918 |
| 3958 switch (op_kind()) { | 3919 switch (op_kind()) { |
| 3959 case Token::kADD: __ addps(left, right); break; | 3920 case Token::kADD: |
| 3960 case Token::kSUB: __ subps(left, right); break; | 3921 __ addps(left, right); |
| 3961 case Token::kMUL: __ mulps(left, right); break; | 3922 break; |
| 3962 case Token::kDIV: __ divps(left, right); break; | 3923 case Token::kSUB: |
| 3963 default: UNREACHABLE(); | 3924 __ subps(left, right); |
| 3925 break; |
| 3926 case Token::kMUL: |
| 3927 __ mulps(left, right); |
| 3928 break; |
| 3929 case Token::kDIV: |
| 3930 __ divps(left, right); |
| 3931 break; |
| 3932 default: |
| 3933 UNREACHABLE(); |
| 3964 } | 3934 } |
| 3965 } | 3935 } |
| 3966 | 3936 |
| 3967 | 3937 |
| 3968 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, | 3938 LocationSummary* BinaryFloat64x2OpInstr::MakeLocationSummary(Zone* zone, |
| 3969 bool opt) const { | 3939 bool opt) const { |
| 3970 const intptr_t kNumInputs = 2; | 3940 const intptr_t kNumInputs = 2; |
| 3971 const intptr_t kNumTemps = 0; | 3941 const intptr_t kNumTemps = 0; |
| 3972 LocationSummary* summary = new(zone) LocationSummary( | 3942 LocationSummary* summary = new (zone) |
| 3973 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3943 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3974 summary->set_in(0, Location::RequiresFpuRegister()); | 3944 summary->set_in(0, Location::RequiresFpuRegister()); |
| 3975 summary->set_in(1, Location::RequiresFpuRegister()); | 3945 summary->set_in(1, Location::RequiresFpuRegister()); |
| 3976 summary->set_out(0, Location::SameAsFirstInput()); | 3946 summary->set_out(0, Location::SameAsFirstInput()); |
| 3977 return summary; | 3947 return summary; |
| 3978 } | 3948 } |
| 3979 | 3949 |
| 3980 | 3950 |
| 3981 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3951 void BinaryFloat64x2OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3982 XmmRegister left = locs()->in(0).fpu_reg(); | 3952 XmmRegister left = locs()->in(0).fpu_reg(); |
| 3983 XmmRegister right = locs()->in(1).fpu_reg(); | 3953 XmmRegister right = locs()->in(1).fpu_reg(); |
| 3984 | 3954 |
| 3985 ASSERT(locs()->out(0).fpu_reg() == left); | 3955 ASSERT(locs()->out(0).fpu_reg() == left); |
| 3986 | 3956 |
| 3987 switch (op_kind()) { | 3957 switch (op_kind()) { |
| 3988 case Token::kADD: __ addpd(left, right); break; | 3958 case Token::kADD: |
| 3989 case Token::kSUB: __ subpd(left, right); break; | 3959 __ addpd(left, right); |
| 3990 case Token::kMUL: __ mulpd(left, right); break; | 3960 break; |
| 3991 case Token::kDIV: __ divpd(left, right); break; | 3961 case Token::kSUB: |
| 3992 default: UNREACHABLE(); | 3962 __ subpd(left, right); |
| 3963 break; |
| 3964 case Token::kMUL: |
| 3965 __ mulpd(left, right); |
| 3966 break; |
| 3967 case Token::kDIV: |
| 3968 __ divpd(left, right); |
| 3969 break; |
| 3970 default: |
| 3971 UNREACHABLE(); |
| 3993 } | 3972 } |
| 3994 } | 3973 } |
| 3995 | 3974 |
| 3996 | 3975 |
| 3997 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, | 3976 LocationSummary* Simd32x4ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 3998 bool opt) const { | 3977 bool opt) const { |
| 3999 const intptr_t kNumInputs = 1; | 3978 const intptr_t kNumInputs = 1; |
| 4000 const intptr_t kNumTemps = 0; | 3979 const intptr_t kNumTemps = 0; |
| 4001 LocationSummary* summary = new(zone) LocationSummary( | 3980 LocationSummary* summary = new (zone) |
| 4002 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3981 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4003 summary->set_in(0, Location::RequiresFpuRegister()); | 3982 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4004 summary->set_out(0, Location::SameAsFirstInput()); | 3983 summary->set_out(0, Location::SameAsFirstInput()); |
| 4005 return summary; | 3984 return summary; |
| 4006 } | 3985 } |
| 4007 | 3986 |
| 4008 | 3987 |
| 4009 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3988 void Simd32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4010 XmmRegister value = locs()->in(0).fpu_reg(); | 3989 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4011 | 3990 |
| 4012 ASSERT(locs()->out(0).fpu_reg() == value); | 3991 ASSERT(locs()->out(0).fpu_reg() == value); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4025 __ cvtss2sd(value, value); | 4004 __ cvtss2sd(value, value); |
| 4026 break; | 4005 break; |
| 4027 case MethodRecognizer::kFloat32x4ShuffleW: | 4006 case MethodRecognizer::kFloat32x4ShuffleW: |
| 4028 __ shufps(value, value, Immediate(0xFF)); | 4007 __ shufps(value, value, Immediate(0xFF)); |
| 4029 __ cvtss2sd(value, value); | 4008 __ cvtss2sd(value, value); |
| 4030 break; | 4009 break; |
| 4031 case MethodRecognizer::kFloat32x4Shuffle: | 4010 case MethodRecognizer::kFloat32x4Shuffle: |
| 4032 case MethodRecognizer::kInt32x4Shuffle: | 4011 case MethodRecognizer::kInt32x4Shuffle: |
| 4033 __ shufps(value, value, Immediate(mask_)); | 4012 __ shufps(value, value, Immediate(mask_)); |
| 4034 break; | 4013 break; |
| 4035 default: UNREACHABLE(); | 4014 default: |
| 4015 UNREACHABLE(); |
| 4036 } | 4016 } |
| 4037 } | 4017 } |
| 4038 | 4018 |
| 4039 | 4019 |
| 4040 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, | 4020 LocationSummary* Simd32x4ShuffleMixInstr::MakeLocationSummary(Zone* zone, |
| 4041 bool opt) const { | 4021 bool opt) const { |
| 4042 const intptr_t kNumInputs = 2; | 4022 const intptr_t kNumInputs = 2; |
| 4043 const intptr_t kNumTemps = 0; | 4023 const intptr_t kNumTemps = 0; |
| 4044 LocationSummary* summary = new(zone) LocationSummary( | 4024 LocationSummary* summary = new (zone) |
| 4045 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4025 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4046 summary->set_in(0, Location::RequiresFpuRegister()); | 4026 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4047 summary->set_in(1, Location::RequiresFpuRegister()); | 4027 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4048 summary->set_out(0, Location::SameAsFirstInput()); | 4028 summary->set_out(0, Location::SameAsFirstInput()); |
| 4049 return summary; | 4029 return summary; |
| 4050 } | 4030 } |
| 4051 | 4031 |
| 4052 | 4032 |
| 4053 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4033 void Simd32x4ShuffleMixInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4054 XmmRegister left = locs()->in(0).fpu_reg(); | 4034 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4055 XmmRegister right = locs()->in(1).fpu_reg(); | 4035 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4056 | 4036 |
| 4057 ASSERT(locs()->out(0).fpu_reg() == left); | 4037 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4058 switch (op_kind()) { | 4038 switch (op_kind()) { |
| 4059 case MethodRecognizer::kFloat32x4ShuffleMix: | 4039 case MethodRecognizer::kFloat32x4ShuffleMix: |
| 4060 case MethodRecognizer::kInt32x4ShuffleMix: | 4040 case MethodRecognizer::kInt32x4ShuffleMix: |
| 4061 __ shufps(left, right, Immediate(mask_)); | 4041 __ shufps(left, right, Immediate(mask_)); |
| 4062 break; | 4042 break; |
| 4063 default: UNREACHABLE(); | 4043 default: |
| 4044 UNREACHABLE(); |
| 4064 } | 4045 } |
| 4065 } | 4046 } |
| 4066 | 4047 |
| 4067 | 4048 |
| 4068 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, | 4049 LocationSummary* Simd32x4GetSignMaskInstr::MakeLocationSummary(Zone* zone, |
| 4069 bool opt) const { | 4050 bool opt) const { |
| 4070 const intptr_t kNumInputs = 1; | 4051 const intptr_t kNumInputs = 1; |
| 4071 const intptr_t kNumTemps = 0; | 4052 const intptr_t kNumTemps = 0; |
| 4072 LocationSummary* summary = new(zone) LocationSummary( | 4053 LocationSummary* summary = new (zone) |
| 4073 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4054 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4074 summary->set_in(0, Location::RequiresFpuRegister()); | 4055 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4075 summary->set_out(0, Location::RequiresRegister()); | 4056 summary->set_out(0, Location::RequiresRegister()); |
| 4076 return summary; | 4057 return summary; |
| 4077 } | 4058 } |
| 4078 | 4059 |
| 4079 | 4060 |
| 4080 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4061 void Simd32x4GetSignMaskInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4081 XmmRegister value = locs()->in(0).fpu_reg(); | 4062 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4082 Register out = locs()->out(0).reg(); | 4063 Register out = locs()->out(0).reg(); |
| 4083 | 4064 |
| 4084 __ movmskps(out, value); | 4065 __ movmskps(out, value); |
| 4085 __ SmiTag(out); | 4066 __ SmiTag(out); |
| 4086 } | 4067 } |
| 4087 | 4068 |
| 4088 | 4069 |
| 4089 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( | 4070 LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary( |
| 4090 Zone* zone, bool opt) const { | 4071 Zone* zone, |
| 4072 bool opt) const { |
| 4091 const intptr_t kNumInputs = 4; | 4073 const intptr_t kNumInputs = 4; |
| 4092 const intptr_t kNumTemps = 0; | 4074 const intptr_t kNumTemps = 0; |
| 4093 LocationSummary* summary = new(zone) LocationSummary( | 4075 LocationSummary* summary = new (zone) |
| 4094 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4076 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4095 summary->set_in(0, Location::RequiresFpuRegister()); | 4077 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4096 summary->set_in(1, Location::RequiresFpuRegister()); | 4078 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4097 summary->set_in(2, Location::RequiresFpuRegister()); | 4079 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4098 summary->set_in(3, Location::RequiresFpuRegister()); | 4080 summary->set_in(3, Location::RequiresFpuRegister()); |
| 4099 summary->set_out(0, Location::SameAsFirstInput()); | 4081 summary->set_out(0, Location::SameAsFirstInput()); |
| 4100 return summary; | 4082 return summary; |
| 4101 } | 4083 } |
| 4102 | 4084 |
| 4103 | 4085 |
| 4104 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4086 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 4121 __ movss(Address(RSP, 12), v0); | 4103 __ movss(Address(RSP, 12), v0); |
| 4122 __ movups(v0, Address(RSP, 0)); | 4104 __ movups(v0, Address(RSP, 0)); |
| 4123 __ AddImmediate(RSP, Immediate(16)); | 4105 __ AddImmediate(RSP, Immediate(16)); |
| 4124 } | 4106 } |
| 4125 | 4107 |
| 4126 | 4108 |
| 4127 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, | 4109 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, |
| 4128 bool opt) const { | 4110 bool opt) const { |
| 4129 const intptr_t kNumInputs = 0; | 4111 const intptr_t kNumInputs = 0; |
| 4130 const intptr_t kNumTemps = 0; | 4112 const intptr_t kNumTemps = 0; |
| 4131 LocationSummary* summary = new(zone) LocationSummary( | 4113 LocationSummary* summary = new (zone) |
| 4132 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4114 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4133 summary->set_out(0, Location::RequiresFpuRegister()); | 4115 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4134 return summary; | 4116 return summary; |
| 4135 } | 4117 } |
| 4136 | 4118 |
| 4137 | 4119 |
| 4138 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4120 void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4139 XmmRegister value = locs()->out(0).fpu_reg(); | 4121 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4140 __ xorps(value, value); | 4122 __ xorps(value, value); |
| 4141 } | 4123 } |
| 4142 | 4124 |
| 4143 | 4125 |
| 4144 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, | 4126 LocationSummary* Float32x4SplatInstr::MakeLocationSummary(Zone* zone, |
| 4145 bool opt) const { | 4127 bool opt) const { |
| 4146 const intptr_t kNumInputs = 1; | 4128 const intptr_t kNumInputs = 1; |
| 4147 const intptr_t kNumTemps = 0; | 4129 const intptr_t kNumTemps = 0; |
| 4148 LocationSummary* summary = new(zone) LocationSummary( | 4130 LocationSummary* summary = new (zone) |
| 4149 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4131 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4150 summary->set_in(0, Location::RequiresFpuRegister()); | 4132 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4151 summary->set_out(0, Location::SameAsFirstInput()); | 4133 summary->set_out(0, Location::SameAsFirstInput()); |
| 4152 return summary; | 4134 return summary; |
| 4153 } | 4135 } |
| 4154 | 4136 |
| 4155 | 4137 |
| 4156 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4138 void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4157 XmmRegister value = locs()->out(0).fpu_reg(); | 4139 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4158 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); | 4140 ASSERT(locs()->in(0).fpu_reg() == locs()->out(0).fpu_reg()); |
| 4159 // Convert to Float32. | 4141 // Convert to Float32. |
| 4160 __ cvtsd2ss(value, value); | 4142 __ cvtsd2ss(value, value); |
| 4161 // Splat across all lanes. | 4143 // Splat across all lanes. |
| 4162 __ shufps(value, value, Immediate(0x00)); | 4144 __ shufps(value, value, Immediate(0x00)); |
| 4163 } | 4145 } |
| 4164 | 4146 |
| 4165 | 4147 |
| 4166 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, | 4148 LocationSummary* Float32x4ComparisonInstr::MakeLocationSummary(Zone* zone, |
| 4167 bool opt) const { | 4149 bool opt) const { |
| 4168 const intptr_t kNumInputs = 2; | 4150 const intptr_t kNumInputs = 2; |
| 4169 const intptr_t kNumTemps = 0; | 4151 const intptr_t kNumTemps = 0; |
| 4170 LocationSummary* summary = new(zone) LocationSummary( | 4152 LocationSummary* summary = new (zone) |
| 4171 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4153 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4172 summary->set_in(0, Location::RequiresFpuRegister()); | 4154 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4173 summary->set_in(1, Location::RequiresFpuRegister()); | 4155 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4174 summary->set_out(0, Location::SameAsFirstInput()); | 4156 summary->set_out(0, Location::SameAsFirstInput()); |
| 4175 return summary; | 4157 return summary; |
| 4176 } | 4158 } |
| 4177 | 4159 |
| 4178 | 4160 |
| 4179 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4161 void Float32x4ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4180 XmmRegister left = locs()->in(0).fpu_reg(); | 4162 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4181 XmmRegister right = locs()->in(1).fpu_reg(); | 4163 XmmRegister right = locs()->in(1).fpu_reg(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4195 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: | 4177 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: |
| 4196 __ cmppsnlt(left, right); | 4178 __ cmppsnlt(left, right); |
| 4197 break; | 4179 break; |
| 4198 case MethodRecognizer::kFloat32x4LessThan: | 4180 case MethodRecognizer::kFloat32x4LessThan: |
| 4199 __ cmppslt(left, right); | 4181 __ cmppslt(left, right); |
| 4200 break; | 4182 break; |
| 4201 case MethodRecognizer::kFloat32x4LessThanOrEqual: | 4183 case MethodRecognizer::kFloat32x4LessThanOrEqual: |
| 4202 __ cmppsle(left, right); | 4184 __ cmppsle(left, right); |
| 4203 break; | 4185 break; |
| 4204 | 4186 |
| 4205 default: UNREACHABLE(); | 4187 default: |
| 4188 UNREACHABLE(); |
| 4206 } | 4189 } |
| 4207 } | 4190 } |
| 4208 | 4191 |
| 4209 | 4192 |
| 4210 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, | 4193 LocationSummary* Float32x4MinMaxInstr::MakeLocationSummary(Zone* zone, |
| 4211 bool opt) const { | 4194 bool opt) const { |
| 4212 const intptr_t kNumInputs = 2; | 4195 const intptr_t kNumInputs = 2; |
| 4213 const intptr_t kNumTemps = 0; | 4196 const intptr_t kNumTemps = 0; |
| 4214 LocationSummary* summary = new(zone) LocationSummary( | 4197 LocationSummary* summary = new (zone) |
| 4215 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4198 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4216 summary->set_in(0, Location::RequiresFpuRegister()); | 4199 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4217 summary->set_in(1, Location::RequiresFpuRegister()); | 4200 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4218 summary->set_out(0, Location::SameAsFirstInput()); | 4201 summary->set_out(0, Location::SameAsFirstInput()); |
| 4219 return summary; | 4202 return summary; |
| 4220 } | 4203 } |
| 4221 | 4204 |
| 4222 | 4205 |
| 4223 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4206 void Float32x4MinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4224 XmmRegister left = locs()->in(0).fpu_reg(); | 4207 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4225 XmmRegister right = locs()->in(1).fpu_reg(); | 4208 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4226 | 4209 |
| 4227 ASSERT(locs()->out(0).fpu_reg() == left); | 4210 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4228 | 4211 |
| 4229 switch (op_kind()) { | 4212 switch (op_kind()) { |
| 4230 case MethodRecognizer::kFloat32x4Min: | 4213 case MethodRecognizer::kFloat32x4Min: |
| 4231 __ minps(left, right); | 4214 __ minps(left, right); |
| 4232 break; | 4215 break; |
| 4233 case MethodRecognizer::kFloat32x4Max: | 4216 case MethodRecognizer::kFloat32x4Max: |
| 4234 __ maxps(left, right); | 4217 __ maxps(left, right); |
| 4235 break; | 4218 break; |
| 4236 default: UNREACHABLE(); | 4219 default: |
| 4220 UNREACHABLE(); |
| 4237 } | 4221 } |
| 4238 } | 4222 } |
| 4239 | 4223 |
| 4240 | 4224 |
| 4241 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, | 4225 LocationSummary* Float32x4ScaleInstr::MakeLocationSummary(Zone* zone, |
| 4242 bool opt) const { | 4226 bool opt) const { |
| 4243 const intptr_t kNumInputs = 2; | 4227 const intptr_t kNumInputs = 2; |
| 4244 const intptr_t kNumTemps = 0; | 4228 const intptr_t kNumTemps = 0; |
| 4245 LocationSummary* summary = new(zone) LocationSummary( | 4229 LocationSummary* summary = new (zone) |
| 4246 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4230 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4247 summary->set_in(0, Location::RequiresFpuRegister()); | 4231 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4248 summary->set_in(1, Location::RequiresFpuRegister()); | 4232 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4249 summary->set_out(0, Location::SameAsFirstInput()); | 4233 summary->set_out(0, Location::SameAsFirstInput()); |
| 4250 return summary; | 4234 return summary; |
| 4251 } | 4235 } |
| 4252 | 4236 |
| 4253 | 4237 |
| 4254 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4238 void Float32x4ScaleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4255 XmmRegister left = locs()->in(0).fpu_reg(); | 4239 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4256 XmmRegister right = locs()->in(1).fpu_reg(); | 4240 XmmRegister right = locs()->in(1).fpu_reg(); |
| 4257 | 4241 |
| 4258 ASSERT(locs()->out(0).fpu_reg() == left); | 4242 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4259 | 4243 |
| 4260 switch (op_kind()) { | 4244 switch (op_kind()) { |
| 4261 case MethodRecognizer::kFloat32x4Scale: | 4245 case MethodRecognizer::kFloat32x4Scale: |
| 4262 __ cvtsd2ss(left, left); | 4246 __ cvtsd2ss(left, left); |
| 4263 __ shufps(left, left, Immediate(0x00)); | 4247 __ shufps(left, left, Immediate(0x00)); |
| 4264 __ mulps(left, right); | 4248 __ mulps(left, right); |
| 4265 break; | 4249 break; |
| 4266 default: UNREACHABLE(); | 4250 default: |
| 4251 UNREACHABLE(); |
| 4267 } | 4252 } |
| 4268 } | 4253 } |
| 4269 | 4254 |
| 4270 | 4255 |
| 4271 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, | 4256 LocationSummary* Float32x4SqrtInstr::MakeLocationSummary(Zone* zone, |
| 4272 bool opt) const { | 4257 bool opt) const { |
| 4273 const intptr_t kNumInputs = 1; | 4258 const intptr_t kNumInputs = 1; |
| 4274 const intptr_t kNumTemps = 0; | 4259 const intptr_t kNumTemps = 0; |
| 4275 LocationSummary* summary = new(zone) LocationSummary( | 4260 LocationSummary* summary = new (zone) |
| 4276 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4261 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4277 summary->set_in(0, Location::RequiresFpuRegister()); | 4262 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4278 summary->set_out(0, Location::SameAsFirstInput()); | 4263 summary->set_out(0, Location::SameAsFirstInput()); |
| 4279 return summary; | 4264 return summary; |
| 4280 } | 4265 } |
| 4281 | 4266 |
| 4282 | 4267 |
| 4283 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4268 void Float32x4SqrtInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4284 XmmRegister left = locs()->in(0).fpu_reg(); | 4269 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4285 | 4270 |
| 4286 ASSERT(locs()->out(0).fpu_reg() == left); | 4271 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4287 | 4272 |
| 4288 switch (op_kind()) { | 4273 switch (op_kind()) { |
| 4289 case MethodRecognizer::kFloat32x4Sqrt: | 4274 case MethodRecognizer::kFloat32x4Sqrt: |
| 4290 __ sqrtps(left); | 4275 __ sqrtps(left); |
| 4291 break; | 4276 break; |
| 4292 case MethodRecognizer::kFloat32x4Reciprocal: | 4277 case MethodRecognizer::kFloat32x4Reciprocal: |
| 4293 __ reciprocalps(left); | 4278 __ reciprocalps(left); |
| 4294 break; | 4279 break; |
| 4295 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | 4280 case MethodRecognizer::kFloat32x4ReciprocalSqrt: |
| 4296 __ rsqrtps(left); | 4281 __ rsqrtps(left); |
| 4297 break; | 4282 break; |
| 4298 default: UNREACHABLE(); | 4283 default: |
| 4284 UNREACHABLE(); |
| 4299 } | 4285 } |
| 4300 } | 4286 } |
| 4301 | 4287 |
| 4302 | 4288 |
| 4303 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4289 LocationSummary* Float32x4ZeroArgInstr::MakeLocationSummary(Zone* zone, |
| 4304 bool opt) const { | 4290 bool opt) const { |
| 4305 const intptr_t kNumInputs = 1; | 4291 const intptr_t kNumInputs = 1; |
| 4306 const intptr_t kNumTemps = 0; | 4292 const intptr_t kNumTemps = 0; |
| 4307 LocationSummary* summary = new(zone) LocationSummary( | 4293 LocationSummary* summary = new (zone) |
| 4308 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4294 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4309 summary->set_in(0, Location::RequiresFpuRegister()); | 4295 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4310 summary->set_out(0, Location::SameAsFirstInput()); | 4296 summary->set_out(0, Location::SameAsFirstInput()); |
| 4311 return summary; | 4297 return summary; |
| 4312 } | 4298 } |
| 4313 | 4299 |
| 4314 | 4300 |
| 4315 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4301 void Float32x4ZeroArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4316 XmmRegister left = locs()->in(0).fpu_reg(); | 4302 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4317 | 4303 |
| 4318 ASSERT(locs()->out(0).fpu_reg() == left); | 4304 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4319 switch (op_kind()) { | 4305 switch (op_kind()) { |
| 4320 case MethodRecognizer::kFloat32x4Negate: | 4306 case MethodRecognizer::kFloat32x4Negate: |
| 4321 __ negateps(left); | 4307 __ negateps(left); |
| 4322 break; | 4308 break; |
| 4323 case MethodRecognizer::kFloat32x4Absolute: | 4309 case MethodRecognizer::kFloat32x4Absolute: |
| 4324 __ absps(left); | 4310 __ absps(left); |
| 4325 break; | 4311 break; |
| 4326 default: UNREACHABLE(); | 4312 default: |
| 4313 UNREACHABLE(); |
| 4327 } | 4314 } |
| 4328 } | 4315 } |
| 4329 | 4316 |
| 4330 | 4317 |
| 4331 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, | 4318 LocationSummary* Float32x4ClampInstr::MakeLocationSummary(Zone* zone, |
| 4332 bool opt) const { | 4319 bool opt) const { |
| 4333 const intptr_t kNumInputs = 3; | 4320 const intptr_t kNumInputs = 3; |
| 4334 const intptr_t kNumTemps = 0; | 4321 const intptr_t kNumTemps = 0; |
| 4335 LocationSummary* summary = new(zone) LocationSummary( | 4322 LocationSummary* summary = new (zone) |
| 4336 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4323 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4337 summary->set_in(0, Location::RequiresFpuRegister()); | 4324 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4338 summary->set_in(1, Location::RequiresFpuRegister()); | 4325 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4339 summary->set_in(2, Location::RequiresFpuRegister()); | 4326 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4340 summary->set_out(0, Location::SameAsFirstInput()); | 4327 summary->set_out(0, Location::SameAsFirstInput()); |
| 4341 return summary; | 4328 return summary; |
| 4342 } | 4329 } |
| 4343 | 4330 |
| 4344 | 4331 |
| 4345 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4332 void Float32x4ClampInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4346 XmmRegister left = locs()->in(0).fpu_reg(); | 4333 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4347 XmmRegister lower = locs()->in(1).fpu_reg(); | 4334 XmmRegister lower = locs()->in(1).fpu_reg(); |
| 4348 XmmRegister upper = locs()->in(2).fpu_reg(); | 4335 XmmRegister upper = locs()->in(2).fpu_reg(); |
| 4349 ASSERT(locs()->out(0).fpu_reg() == left); | 4336 ASSERT(locs()->out(0).fpu_reg() == left); |
| 4350 __ minps(left, upper); | 4337 __ minps(left, upper); |
| 4351 __ maxps(left, lower); | 4338 __ maxps(left, lower); |
| 4352 } | 4339 } |
| 4353 | 4340 |
| 4354 | 4341 |
| 4355 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, | 4342 LocationSummary* Float32x4WithInstr::MakeLocationSummary(Zone* zone, |
| 4356 bool opt) const { | 4343 bool opt) const { |
| 4357 const intptr_t kNumInputs = 2; | 4344 const intptr_t kNumInputs = 2; |
| 4358 const intptr_t kNumTemps = 0; | 4345 const intptr_t kNumTemps = 0; |
| 4359 LocationSummary* summary = new(zone) LocationSummary( | 4346 LocationSummary* summary = new (zone) |
| 4360 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4347 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4361 summary->set_in(0, Location::RequiresFpuRegister()); | 4348 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4362 summary->set_in(1, Location::RequiresFpuRegister()); | 4349 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4363 summary->set_out(0, Location::SameAsFirstInput()); | 4350 summary->set_out(0, Location::SameAsFirstInput()); |
| 4364 return summary; | 4351 return summary; |
| 4365 } | 4352 } |
| 4366 | 4353 |
| 4367 | 4354 |
| 4368 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4355 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4369 XmmRegister replacement = locs()->in(0).fpu_reg(); | 4356 XmmRegister replacement = locs()->in(0).fpu_reg(); |
| 4370 XmmRegister value = locs()->in(1).fpu_reg(); | 4357 XmmRegister value = locs()->in(1).fpu_reg(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4409 __ cvtsd2ss(replacement, replacement); | 4396 __ cvtsd2ss(replacement, replacement); |
| 4410 __ AddImmediate(RSP, Immediate(-16)); | 4397 __ AddImmediate(RSP, Immediate(-16)); |
| 4411 // Move value to stack. | 4398 // Move value to stack. |
| 4412 __ movups(Address(RSP, 0), value); | 4399 __ movups(Address(RSP, 0), value); |
| 4413 // Write over W value. | 4400 // Write over W value. |
| 4414 __ movss(Address(RSP, 12), replacement); | 4401 __ movss(Address(RSP, 12), replacement); |
| 4415 // Move updated value into output register. | 4402 // Move updated value into output register. |
| 4416 __ movups(replacement, Address(RSP, 0)); | 4403 __ movups(replacement, Address(RSP, 0)); |
| 4417 __ AddImmediate(RSP, Immediate(16)); | 4404 __ AddImmediate(RSP, Immediate(16)); |
| 4418 break; | 4405 break; |
| 4419 default: UNREACHABLE(); | 4406 default: |
| 4407 UNREACHABLE(); |
| 4420 } | 4408 } |
| 4421 } | 4409 } |
| 4422 | 4410 |
| 4423 | 4411 |
| 4424 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, | 4412 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, |
| 4425 bool opt) const { | 4413 bool opt) const { |
| 4426 const intptr_t kNumInputs = 1; | 4414 const intptr_t kNumInputs = 1; |
| 4427 const intptr_t kNumTemps = 0; | 4415 const intptr_t kNumTemps = 0; |
| 4428 LocationSummary* summary = new(zone) LocationSummary( | 4416 LocationSummary* summary = new (zone) |
| 4429 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4417 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4430 summary->set_in(0, Location::RequiresFpuRegister()); | 4418 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4431 summary->set_out(0, Location::SameAsFirstInput()); | 4419 summary->set_out(0, Location::SameAsFirstInput()); |
| 4432 return summary; | 4420 return summary; |
| 4433 } | 4421 } |
| 4434 | 4422 |
| 4435 | 4423 |
| 4436 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4424 void Float32x4ToInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4437 // NOP. | 4425 // NOP. |
| 4438 } | 4426 } |
| 4439 | 4427 |
| 4440 | 4428 |
| 4441 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, | 4429 LocationSummary* Simd64x2ShuffleInstr::MakeLocationSummary(Zone* zone, |
| 4442 bool opt) const { | 4430 bool opt) const { |
| 4443 const intptr_t kNumInputs = 1; | 4431 const intptr_t kNumInputs = 1; |
| 4444 const intptr_t kNumTemps = 0; | 4432 const intptr_t kNumTemps = 0; |
| 4445 LocationSummary* summary = new(zone) LocationSummary( | 4433 LocationSummary* summary = new (zone) |
| 4446 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4434 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4447 summary->set_in(0, Location::RequiresFpuRegister()); | 4435 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4448 summary->set_out(0, Location::SameAsFirstInput()); | 4436 summary->set_out(0, Location::SameAsFirstInput()); |
| 4449 return summary; | 4437 return summary; |
| 4450 } | 4438 } |
| 4451 | 4439 |
| 4452 | 4440 |
| 4453 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4441 void Simd64x2ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4454 XmmRegister value = locs()->in(0).fpu_reg(); | 4442 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4455 | 4443 |
| 4456 ASSERT(locs()->out(0).fpu_reg() == value); | 4444 ASSERT(locs()->out(0).fpu_reg() == value); |
| 4457 switch (op_kind()) { | 4445 switch (op_kind()) { |
| 4458 case MethodRecognizer::kFloat64x2GetX: | 4446 case MethodRecognizer::kFloat64x2GetX: |
| 4459 // nop. | 4447 // nop. |
| 4460 break; | 4448 break; |
| 4461 case MethodRecognizer::kFloat64x2GetY: | 4449 case MethodRecognizer::kFloat64x2GetY: |
| 4462 __ shufpd(value, value, Immediate(0x33)); | 4450 __ shufpd(value, value, Immediate(0x33)); |
| 4463 break; | 4451 break; |
| 4464 default: UNREACHABLE(); | 4452 default: |
| 4453 UNREACHABLE(); |
| 4465 } | 4454 } |
| 4466 } | 4455 } |
| 4467 | 4456 |
| 4468 | 4457 |
| 4469 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, | 4458 LocationSummary* Float64x2ZeroInstr::MakeLocationSummary(Zone* zone, |
| 4470 bool opt) const { | 4459 bool opt) const { |
| 4471 const intptr_t kNumInputs = 0; | 4460 const intptr_t kNumInputs = 0; |
| 4472 const intptr_t kNumTemps = 0; | 4461 const intptr_t kNumTemps = 0; |
| 4473 LocationSummary* summary = new(zone) LocationSummary( | 4462 LocationSummary* summary = new (zone) |
| 4474 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4463 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4475 summary->set_out(0, Location::RequiresFpuRegister()); | 4464 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4476 return summary; | 4465 return summary; |
| 4477 } | 4466 } |
| 4478 | 4467 |
| 4479 | 4468 |
| 4480 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4469 void Float64x2ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4481 XmmRegister value = locs()->out(0).fpu_reg(); | 4470 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4482 __ xorpd(value, value); | 4471 __ xorpd(value, value); |
| 4483 } | 4472 } |
| 4484 | 4473 |
| 4485 | 4474 |
| 4486 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, | 4475 LocationSummary* Float64x2SplatInstr::MakeLocationSummary(Zone* zone, |
| 4487 bool opt) const { | 4476 bool opt) const { |
| 4488 const intptr_t kNumInputs = 1; | 4477 const intptr_t kNumInputs = 1; |
| 4489 const intptr_t kNumTemps = 0; | 4478 const intptr_t kNumTemps = 0; |
| 4490 LocationSummary* summary = new(zone) LocationSummary( | 4479 LocationSummary* summary = new (zone) |
| 4491 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4480 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4492 summary->set_in(0, Location::RequiresFpuRegister()); | 4481 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4493 summary->set_out(0, Location::SameAsFirstInput()); | 4482 summary->set_out(0, Location::SameAsFirstInput()); |
| 4494 return summary; | 4483 return summary; |
| 4495 } | 4484 } |
| 4496 | 4485 |
| 4497 | 4486 |
| 4498 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4487 void Float64x2SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4499 XmmRegister value = locs()->out(0).fpu_reg(); | 4488 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4500 __ shufpd(value, value, Immediate(0x0)); | 4489 __ shufpd(value, value, Immediate(0x0)); |
| 4501 } | 4490 } |
| 4502 | 4491 |
| 4503 | 4492 |
| 4504 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( | 4493 LocationSummary* Float64x2ConstructorInstr::MakeLocationSummary( |
| 4505 Zone* zone, bool opt) const { | 4494 Zone* zone, |
| 4495 bool opt) const { |
| 4506 const intptr_t kNumInputs = 2; | 4496 const intptr_t kNumInputs = 2; |
| 4507 const intptr_t kNumTemps = 0; | 4497 const intptr_t kNumTemps = 0; |
| 4508 LocationSummary* summary = new(zone) LocationSummary( | 4498 LocationSummary* summary = new (zone) |
| 4509 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4499 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4510 summary->set_in(0, Location::RequiresFpuRegister()); | 4500 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4511 summary->set_in(1, Location::RequiresFpuRegister()); | 4501 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4512 summary->set_out(0, Location::SameAsFirstInput()); | 4502 summary->set_out(0, Location::SameAsFirstInput()); |
| 4513 return summary; | 4503 return summary; |
| 4514 } | 4504 } |
| 4515 | 4505 |
| 4516 | 4506 |
| 4517 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4507 void Float64x2ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4518 XmmRegister v0 = locs()->in(0).fpu_reg(); | 4508 XmmRegister v0 = locs()->in(0).fpu_reg(); |
| 4519 XmmRegister v1 = locs()->in(1).fpu_reg(); | 4509 XmmRegister v1 = locs()->in(1).fpu_reg(); |
| 4520 ASSERT(v0 == locs()->out(0).fpu_reg()); | 4510 ASSERT(v0 == locs()->out(0).fpu_reg()); |
| 4521 // shufpd mask 0x0 results in: | 4511 // shufpd mask 0x0 results in: |
| 4522 // Lower 64-bits of v0 = Lower 64-bits of v0. | 4512 // Lower 64-bits of v0 = Lower 64-bits of v0. |
| 4523 // Upper 64-bits of v0 = Lower 64-bits of v1. | 4513 // Upper 64-bits of v0 = Lower 64-bits of v1. |
| 4524 __ shufpd(v0, v1, Immediate(0x0)); | 4514 __ shufpd(v0, v1, Immediate(0x0)); |
| 4525 } | 4515 } |
| 4526 | 4516 |
| 4527 | 4517 |
| 4528 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( | 4518 LocationSummary* Float64x2ToFloat32x4Instr::MakeLocationSummary( |
| 4529 Zone* zone, bool opt) const { | 4519 Zone* zone, |
| 4520 bool opt) const { |
| 4530 const intptr_t kNumInputs = 1; | 4521 const intptr_t kNumInputs = 1; |
| 4531 const intptr_t kNumTemps = 0; | 4522 const intptr_t kNumTemps = 0; |
| 4532 LocationSummary* summary = new(zone) LocationSummary( | 4523 LocationSummary* summary = new (zone) |
| 4533 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4524 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4534 summary->set_in(0, Location::RequiresFpuRegister()); | 4525 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4535 summary->set_out(0, Location::SameAsFirstInput()); | 4526 summary->set_out(0, Location::SameAsFirstInput()); |
| 4536 return summary; | 4527 return summary; |
| 4537 } | 4528 } |
| 4538 | 4529 |
| 4539 | 4530 |
| 4540 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4531 void Float64x2ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4541 XmmRegister value = locs()->out(0).fpu_reg(); | 4532 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4542 __ cvtpd2ps(value, value); | 4533 __ cvtpd2ps(value, value); |
| 4543 } | 4534 } |
| 4544 | 4535 |
| 4545 | 4536 |
| 4546 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( | 4537 LocationSummary* Float32x4ToFloat64x2Instr::MakeLocationSummary( |
| 4547 Zone* zone, bool opt) const { | 4538 Zone* zone, |
| 4539 bool opt) const { |
| 4548 const intptr_t kNumInputs = 1; | 4540 const intptr_t kNumInputs = 1; |
| 4549 const intptr_t kNumTemps = 0; | 4541 const intptr_t kNumTemps = 0; |
| 4550 LocationSummary* summary = new(zone) LocationSummary( | 4542 LocationSummary* summary = new (zone) |
| 4551 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4543 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4552 summary->set_in(0, Location::RequiresFpuRegister()); | 4544 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4553 summary->set_out(0, Location::SameAsFirstInput()); | 4545 summary->set_out(0, Location::SameAsFirstInput()); |
| 4554 return summary; | 4546 return summary; |
| 4555 } | 4547 } |
| 4556 | 4548 |
| 4557 | 4549 |
| 4558 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4550 void Float32x4ToFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4559 XmmRegister value = locs()->out(0).fpu_reg(); | 4551 XmmRegister value = locs()->out(0).fpu_reg(); |
| 4560 __ cvtps2pd(value, value); | 4552 __ cvtps2pd(value, value); |
| 4561 } | 4553 } |
| 4562 | 4554 |
| 4563 | 4555 |
| 4564 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, | 4556 LocationSummary* Float64x2ZeroArgInstr::MakeLocationSummary(Zone* zone, |
| 4565 bool opt) const { | 4557 bool opt) const { |
| 4566 const intptr_t kNumInputs = 1; | 4558 const intptr_t kNumInputs = 1; |
| 4567 const intptr_t kNumTemps = 0; | 4559 const intptr_t kNumTemps = 0; |
| 4568 LocationSummary* summary = new(zone) LocationSummary( | 4560 LocationSummary* summary = new (zone) |
| 4569 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4561 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4570 summary->set_in(0, Location::RequiresFpuRegister()); | 4562 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4571 if (representation() == kTagged) { | 4563 if (representation() == kTagged) { |
| 4572 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); | 4564 ASSERT(op_kind() == MethodRecognizer::kFloat64x2GetSignMask); |
| 4573 summary->set_out(0, Location::RequiresRegister()); | 4565 summary->set_out(0, Location::RequiresRegister()); |
| 4574 } else { | 4566 } else { |
| 4575 ASSERT(representation() == kUnboxedFloat64x2); | 4567 ASSERT(representation() == kUnboxedFloat64x2); |
| 4576 summary->set_out(0, Location::SameAsFirstInput()); | 4568 summary->set_out(0, Location::SameAsFirstInput()); |
| 4577 } | 4569 } |
| 4578 return summary; | 4570 return summary; |
| 4579 } | 4571 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4592 case MethodRecognizer::kFloat64x2Abs: | 4584 case MethodRecognizer::kFloat64x2Abs: |
| 4593 __ abspd(left); | 4585 __ abspd(left); |
| 4594 break; | 4586 break; |
| 4595 case MethodRecognizer::kFloat64x2Sqrt: | 4587 case MethodRecognizer::kFloat64x2Sqrt: |
| 4596 __ sqrtpd(left); | 4588 __ sqrtpd(left); |
| 4597 break; | 4589 break; |
| 4598 case MethodRecognizer::kFloat64x2GetSignMask: | 4590 case MethodRecognizer::kFloat64x2GetSignMask: |
| 4599 __ movmskpd(locs()->out(0).reg(), left); | 4591 __ movmskpd(locs()->out(0).reg(), left); |
| 4600 __ SmiTag(locs()->out(0).reg()); | 4592 __ SmiTag(locs()->out(0).reg()); |
| 4601 break; | 4593 break; |
| 4602 default: UNREACHABLE(); | 4594 default: |
| 4595 UNREACHABLE(); |
| 4603 } | 4596 } |
| 4604 } | 4597 } |
| 4605 | 4598 |
| 4606 | 4599 |
| 4607 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, | 4600 LocationSummary* Float64x2OneArgInstr::MakeLocationSummary(Zone* zone, |
| 4608 bool opt) const { | 4601 bool opt) const { |
| 4609 const intptr_t kNumInputs = 2; | 4602 const intptr_t kNumInputs = 2; |
| 4610 const intptr_t kNumTemps = 0; | 4603 const intptr_t kNumTemps = 0; |
| 4611 LocationSummary* summary = new(zone) LocationSummary( | 4604 LocationSummary* summary = new (zone) |
| 4612 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4605 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4613 summary->set_in(0, Location::RequiresFpuRegister()); | 4606 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4614 summary->set_in(1, Location::RequiresFpuRegister()); | 4607 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4615 summary->set_out(0, Location::SameAsFirstInput()); | 4608 summary->set_out(0, Location::SameAsFirstInput()); |
| 4616 return summary; | 4609 return summary; |
| 4617 } | 4610 } |
| 4618 | 4611 |
| 4619 | 4612 |
| 4620 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4613 void Float64x2OneArgInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4621 XmmRegister left = locs()->in(0).fpu_reg(); | 4614 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4622 XmmRegister right = locs()->in(1).fpu_reg(); | 4615 XmmRegister right = locs()->in(1).fpu_reg(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 4646 // Move updated value into output register. | 4639 // Move updated value into output register. |
| 4647 __ movups(left, Address(RSP, 0)); | 4640 __ movups(left, Address(RSP, 0)); |
| 4648 __ addq(RSP, Immediate(16)); | 4641 __ addq(RSP, Immediate(16)); |
| 4649 break; | 4642 break; |
| 4650 case MethodRecognizer::kFloat64x2Min: | 4643 case MethodRecognizer::kFloat64x2Min: |
| 4651 __ minpd(left, right); | 4644 __ minpd(left, right); |
| 4652 break; | 4645 break; |
| 4653 case MethodRecognizer::kFloat64x2Max: | 4646 case MethodRecognizer::kFloat64x2Max: |
| 4654 __ maxpd(left, right); | 4647 __ maxpd(left, right); |
| 4655 break; | 4648 break; |
| 4656 default: UNREACHABLE(); | 4649 default: |
| 4650 UNREACHABLE(); |
| 4657 } | 4651 } |
| 4658 } | 4652 } |
| 4659 | 4653 |
| 4660 | 4654 |
| 4661 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary( | 4655 LocationSummary* Int32x4ConstructorInstr::MakeLocationSummary(Zone* zone, |
| 4662 Zone* zone, bool opt) const { | 4656 bool opt) const { |
| 4663 const intptr_t kNumInputs = 4; | 4657 const intptr_t kNumInputs = 4; |
| 4664 const intptr_t kNumTemps = 0; | 4658 const intptr_t kNumTemps = 0; |
| 4665 LocationSummary* summary = new(zone) LocationSummary( | 4659 LocationSummary* summary = new (zone) |
| 4666 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4660 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4667 summary->set_in(0, Location::RequiresRegister()); | 4661 summary->set_in(0, Location::RequiresRegister()); |
| 4668 summary->set_in(1, Location::RequiresRegister()); | 4662 summary->set_in(1, Location::RequiresRegister()); |
| 4669 summary->set_in(2, Location::RequiresRegister()); | 4663 summary->set_in(2, Location::RequiresRegister()); |
| 4670 summary->set_in(3, Location::RequiresRegister()); | 4664 summary->set_in(3, Location::RequiresRegister()); |
| 4671 summary->set_out(0, Location::RequiresFpuRegister()); | 4665 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4672 return summary; | 4666 return summary; |
| 4673 } | 4667 } |
| 4674 | 4668 |
| 4675 | 4669 |
| 4676 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4670 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4677 Register v0 = locs()->in(0).reg(); | 4671 Register v0 = locs()->in(0).reg(); |
| 4678 Register v1 = locs()->in(1).reg(); | 4672 Register v1 = locs()->in(1).reg(); |
| 4679 Register v2 = locs()->in(2).reg(); | 4673 Register v2 = locs()->in(2).reg(); |
| 4680 Register v3 = locs()->in(3).reg(); | 4674 Register v3 = locs()->in(3).reg(); |
| 4681 XmmRegister result = locs()->out(0).fpu_reg(); | 4675 XmmRegister result = locs()->out(0).fpu_reg(); |
| 4682 __ AddImmediate(RSP, Immediate(-4 * kInt32Size)); | 4676 __ AddImmediate(RSP, Immediate(-4 * kInt32Size)); |
| 4683 __ movl(Address(RSP, 0 * kInt32Size), v0); | 4677 __ movl(Address(RSP, 0 * kInt32Size), v0); |
| 4684 __ movl(Address(RSP, 1 * kInt32Size), v1); | 4678 __ movl(Address(RSP, 1 * kInt32Size), v1); |
| 4685 __ movl(Address(RSP, 2 * kInt32Size), v2); | 4679 __ movl(Address(RSP, 2 * kInt32Size), v2); |
| 4686 __ movl(Address(RSP, 3 * kInt32Size), v3); | 4680 __ movl(Address(RSP, 3 * kInt32Size), v3); |
| 4687 __ movups(result, Address(RSP, 0)); | 4681 __ movups(result, Address(RSP, 0)); |
| 4688 __ AddImmediate(RSP, Immediate(4 * kInt32Size)); | 4682 __ AddImmediate(RSP, Immediate(4 * kInt32Size)); |
| 4689 } | 4683 } |
| 4690 | 4684 |
| 4691 | 4685 |
| 4692 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 4686 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
| 4693 Zone* zone, bool opt) const { | 4687 Zone* zone, |
| 4688 bool opt) const { |
| 4694 const intptr_t kNumInputs = 4; | 4689 const intptr_t kNumInputs = 4; |
| 4695 const intptr_t kNumTemps = 1; | 4690 const intptr_t kNumTemps = 1; |
| 4696 LocationSummary* summary = new(zone) LocationSummary( | 4691 LocationSummary* summary = new (zone) |
| 4697 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4692 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4698 summary->set_in(0, Location::RequiresRegister()); | 4693 summary->set_in(0, Location::RequiresRegister()); |
| 4699 summary->set_in(1, Location::RequiresRegister()); | 4694 summary->set_in(1, Location::RequiresRegister()); |
| 4700 summary->set_in(2, Location::RequiresRegister()); | 4695 summary->set_in(2, Location::RequiresRegister()); |
| 4701 summary->set_in(3, Location::RequiresRegister()); | 4696 summary->set_in(3, Location::RequiresRegister()); |
| 4702 summary->set_temp(0, Location::RequiresRegister()); | 4697 summary->set_temp(0, Location::RequiresRegister()); |
| 4703 summary->set_out(0, Location::RequiresFpuRegister()); | 4698 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4704 return summary; | 4699 return summary; |
| 4705 } | 4700 } |
| 4706 | 4701 |
| 4707 | 4702 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4756 | 4751 |
| 4757 __ movups(result, Address(RSP, 0)); | 4752 __ movups(result, Address(RSP, 0)); |
| 4758 __ AddImmediate(RSP, Immediate(16)); | 4753 __ AddImmediate(RSP, Immediate(16)); |
| 4759 } | 4754 } |
| 4760 | 4755 |
| 4761 | 4756 |
| 4762 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, | 4757 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, |
| 4763 bool opt) const { | 4758 bool opt) const { |
| 4764 const intptr_t kNumInputs = 1; | 4759 const intptr_t kNumInputs = 1; |
| 4765 const intptr_t kNumTemps = 0; | 4760 const intptr_t kNumTemps = 0; |
| 4766 LocationSummary* summary = new(zone) LocationSummary( | 4761 LocationSummary* summary = new (zone) |
| 4767 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4762 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4768 summary->set_in(0, Location::RequiresFpuRegister()); | 4763 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4769 summary->set_out(0, Location::RequiresRegister()); | 4764 summary->set_out(0, Location::RequiresRegister()); |
| 4770 return summary; | 4765 return summary; |
| 4771 } | 4766 } |
| 4772 | 4767 |
| 4773 | 4768 |
| 4774 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4769 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4775 XmmRegister value = locs()->in(0).fpu_reg(); | 4770 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4776 Register result = locs()->out(0).reg(); | 4771 Register result = locs()->out(0).reg(); |
| 4777 Label done; | 4772 Label done; |
| 4778 Label non_zero; | 4773 Label non_zero; |
| 4779 __ AddImmediate(RSP, Immediate(-16)); | 4774 __ AddImmediate(RSP, Immediate(-16)); |
| 4780 // Move value to stack. | 4775 // Move value to stack. |
| 4781 __ movups(Address(RSP, 0), value); | 4776 __ movups(Address(RSP, 0), value); |
| 4782 switch (op_kind()) { | 4777 switch (op_kind()) { |
| 4783 case MethodRecognizer::kInt32x4GetFlagX: | 4778 case MethodRecognizer::kInt32x4GetFlagX: |
| 4784 __ movl(result, Address(RSP, 0)); | 4779 __ movl(result, Address(RSP, 0)); |
| 4785 break; | 4780 break; |
| 4786 case MethodRecognizer::kInt32x4GetFlagY: | 4781 case MethodRecognizer::kInt32x4GetFlagY: |
| 4787 __ movl(result, Address(RSP, 4)); | 4782 __ movl(result, Address(RSP, 4)); |
| 4788 break; | 4783 break; |
| 4789 case MethodRecognizer::kInt32x4GetFlagZ: | 4784 case MethodRecognizer::kInt32x4GetFlagZ: |
| 4790 __ movl(result, Address(RSP, 8)); | 4785 __ movl(result, Address(RSP, 8)); |
| 4791 break; | 4786 break; |
| 4792 case MethodRecognizer::kInt32x4GetFlagW: | 4787 case MethodRecognizer::kInt32x4GetFlagW: |
| 4793 __ movl(result, Address(RSP, 12)); | 4788 __ movl(result, Address(RSP, 12)); |
| 4794 break; | 4789 break; |
| 4795 default: UNREACHABLE(); | 4790 default: |
| 4791 UNREACHABLE(); |
| 4796 } | 4792 } |
| 4797 __ AddImmediate(RSP, Immediate(16)); | 4793 __ AddImmediate(RSP, Immediate(16)); |
| 4798 __ testl(result, result); | 4794 __ testl(result, result); |
| 4799 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); | 4795 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); |
| 4800 __ LoadObject(result, Bool::False()); | 4796 __ LoadObject(result, Bool::False()); |
| 4801 __ jmp(&done); | 4797 __ jmp(&done); |
| 4802 __ Bind(&non_zero); | 4798 __ Bind(&non_zero); |
| 4803 __ LoadObject(result, Bool::True()); | 4799 __ LoadObject(result, Bool::True()); |
| 4804 __ Bind(&done); | 4800 __ Bind(&done); |
| 4805 } | 4801 } |
| 4806 | 4802 |
| 4807 | 4803 |
| 4808 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, | 4804 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, |
| 4809 bool opt) const { | 4805 bool opt) const { |
| 4810 const intptr_t kNumInputs = 3; | 4806 const intptr_t kNumInputs = 3; |
| 4811 const intptr_t kNumTemps = 1; | 4807 const intptr_t kNumTemps = 1; |
| 4812 LocationSummary* summary = new(zone) LocationSummary( | 4808 LocationSummary* summary = new (zone) |
| 4813 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4809 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4814 summary->set_in(0, Location::RequiresFpuRegister()); | 4810 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4815 summary->set_in(1, Location::RequiresFpuRegister()); | 4811 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4816 summary->set_in(2, Location::RequiresFpuRegister()); | 4812 summary->set_in(2, Location::RequiresFpuRegister()); |
| 4817 summary->set_temp(0, Location::RequiresFpuRegister()); | 4813 summary->set_temp(0, Location::RequiresFpuRegister()); |
| 4818 summary->set_out(0, Location::SameAsFirstInput()); | 4814 summary->set_out(0, Location::SameAsFirstInput()); |
| 4819 return summary; | 4815 return summary; |
| 4820 } | 4816 } |
| 4821 | 4817 |
| 4822 | 4818 |
| 4823 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4819 void Int32x4SelectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 4837 __ andps(temp, falseValue); | 4833 __ andps(temp, falseValue); |
| 4838 // out = mask | temp. | 4834 // out = mask | temp. |
| 4839 __ orps(mask, temp); | 4835 __ orps(mask, temp); |
| 4840 } | 4836 } |
| 4841 | 4837 |
| 4842 | 4838 |
| 4843 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, | 4839 LocationSummary* Int32x4SetFlagInstr::MakeLocationSummary(Zone* zone, |
| 4844 bool opt) const { | 4840 bool opt) const { |
| 4845 const intptr_t kNumInputs = 2; | 4841 const intptr_t kNumInputs = 2; |
| 4846 const intptr_t kNumTemps = 1; | 4842 const intptr_t kNumTemps = 1; |
| 4847 LocationSummary* summary = new(zone) LocationSummary( | 4843 LocationSummary* summary = new (zone) |
| 4848 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4844 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4849 summary->set_in(0, Location::RequiresFpuRegister()); | 4845 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4850 summary->set_in(1, Location::RequiresRegister()); | 4846 summary->set_in(1, Location::RequiresRegister()); |
| 4851 summary->set_temp(0, Location::RequiresRegister()); | 4847 summary->set_temp(0, Location::RequiresRegister()); |
| 4852 summary->set_out(0, Location::SameAsFirstInput()); | 4848 summary->set_out(0, Location::SameAsFirstInput()); |
| 4853 return summary; | 4849 return summary; |
| 4854 } | 4850 } |
| 4855 | 4851 |
| 4856 | 4852 |
| 4857 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4853 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4858 XmmRegister mask = locs()->in(0).fpu_reg(); | 4854 XmmRegister mask = locs()->in(0).fpu_reg(); |
| 4859 Register flag = locs()->in(1).reg(); | 4855 Register flag = locs()->in(1).reg(); |
| 4860 Register temp = locs()->temp(0).reg(); | 4856 Register temp = locs()->temp(0).reg(); |
| 4861 ASSERT(mask == locs()->out(0).fpu_reg()); | 4857 ASSERT(mask == locs()->out(0).fpu_reg()); |
| 4862 __ AddImmediate(RSP, Immediate(-16)); | 4858 __ AddImmediate(RSP, Immediate(-16)); |
| 4863 // Copy mask to stack. | 4859 // Copy mask to stack. |
| 4864 __ movups(Address(RSP, 0), mask); | 4860 __ movups(Address(RSP, 0), mask); |
| 4865 Label falsePath, exitPath; | 4861 Label falsePath, exitPath; |
| 4866 __ CompareObject(flag, Bool::True()); | 4862 __ CompareObject(flag, Bool::True()); |
| 4867 __ j(NOT_EQUAL, &falsePath); | 4863 __ j(NOT_EQUAL, &falsePath); |
| 4868 switch (op_kind()) { | 4864 switch (op_kind()) { |
| 4869 case MethodRecognizer::kInt32x4WithFlagX: | 4865 case MethodRecognizer::kInt32x4WithFlagX: |
| 4870 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); | 4866 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
| 4871 __ movl(Address(RSP, 0), temp); | 4867 __ movl(Address(RSP, 0), temp); |
| 4872 __ jmp(&exitPath); | 4868 __ jmp(&exitPath); |
| 4873 __ Bind(&falsePath); | 4869 __ Bind(&falsePath); |
| 4874 __ LoadImmediate(temp, Immediate(0x0)); | 4870 __ LoadImmediate(temp, Immediate(0x0)); |
| 4875 __ movl(Address(RSP, 0), temp); | 4871 __ movl(Address(RSP, 0), temp); |
| 4876 break; | 4872 break; |
| 4877 case MethodRecognizer::kInt32x4WithFlagY: | 4873 case MethodRecognizer::kInt32x4WithFlagY: |
| 4878 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); | 4874 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
| 4879 __ movl(Address(RSP, 4), temp); | 4875 __ movl(Address(RSP, 4), temp); |
| 4880 __ jmp(&exitPath); | 4876 __ jmp(&exitPath); |
| 4881 __ Bind(&falsePath); | 4877 __ Bind(&falsePath); |
| 4882 __ LoadImmediate(temp, Immediate(0x0)); | 4878 __ LoadImmediate(temp, Immediate(0x0)); |
| 4883 __ movl(Address(RSP, 4), temp); | 4879 __ movl(Address(RSP, 4), temp); |
| 4884 break; | 4880 break; |
| 4885 case MethodRecognizer::kInt32x4WithFlagZ: | 4881 case MethodRecognizer::kInt32x4WithFlagZ: |
| 4886 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); | 4882 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
| 4887 __ movl(Address(RSP, 8), temp); | 4883 __ movl(Address(RSP, 8), temp); |
| 4888 __ jmp(&exitPath); | 4884 __ jmp(&exitPath); |
| 4889 __ Bind(&falsePath); | 4885 __ Bind(&falsePath); |
| 4890 __ LoadImmediate(temp, Immediate(0x0)); | 4886 __ LoadImmediate(temp, Immediate(0x0)); |
| 4891 __ movl(Address(RSP, 8), temp); | 4887 __ movl(Address(RSP, 8), temp); |
| 4892 break; | 4888 break; |
| 4893 case MethodRecognizer::kInt32x4WithFlagW: | 4889 case MethodRecognizer::kInt32x4WithFlagW: |
| 4894 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); | 4890 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
| 4895 __ movl(Address(RSP, 12), temp); | 4891 __ movl(Address(RSP, 12), temp); |
| 4896 __ jmp(&exitPath); | 4892 __ jmp(&exitPath); |
| 4897 __ Bind(&falsePath); | 4893 __ Bind(&falsePath); |
| 4898 __ LoadImmediate(temp, Immediate(0x0)); | 4894 __ LoadImmediate(temp, Immediate(0x0)); |
| 4899 __ movl(Address(RSP, 12), temp); | 4895 __ movl(Address(RSP, 12), temp); |
| 4900 break; | 4896 break; |
| 4901 default: UNREACHABLE(); | 4897 default: |
| 4898 UNREACHABLE(); |
| 4902 } | 4899 } |
| 4903 __ Bind(&exitPath); | 4900 __ Bind(&exitPath); |
| 4904 // Copy mask back to register. | 4901 // Copy mask back to register. |
| 4905 __ movups(mask, Address(RSP, 0)); | 4902 __ movups(mask, Address(RSP, 0)); |
| 4906 __ AddImmediate(RSP, Immediate(16)); | 4903 __ AddImmediate(RSP, Immediate(16)); |
| 4907 } | 4904 } |
| 4908 | 4905 |
| 4909 | 4906 |
| 4910 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, | 4907 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, |
| 4911 bool opt) const { | 4908 bool opt) const { |
| 4912 const intptr_t kNumInputs = 1; | 4909 const intptr_t kNumInputs = 1; |
| 4913 const intptr_t kNumTemps = 0; | 4910 const intptr_t kNumTemps = 0; |
| 4914 LocationSummary* summary = new(zone) LocationSummary( | 4911 LocationSummary* summary = new (zone) |
| 4915 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4912 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4916 summary->set_in(0, Location::RequiresFpuRegister()); | 4913 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4917 summary->set_out(0, Location::SameAsFirstInput()); | 4914 summary->set_out(0, Location::SameAsFirstInput()); |
| 4918 return summary; | 4915 return summary; |
| 4919 } | 4916 } |
| 4920 | 4917 |
| 4921 | 4918 |
| 4922 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4919 void Int32x4ToFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4923 // NOP. | 4920 // NOP. |
| 4924 } | 4921 } |
| 4925 | 4922 |
| 4926 | 4923 |
| 4927 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, | 4924 LocationSummary* BinaryInt32x4OpInstr::MakeLocationSummary(Zone* zone, |
| 4928 bool opt) const { | 4925 bool opt) const { |
| 4929 const intptr_t kNumInputs = 2; | 4926 const intptr_t kNumInputs = 2; |
| 4930 const intptr_t kNumTemps = 0; | 4927 const intptr_t kNumTemps = 0; |
| 4931 LocationSummary* summary = new(zone) LocationSummary( | 4928 LocationSummary* summary = new (zone) |
| 4932 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4929 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4933 summary->set_in(0, Location::RequiresFpuRegister()); | 4930 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4934 summary->set_in(1, Location::RequiresFpuRegister()); | 4931 summary->set_in(1, Location::RequiresFpuRegister()); |
| 4935 summary->set_out(0, Location::SameAsFirstInput()); | 4932 summary->set_out(0, Location::SameAsFirstInput()); |
| 4936 return summary; | 4933 return summary; |
| 4937 } | 4934 } |
| 4938 | 4935 |
| 4939 | 4936 |
| 4940 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4937 void BinaryInt32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4941 XmmRegister left = locs()->in(0).fpu_reg(); | 4938 XmmRegister left = locs()->in(0).fpu_reg(); |
| 4942 XmmRegister right = locs()->in(1).fpu_reg(); | 4939 XmmRegister right = locs()->in(1).fpu_reg(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4953 case Token::kBIT_XOR: { | 4950 case Token::kBIT_XOR: { |
| 4954 __ xorps(left, right); | 4951 __ xorps(left, right); |
| 4955 break; | 4952 break; |
| 4956 } | 4953 } |
| 4957 case Token::kADD: | 4954 case Token::kADD: |
| 4958 __ addpl(left, right); | 4955 __ addpl(left, right); |
| 4959 break; | 4956 break; |
| 4960 case Token::kSUB: | 4957 case Token::kSUB: |
| 4961 __ subpl(left, right); | 4958 __ subpl(left, right); |
| 4962 break; | 4959 break; |
| 4963 default: UNREACHABLE(); | 4960 default: |
| 4961 UNREACHABLE(); |
| 4964 } | 4962 } |
| 4965 } | 4963 } |
| 4966 | 4964 |
| 4967 | 4965 |
| 4968 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, | 4966 LocationSummary* MathUnaryInstr::MakeLocationSummary(Zone* zone, |
| 4969 bool opt) const { | 4967 bool opt) const { |
| 4970 ASSERT((kind() == MathUnaryInstr::kSqrt) || | 4968 ASSERT((kind() == MathUnaryInstr::kSqrt) || |
| 4971 (kind() == MathUnaryInstr::kDoubleSquare)); | 4969 (kind() == MathUnaryInstr::kDoubleSquare)); |
| 4972 const intptr_t kNumInputs = 1; | 4970 const intptr_t kNumInputs = 1; |
| 4973 const intptr_t kNumTemps = 0; | 4971 const intptr_t kNumTemps = 0; |
| 4974 LocationSummary* summary = new(zone) LocationSummary( | 4972 LocationSummary* summary = new (zone) |
| 4975 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4973 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4976 summary->set_in(0, Location::RequiresFpuRegister()); | 4974 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4977 if (kind() == MathUnaryInstr::kDoubleSquare) { | 4975 if (kind() == MathUnaryInstr::kDoubleSquare) { |
| 4978 summary->set_out(0, Location::SameAsFirstInput()); | 4976 summary->set_out(0, Location::SameAsFirstInput()); |
| 4979 } else { | 4977 } else { |
| 4980 summary->set_out(0, Location::RequiresFpuRegister()); | 4978 summary->set_out(0, Location::RequiresFpuRegister()); |
| 4981 } | 4979 } |
| 4982 return summary; | 4980 return summary; |
| 4983 } | 4981 } |
| 4984 | 4982 |
| 4985 | 4983 |
| 4986 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4984 void MathUnaryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4987 if (kind() == MathUnaryInstr::kSqrt) { | 4985 if (kind() == MathUnaryInstr::kSqrt) { |
| 4988 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 4986 __ sqrtsd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 4989 } else if (kind() == MathUnaryInstr::kDoubleSquare) { | 4987 } else if (kind() == MathUnaryInstr::kDoubleSquare) { |
| 4990 XmmRegister value_reg = locs()->in(0).fpu_reg(); | 4988 XmmRegister value_reg = locs()->in(0).fpu_reg(); |
| 4991 __ mulsd(value_reg, value_reg); | 4989 __ mulsd(value_reg, value_reg); |
| 4992 ASSERT(value_reg == locs()->out(0).fpu_reg()); | 4990 ASSERT(value_reg == locs()->out(0).fpu_reg()); |
| 4993 } else { | 4991 } else { |
| 4994 UNREACHABLE(); | 4992 UNREACHABLE(); |
| 4995 } | 4993 } |
| 4996 } | 4994 } |
| 4997 | 4995 |
| 4998 | 4996 |
| 4999 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( | 4997 LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary( |
| 5000 Zone* zone, bool opt) const { | 4998 Zone* zone, |
| 4999 bool opt) const { |
| 5001 const intptr_t kNumTemps = 0; | 5000 const intptr_t kNumTemps = 0; |
| 5002 LocationSummary* summary = new(zone) LocationSummary( | 5001 LocationSummary* summary = new (zone) |
| 5003 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5002 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 5004 summary->set_in(0, Location::RegisterLocation(CallingConventions::kArg1Reg)); | 5003 summary->set_in(0, Location::RegisterLocation(CallingConventions::kArg1Reg)); |
| 5005 summary->set_in(1, Location::RegisterLocation(CallingConventions::kArg2Reg)); | 5004 summary->set_in(1, Location::RegisterLocation(CallingConventions::kArg2Reg)); |
| 5006 summary->set_in(2, Location::RegisterLocation(CallingConventions::kArg3Reg)); | 5005 summary->set_in(2, Location::RegisterLocation(CallingConventions::kArg3Reg)); |
| 5007 summary->set_in(3, Location::RegisterLocation(CallingConventions::kArg4Reg)); | 5006 summary->set_in(3, Location::RegisterLocation(CallingConventions::kArg4Reg)); |
| 5008 summary->set_out(0, Location::RegisterLocation(RAX)); | 5007 summary->set_out(0, Location::RegisterLocation(RAX)); |
| 5009 return summary; | 5008 return summary; |
| 5010 } | 5009 } |
| 5011 | 5010 |
| 5012 | 5011 |
| 5013 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( | 5012 void CaseInsensitiveCompareUC16Instr::EmitNativeCode( |
| 5014 FlowGraphCompiler* compiler) { | 5013 FlowGraphCompiler* compiler) { |
| 5015 | |
| 5016 // Save RSP. R13 is chosen because it is callee saved so we do not need to | 5014 // Save RSP. R13 is chosen because it is callee saved so we do not need to |
| 5017 // back it up before calling into the runtime. | 5015 // back it up before calling into the runtime. |
| 5018 static const Register kSavedSPReg = R13; | 5016 static const Register kSavedSPReg = R13; |
| 5019 __ movq(kSavedSPReg, RSP); | 5017 __ movq(kSavedSPReg, RSP); |
| 5020 __ ReserveAlignedFrameSpace(0); | 5018 __ ReserveAlignedFrameSpace(0); |
| 5021 | 5019 |
| 5022 // Call the function. Parameters are already in their correct spots. | 5020 // Call the function. Parameters are already in their correct spots. |
| 5023 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); | 5021 __ CallRuntime(TargetFunction(), TargetFunction().argument_count()); |
| 5024 | 5022 |
| 5025 // Restore RSP. | 5023 // Restore RSP. |
| 5026 __ movq(RSP, kSavedSPReg); | 5024 __ movq(RSP, kSavedSPReg); |
| 5027 } | 5025 } |
| 5028 | 5026 |
| 5029 | 5027 |
| 5030 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, | 5028 LocationSummary* UnarySmiOpInstr::MakeLocationSummary(Zone* zone, |
| 5031 bool opt) const { | 5029 bool opt) const { |
| 5032 const intptr_t kNumInputs = 1; | 5030 const intptr_t kNumInputs = 1; |
| 5033 return LocationSummary::Make(zone, | 5031 return LocationSummary::Make(zone, kNumInputs, Location::SameAsFirstInput(), |
| 5034 kNumInputs, | |
| 5035 Location::SameAsFirstInput(), | |
| 5036 LocationSummary::kNoCall); | 5032 LocationSummary::kNoCall); |
| 5037 } | 5033 } |
| 5038 | 5034 |
| 5039 | 5035 |
| 5040 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5036 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5041 Register value = locs()->in(0).reg(); | 5037 Register value = locs()->in(0).reg(); |
| 5042 ASSERT(value == locs()->out(0).reg()); | 5038 ASSERT(value == locs()->out(0).reg()); |
| 5043 switch (op_kind()) { | 5039 switch (op_kind()) { |
| 5044 case Token::kNEGATE: { | 5040 case Token::kNEGATE: { |
| 5045 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); | 5041 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); |
| 5046 __ negq(value); | 5042 __ negq(value); |
| 5047 __ j(OVERFLOW, deopt); | 5043 __ j(OVERFLOW, deopt); |
| 5048 break; | 5044 break; |
| 5049 } | 5045 } |
| 5050 case Token::kBIT_NOT: | 5046 case Token::kBIT_NOT: |
| 5051 __ notq(value); | 5047 __ notq(value); |
| 5052 // Remove inverted smi-tag. | 5048 // Remove inverted smi-tag. |
| 5053 __ AndImmediate(value, Immediate(~kSmiTagMask)); | 5049 __ AndImmediate(value, Immediate(~kSmiTagMask)); |
| 5054 break; | 5050 break; |
| 5055 default: | 5051 default: |
| 5056 UNREACHABLE(); | 5052 UNREACHABLE(); |
| 5057 } | 5053 } |
| 5058 } | 5054 } |
| 5059 | 5055 |
| 5060 | 5056 |
| 5061 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 5057 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 5062 bool opt) const { | 5058 bool opt) const { |
| 5063 const intptr_t kNumInputs = 1; | 5059 const intptr_t kNumInputs = 1; |
| 5064 const intptr_t kNumTemps = 0; | 5060 const intptr_t kNumTemps = 0; |
| 5065 LocationSummary* summary = new(zone) LocationSummary( | 5061 LocationSummary* summary = new (zone) |
| 5066 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5062 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5067 summary->set_in(0, Location::RequiresFpuRegister()); | 5063 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5068 summary->set_out(0, Location::SameAsFirstInput()); | 5064 summary->set_out(0, Location::SameAsFirstInput()); |
| 5069 return summary; | 5065 return summary; |
| 5070 } | 5066 } |
| 5071 | 5067 |
| 5072 | 5068 |
| 5073 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5069 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5074 XmmRegister value = locs()->in(0).fpu_reg(); | 5070 XmmRegister value = locs()->in(0).fpu_reg(); |
| 5075 ASSERT(locs()->out(0).fpu_reg() == value); | 5071 ASSERT(locs()->out(0).fpu_reg() == value); |
| 5076 __ DoubleNegate(value); | 5072 __ DoubleNegate(value); |
| 5077 } | 5073 } |
| 5078 | 5074 |
| 5079 | 5075 |
| 5080 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, | 5076 LocationSummary* MathMinMaxInstr::MakeLocationSummary(Zone* zone, |
| 5081 bool opt) const { | 5077 bool opt) const { |
| 5082 if (result_cid() == kDoubleCid) { | 5078 if (result_cid() == kDoubleCid) { |
| 5083 const intptr_t kNumInputs = 2; | 5079 const intptr_t kNumInputs = 2; |
| 5084 const intptr_t kNumTemps = 1; | 5080 const intptr_t kNumTemps = 1; |
| 5085 LocationSummary* summary = new(zone) LocationSummary( | 5081 LocationSummary* summary = new (zone) |
| 5086 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5082 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5087 summary->set_in(0, Location::RequiresFpuRegister()); | 5083 summary->set_in(0, Location::RequiresFpuRegister()); |
| 5088 summary->set_in(1, Location::RequiresFpuRegister()); | 5084 summary->set_in(1, Location::RequiresFpuRegister()); |
| 5089 // Reuse the left register so that code can be made shorter. | 5085 // Reuse the left register so that code can be made shorter. |
| 5090 summary->set_out(0, Location::SameAsFirstInput()); | 5086 summary->set_out(0, Location::SameAsFirstInput()); |
| 5091 summary->set_temp(0, Location::RequiresRegister()); | 5087 summary->set_temp(0, Location::RequiresRegister()); |
| 5092 return summary; | 5088 return summary; |
| 5093 } | 5089 } |
| 5094 ASSERT(result_cid() == kSmiCid); | 5090 ASSERT(result_cid() == kSmiCid); |
| 5095 const intptr_t kNumInputs = 2; | 5091 const intptr_t kNumInputs = 2; |
| 5096 const intptr_t kNumTemps = 0; | 5092 const intptr_t kNumTemps = 0; |
| 5097 LocationSummary* summary = new(zone) LocationSummary( | 5093 LocationSummary* summary = new (zone) |
| 5098 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5094 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5099 summary->set_in(0, Location::RequiresRegister()); | 5095 summary->set_in(0, Location::RequiresRegister()); |
| 5100 summary->set_in(1, Location::RequiresRegister()); | 5096 summary->set_in(1, Location::RequiresRegister()); |
| 5101 // Reuse the left register so that code can be made shorter. | 5097 // Reuse the left register so that code can be made shorter. |
| 5102 summary->set_out(0, Location::SameAsFirstInput()); | 5098 summary->set_out(0, Location::SameAsFirstInput()); |
| 5103 return summary; | 5099 return summary; |
| 5104 } | 5100 } |
| 5105 | 5101 |
| 5106 | 5102 |
| 5107 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5103 void MathMinMaxInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5108 ASSERT((op_kind() == MethodRecognizer::kMathMin) || | 5104 ASSERT((op_kind() == MethodRecognizer::kMathMin) || |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5161 ASSERT(result == left); | 5157 ASSERT(result == left); |
| 5162 if (is_min) { | 5158 if (is_min) { |
| 5163 __ cmovgeq(result, right); | 5159 __ cmovgeq(result, right); |
| 5164 } else { | 5160 } else { |
| 5165 __ cmovlessq(result, right); | 5161 __ cmovlessq(result, right); |
| 5166 } | 5162 } |
| 5167 } | 5163 } |
| 5168 | 5164 |
| 5169 | 5165 |
| 5170 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, | 5166 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5171 bool opt) const { | 5167 bool opt) const { |
| 5172 const intptr_t kNumInputs = 1; | 5168 const intptr_t kNumInputs = 1; |
| 5173 const intptr_t kNumTemps = 0; | 5169 const intptr_t kNumTemps = 0; |
| 5174 LocationSummary* result = new(zone) LocationSummary( | 5170 LocationSummary* result = new (zone) |
| 5175 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5171 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5176 result->set_in(0, Location::RequiresRegister()); | 5172 result->set_in(0, Location::RequiresRegister()); |
| 5177 result->set_out(0, Location::RequiresFpuRegister()); | 5173 result->set_out(0, Location::RequiresFpuRegister()); |
| 5178 return result; | 5174 return result; |
| 5179 } | 5175 } |
| 5180 | 5176 |
| 5181 | 5177 |
| 5182 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5178 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5183 Register value = locs()->in(0).reg(); | 5179 Register value = locs()->in(0).reg(); |
| 5184 FpuRegister result = locs()->out(0).fpu_reg(); | 5180 FpuRegister result = locs()->out(0).fpu_reg(); |
| 5185 __ cvtsi2sdl(result, value); | 5181 __ cvtsi2sdl(result, value); |
| 5186 } | 5182 } |
| 5187 | 5183 |
| 5188 | 5184 |
| 5189 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, | 5185 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5190 bool opt) const { | 5186 bool opt) const { |
| 5191 const intptr_t kNumInputs = 1; | 5187 const intptr_t kNumInputs = 1; |
| 5192 const intptr_t kNumTemps = 0; | 5188 const intptr_t kNumTemps = 0; |
| 5193 LocationSummary* result = new(zone) LocationSummary( | 5189 LocationSummary* result = new (zone) |
| 5194 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5190 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5195 result->set_in(0, Location::WritableRegister()); | 5191 result->set_in(0, Location::WritableRegister()); |
| 5196 result->set_out(0, Location::RequiresFpuRegister()); | 5192 result->set_out(0, Location::RequiresFpuRegister()); |
| 5197 return result; | 5193 return result; |
| 5198 } | 5194 } |
| 5199 | 5195 |
| 5200 | 5196 |
| 5201 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5197 void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5202 Register value = locs()->in(0).reg(); | 5198 Register value = locs()->in(0).reg(); |
| 5203 FpuRegister result = locs()->out(0).fpu_reg(); | 5199 FpuRegister result = locs()->out(0).fpu_reg(); |
| 5204 __ SmiUntag(value); | 5200 __ SmiUntag(value); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5215 | 5211 |
| 5216 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5212 void MintToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5217 UNIMPLEMENTED(); | 5213 UNIMPLEMENTED(); |
| 5218 } | 5214 } |
| 5219 | 5215 |
| 5220 | 5216 |
| 5221 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, | 5217 LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone, |
| 5222 bool opt) const { | 5218 bool opt) const { |
| 5223 const intptr_t kNumInputs = 1; | 5219 const intptr_t kNumInputs = 1; |
| 5224 const intptr_t kNumTemps = 1; | 5220 const intptr_t kNumTemps = 1; |
| 5225 LocationSummary* result = new(zone) LocationSummary( | 5221 LocationSummary* result = new (zone) |
| 5226 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5222 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 5227 result->set_in(0, Location::RegisterLocation(RCX)); | 5223 result->set_in(0, Location::RegisterLocation(RCX)); |
| 5228 result->set_out(0, Location::RegisterLocation(RAX)); | 5224 result->set_out(0, Location::RegisterLocation(RAX)); |
| 5229 result->set_temp(0, Location::RegisterLocation(RBX)); | 5225 result->set_temp(0, Location::RegisterLocation(RBX)); |
| 5230 return result; | 5226 return result; |
| 5231 } | 5227 } |
| 5232 | 5228 |
| 5233 | 5229 |
| 5234 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5230 void DoubleToIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5235 Register result = locs()->out(0).reg(); | 5231 Register result = locs()->out(0).reg(); |
| 5236 Register value_obj = locs()->in(0).reg(); | 5232 Register value_obj = locs()->in(0).reg(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5250 __ SmiTag(result); | 5246 __ SmiTag(result); |
| 5251 __ jmp(&done); | 5247 __ jmp(&done); |
| 5252 __ Bind(&do_call); | 5248 __ Bind(&do_call); |
| 5253 ASSERT(instance_call()->HasICData()); | 5249 ASSERT(instance_call()->HasICData()); |
| 5254 const ICData& ic_data = *instance_call()->ic_data(); | 5250 const ICData& ic_data = *instance_call()->ic_data(); |
| 5255 ASSERT((ic_data.NumberOfChecks() == 1)); | 5251 ASSERT((ic_data.NumberOfChecks() == 1)); |
| 5256 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 5252 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
| 5257 | 5253 |
| 5258 const intptr_t kNumberOfArguments = 1; | 5254 const intptr_t kNumberOfArguments = 1; |
| 5259 __ pushq(value_obj); | 5255 __ pushq(value_obj); |
| 5260 compiler->GenerateStaticCall(deopt_id(), | 5256 compiler->GenerateStaticCall(deopt_id(), instance_call()->token_pos(), target, |
| 5261 instance_call()->token_pos(), | |
| 5262 target, | |
| 5263 kNumberOfArguments, | 5257 kNumberOfArguments, |
| 5264 Object::null_array(), // No argument names. | 5258 Object::null_array(), // No argument names. |
| 5265 locs(), | 5259 locs(), ICData::Handle()); |
| 5266 ICData::Handle()); | |
| 5267 __ Bind(&done); | 5260 __ Bind(&done); |
| 5268 } | 5261 } |
| 5269 | 5262 |
| 5270 | 5263 |
| 5271 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, | 5264 LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone, |
| 5272 bool opt) const { | 5265 bool opt) const { |
| 5273 const intptr_t kNumInputs = 1; | 5266 const intptr_t kNumInputs = 1; |
| 5274 const intptr_t kNumTemps = 1; | 5267 const intptr_t kNumTemps = 1; |
| 5275 LocationSummary* result = new(zone) LocationSummary( | 5268 LocationSummary* result = new (zone) |
| 5276 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5269 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5277 result->set_in(0, Location::RequiresFpuRegister()); | 5270 result->set_in(0, Location::RequiresFpuRegister()); |
| 5278 result->set_out(0, Location::RequiresRegister()); | 5271 result->set_out(0, Location::RequiresRegister()); |
| 5279 result->set_temp(0, Location::RequiresRegister()); | 5272 result->set_temp(0, Location::RequiresRegister()); |
| 5280 return result; | 5273 return result; |
| 5281 } | 5274 } |
| 5282 | 5275 |
| 5283 | 5276 |
| 5284 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5277 void DoubleToSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5285 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); | 5278 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptDoubleToSmi); |
| 5286 Register result = locs()->out(0).reg(); | 5279 Register result = locs()->out(0).reg(); |
| 5287 XmmRegister value = locs()->in(0).fpu_reg(); | 5280 XmmRegister value = locs()->in(0).fpu_reg(); |
| 5288 Register temp = locs()->temp(0).reg(); | 5281 Register temp = locs()->temp(0).reg(); |
| 5289 | 5282 |
| 5290 __ cvttsd2siq(result, value); | 5283 __ cvttsd2siq(result, value); |
| 5291 // Overflow is signalled with minint. | 5284 // Overflow is signalled with minint. |
| 5292 Label do_call, done; | 5285 Label do_call, done; |
| 5293 // Check for overflow and that it fits into Smi. | 5286 // Check for overflow and that it fits into Smi. |
| 5294 __ movq(temp, result); | 5287 __ movq(temp, result); |
| 5295 __ shlq(temp, Immediate(1)); | 5288 __ shlq(temp, Immediate(1)); |
| 5296 __ j(OVERFLOW, deopt); | 5289 __ j(OVERFLOW, deopt); |
| 5297 __ SmiTag(result); | 5290 __ SmiTag(result); |
| 5298 } | 5291 } |
| 5299 | 5292 |
| 5300 | 5293 |
| 5301 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, | 5294 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5302 bool opt) const { | 5295 bool opt) const { |
| 5303 const intptr_t kNumInputs = 1; | 5296 const intptr_t kNumInputs = 1; |
| 5304 const intptr_t kNumTemps = 0; | 5297 const intptr_t kNumTemps = 0; |
| 5305 LocationSummary* result = new(zone) LocationSummary( | 5298 LocationSummary* result = new (zone) |
| 5306 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5299 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5307 result->set_in(0, Location::RequiresFpuRegister()); | 5300 result->set_in(0, Location::RequiresFpuRegister()); |
| 5308 result->set_out(0, Location::RequiresFpuRegister()); | 5301 result->set_out(0, Location::RequiresFpuRegister()); |
| 5309 return result; | 5302 return result; |
| 5310 } | 5303 } |
| 5311 | 5304 |
| 5312 | 5305 |
| 5313 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5306 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5314 XmmRegister value = locs()->in(0).fpu_reg(); | 5307 XmmRegister value = locs()->in(0).fpu_reg(); |
| 5315 XmmRegister result = locs()->out(0).fpu_reg(); | 5308 XmmRegister result = locs()->out(0).fpu_reg(); |
| 5316 switch (recognized_kind()) { | 5309 switch (recognized_kind()) { |
| 5317 case MethodRecognizer::kDoubleTruncate: | 5310 case MethodRecognizer::kDoubleTruncate: |
| 5318 __ roundsd(result, value, Assembler::kRoundToZero); | 5311 __ roundsd(result, value, Assembler::kRoundToZero); |
| 5319 break; | 5312 break; |
| 5320 case MethodRecognizer::kDoubleFloor: | 5313 case MethodRecognizer::kDoubleFloor: |
| 5321 __ roundsd(result, value, Assembler::kRoundDown); | 5314 __ roundsd(result, value, Assembler::kRoundDown); |
| 5322 break; | 5315 break; |
| 5323 case MethodRecognizer::kDoubleCeil: | 5316 case MethodRecognizer::kDoubleCeil: |
| 5324 __ roundsd(result, value, Assembler::kRoundUp); | 5317 __ roundsd(result, value, Assembler::kRoundUp); |
| 5325 break; | 5318 break; |
| 5326 default: | 5319 default: |
| 5327 UNREACHABLE(); | 5320 UNREACHABLE(); |
| 5328 } | 5321 } |
| 5329 } | 5322 } |
| 5330 | 5323 |
| 5331 | 5324 |
| 5332 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, | 5325 LocationSummary* DoubleToFloatInstr::MakeLocationSummary(Zone* zone, |
| 5333 bool opt) const { | 5326 bool opt) const { |
| 5334 const intptr_t kNumInputs = 1; | 5327 const intptr_t kNumInputs = 1; |
| 5335 const intptr_t kNumTemps = 0; | 5328 const intptr_t kNumTemps = 0; |
| 5336 LocationSummary* result = new(zone) LocationSummary( | 5329 LocationSummary* result = new (zone) |
| 5337 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5330 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5338 result->set_in(0, Location::RequiresFpuRegister()); | 5331 result->set_in(0, Location::RequiresFpuRegister()); |
| 5339 result->set_out(0, Location::SameAsFirstInput()); | 5332 result->set_out(0, Location::SameAsFirstInput()); |
| 5340 return result; | 5333 return result; |
| 5341 } | 5334 } |
| 5342 | 5335 |
| 5343 | 5336 |
| 5344 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5337 void DoubleToFloatInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5345 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5338 __ cvtsd2ss(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 5346 } | 5339 } |
| 5347 | 5340 |
| 5348 | 5341 |
| 5349 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, | 5342 LocationSummary* FloatToDoubleInstr::MakeLocationSummary(Zone* zone, |
| 5350 bool opt) const { | 5343 bool opt) const { |
| 5351 const intptr_t kNumInputs = 1; | 5344 const intptr_t kNumInputs = 1; |
| 5352 const intptr_t kNumTemps = 0; | 5345 const intptr_t kNumTemps = 0; |
| 5353 LocationSummary* result = new(zone) LocationSummary( | 5346 LocationSummary* result = new (zone) |
| 5354 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5347 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5355 result->set_in(0, Location::RequiresFpuRegister()); | 5348 result->set_in(0, Location::RequiresFpuRegister()); |
| 5356 result->set_out(0, Location::SameAsFirstInput()); | 5349 result->set_out(0, Location::SameAsFirstInput()); |
| 5357 return result; | 5350 return result; |
| 5358 } | 5351 } |
| 5359 | 5352 |
| 5360 | 5353 |
| 5361 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5354 void FloatToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5362 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); | 5355 __ cvtss2sd(locs()->out(0).fpu_reg(), locs()->in(0).fpu_reg()); |
| 5363 } | 5356 } |
| 5364 | 5357 |
| 5365 | 5358 |
| 5366 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, | 5359 LocationSummary* InvokeMathCFunctionInstr::MakeLocationSummary(Zone* zone, |
| 5367 bool opt) const { | 5360 bool opt) const { |
| 5368 // Calling convention on x64 uses XMM0 and XMM1 to pass the first two | 5361 // Calling convention on x64 uses XMM0 and XMM1 to pass the first two |
| 5369 // double arguments and XMM0 to return the result. Unfortunately | 5362 // double arguments and XMM0 to return the result. Unfortunately |
| 5370 // currently we can't specify these registers because ParallelMoveResolver | 5363 // currently we can't specify these registers because ParallelMoveResolver |
| 5371 // assumes that XMM0 is free at all times. | 5364 // assumes that XMM0 is free at all times. |
| 5372 // TODO(vegorov): allow XMM0 to be used. | 5365 // TODO(vegorov): allow XMM0 to be used. |
| 5373 ASSERT((InputCount() == 1) || (InputCount() == 2)); | 5366 ASSERT((InputCount() == 1) || (InputCount() == 2)); |
| 5374 const intptr_t kNumTemps = | 5367 const intptr_t kNumTemps = |
| 5375 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; | 5368 (recognized_kind() == MethodRecognizer::kMathDoublePow) ? 3 : 1; |
| 5376 LocationSummary* result = new(zone) LocationSummary( | 5369 LocationSummary* result = new (zone) |
| 5377 zone, InputCount(), kNumTemps, LocationSummary::kCall); | 5370 LocationSummary(zone, InputCount(), kNumTemps, LocationSummary::kCall); |
| 5378 ASSERT(R13 != CALLEE_SAVED_TEMP); | 5371 ASSERT(R13 != CALLEE_SAVED_TEMP); |
| 5379 ASSERT(((1 << R13) & CallingConventions::kCalleeSaveCpuRegisters) != 0); | 5372 ASSERT(((1 << R13) & CallingConventions::kCalleeSaveCpuRegisters) != 0); |
| 5380 result->set_temp(0, Location::RegisterLocation(R13)); | 5373 result->set_temp(0, Location::RegisterLocation(R13)); |
| 5381 result->set_in(0, Location::FpuRegisterLocation(XMM2)); | 5374 result->set_in(0, Location::FpuRegisterLocation(XMM2)); |
| 5382 if (InputCount() == 2) { | 5375 if (InputCount() == 2) { |
| 5383 result->set_in(1, Location::FpuRegisterLocation(XMM1)); | 5376 result->set_in(1, Location::FpuRegisterLocation(XMM1)); |
| 5384 } | 5377 } |
| 5385 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { | 5378 if (recognized_kind() == MethodRecognizer::kMathDoublePow) { |
| 5386 // Temp index 1. | 5379 // Temp index 1. |
| 5387 result->set_temp(1, Location::RegisterLocation(RAX)); | 5380 result->set_temp(1, Location::RegisterLocation(RAX)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 5411 static void InvokeDoublePow(FlowGraphCompiler* compiler, | 5404 static void InvokeDoublePow(FlowGraphCompiler* compiler, |
| 5412 InvokeMathCFunctionInstr* instr) { | 5405 InvokeMathCFunctionInstr* instr) { |
| 5413 ASSERT(instr->recognized_kind() == MethodRecognizer::kMathDoublePow); | 5406 ASSERT(instr->recognized_kind() == MethodRecognizer::kMathDoublePow); |
| 5414 const intptr_t kInputCount = 2; | 5407 const intptr_t kInputCount = 2; |
| 5415 ASSERT(instr->InputCount() == kInputCount); | 5408 ASSERT(instr->InputCount() == kInputCount); |
| 5416 LocationSummary* locs = instr->locs(); | 5409 LocationSummary* locs = instr->locs(); |
| 5417 | 5410 |
| 5418 XmmRegister base = locs->in(0).fpu_reg(); | 5411 XmmRegister base = locs->in(0).fpu_reg(); |
| 5419 XmmRegister exp = locs->in(1).fpu_reg(); | 5412 XmmRegister exp = locs->in(1).fpu_reg(); |
| 5420 XmmRegister result = locs->out(0).fpu_reg(); | 5413 XmmRegister result = locs->out(0).fpu_reg(); |
| 5421 Register temp = | 5414 Register temp = locs->temp(InvokeMathCFunctionInstr::kObjectTempIndex).reg(); |
| 5422 locs->temp(InvokeMathCFunctionInstr::kObjectTempIndex).reg(); | |
| 5423 XmmRegister zero_temp = | 5415 XmmRegister zero_temp = |
| 5424 locs->temp(InvokeMathCFunctionInstr::kDoubleTempIndex).fpu_reg(); | 5416 locs->temp(InvokeMathCFunctionInstr::kDoubleTempIndex).fpu_reg(); |
| 5425 | 5417 |
| 5426 __ xorps(zero_temp, zero_temp); | 5418 __ xorps(zero_temp, zero_temp); |
| 5427 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1))); | 5419 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1))); |
| 5428 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 5420 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 5429 | 5421 |
| 5430 Label check_base, skip_call; | 5422 Label check_base, skip_call; |
| 5431 // exponent == 0.0 -> return 1.0; | 5423 // exponent == 0.0 -> return 1.0; |
| 5432 __ comisd(exp, zero_temp); | 5424 __ comisd(exp, zero_temp); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5481 __ j(PARITY_ODD, &try_sqrt, Assembler::kNearJump); | 5473 __ j(PARITY_ODD, &try_sqrt, Assembler::kNearJump); |
| 5482 // Return NaN. | 5474 // Return NaN. |
| 5483 __ Bind(&return_nan); | 5475 __ Bind(&return_nan); |
| 5484 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN))); | 5476 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN))); |
| 5485 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 5477 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 5486 __ jmp(&skip_call); | 5478 __ jmp(&skip_call); |
| 5487 | 5479 |
| 5488 Label do_pow, return_zero; | 5480 Label do_pow, return_zero; |
| 5489 __ Bind(&try_sqrt); | 5481 __ Bind(&try_sqrt); |
| 5490 // Before calling pow, check if we could use sqrt instead of pow. | 5482 // Before calling pow, check if we could use sqrt instead of pow. |
| 5491 __ LoadObject(temp, | 5483 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(kNegInfinity))); |
| 5492 Double::ZoneHandle(Double::NewCanonical(kNegInfinity))); | |
| 5493 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 5484 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 5494 // base == -Infinity -> call pow; | 5485 // base == -Infinity -> call pow; |
| 5495 __ comisd(base, result); | 5486 __ comisd(base, result); |
| 5496 __ j(EQUAL, &do_pow, Assembler::kNearJump); | 5487 __ j(EQUAL, &do_pow, Assembler::kNearJump); |
| 5497 | 5488 |
| 5498 // exponent == 0.5 ? | 5489 // exponent == 0.5 ? |
| 5499 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5))); | 5490 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5))); |
| 5500 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 5491 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 5501 __ comisd(exp, result); | 5492 __ comisd(exp, result); |
| 5502 __ j(NOT_EQUAL, &do_pow, Assembler::kNearJump); | 5493 __ j(NOT_EQUAL, &do_pow, Assembler::kNearJump); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5546 // Restore RSP. | 5537 // Restore RSP. |
| 5547 __ movq(RSP, locs()->temp(kSavedSpTempIndex).reg()); | 5538 __ movq(RSP, locs()->temp(kSavedSpTempIndex).reg()); |
| 5548 } | 5539 } |
| 5549 | 5540 |
| 5550 | 5541 |
| 5551 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, | 5542 LocationSummary* ExtractNthOutputInstr::MakeLocationSummary(Zone* zone, |
| 5552 bool opt) const { | 5543 bool opt) const { |
| 5553 // Only use this instruction in optimized code. | 5544 // Only use this instruction in optimized code. |
| 5554 ASSERT(opt); | 5545 ASSERT(opt); |
| 5555 const intptr_t kNumInputs = 1; | 5546 const intptr_t kNumInputs = 1; |
| 5556 LocationSummary* summary = new(zone) LocationSummary( | 5547 LocationSummary* summary = |
| 5557 zone, kNumInputs, 0, LocationSummary::kNoCall); | 5548 new (zone) LocationSummary(zone, kNumInputs, 0, LocationSummary::kNoCall); |
| 5558 if (representation() == kUnboxedDouble) { | 5549 if (representation() == kUnboxedDouble) { |
| 5559 if (index() == 0) { | 5550 if (index() == 0) { |
| 5560 summary->set_in(0, Location::Pair(Location::RequiresFpuRegister(), | 5551 summary->set_in( |
| 5561 Location::Any())); | 5552 0, Location::Pair(Location::RequiresFpuRegister(), Location::Any())); |
| 5562 } else { | 5553 } else { |
| 5563 ASSERT(index() == 1); | 5554 ASSERT(index() == 1); |
| 5564 summary->set_in(0, Location::Pair(Location::Any(), | 5555 summary->set_in( |
| 5565 Location::RequiresFpuRegister())); | 5556 0, Location::Pair(Location::Any(), Location::RequiresFpuRegister())); |
| 5566 } | 5557 } |
| 5567 summary->set_out(0, Location::RequiresFpuRegister()); | 5558 summary->set_out(0, Location::RequiresFpuRegister()); |
| 5568 } else { | 5559 } else { |
| 5569 ASSERT(representation() == kTagged); | 5560 ASSERT(representation() == kTagged); |
| 5570 if (index() == 0) { | 5561 if (index() == 0) { |
| 5571 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 5562 summary->set_in( |
| 5572 Location::Any())); | 5563 0, Location::Pair(Location::RequiresRegister(), Location::Any())); |
| 5573 } else { | 5564 } else { |
| 5574 ASSERT(index() == 1); | 5565 ASSERT(index() == 1); |
| 5575 summary->set_in(0, Location::Pair(Location::Any(), | 5566 summary->set_in( |
| 5576 Location::RequiresRegister())); | 5567 0, Location::Pair(Location::Any(), Location::RequiresRegister())); |
| 5577 } | 5568 } |
| 5578 summary->set_out(0, Location::RequiresRegister()); | 5569 summary->set_out(0, Location::RequiresRegister()); |
| 5579 } | 5570 } |
| 5580 return summary; | 5571 return summary; |
| 5581 } | 5572 } |
| 5582 | 5573 |
| 5583 | 5574 |
| 5584 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5575 void ExtractNthOutputInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5585 ASSERT(locs()->in(0).IsPairLocation()); | 5576 ASSERT(locs()->in(0).IsPairLocation()); |
| 5586 PairLocation* pair = locs()->in(0).AsPairLocation(); | 5577 PairLocation* pair = locs()->in(0).AsPairLocation(); |
| 5587 Location in_loc = pair->At(index()); | 5578 Location in_loc = pair->At(index()); |
| 5588 if (representation() == kUnboxedDouble) { | 5579 if (representation() == kUnboxedDouble) { |
| 5589 XmmRegister out = locs()->out(0).fpu_reg(); | 5580 XmmRegister out = locs()->out(0).fpu_reg(); |
| 5590 XmmRegister in = in_loc.fpu_reg(); | 5581 XmmRegister in = in_loc.fpu_reg(); |
| 5591 __ movaps(out, in); | 5582 __ movaps(out, in); |
| 5592 } else { | 5583 } else { |
| 5593 ASSERT(representation() == kTagged); | 5584 ASSERT(representation() == kTagged); |
| 5594 Register out = locs()->out(0).reg(); | 5585 Register out = locs()->out(0).reg(); |
| 5595 Register in = in_loc.reg(); | 5586 Register in = in_loc.reg(); |
| 5596 __ movq(out, in); | 5587 __ movq(out, in); |
| 5597 } | 5588 } |
| 5598 } | 5589 } |
| 5599 | 5590 |
| 5600 | 5591 |
| 5601 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, | 5592 LocationSummary* MergedMathInstr::MakeLocationSummary(Zone* zone, |
| 5602 bool opt) const { | 5593 bool opt) const { |
| 5603 if (kind() == MergedMathInstr::kTruncDivMod) { | 5594 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 5604 const intptr_t kNumInputs = 2; | 5595 const intptr_t kNumInputs = 2; |
| 5605 const intptr_t kNumTemps = 0; | 5596 const intptr_t kNumTemps = 0; |
| 5606 LocationSummary* summary = new(zone) LocationSummary( | 5597 LocationSummary* summary = new (zone) |
| 5607 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5598 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5608 // Both inputs must be writable because they will be untagged. | 5599 // Both inputs must be writable because they will be untagged. |
| 5609 summary->set_in(0, Location::RegisterLocation(RAX)); | 5600 summary->set_in(0, Location::RegisterLocation(RAX)); |
| 5610 summary->set_in(1, Location::WritableRegister()); | 5601 summary->set_in(1, Location::WritableRegister()); |
| 5611 summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX), | 5602 summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX), |
| 5612 Location::RegisterLocation(RDX))); | 5603 Location::RegisterLocation(RDX))); |
| 5613 return summary; | 5604 return summary; |
| 5614 } | 5605 } |
| 5615 if (kind() == MergedMathInstr::kSinCos) { | 5606 if (kind() == MergedMathInstr::kSinCos) { |
| 5616 const intptr_t kNumInputs = 1; | 5607 const intptr_t kNumInputs = 1; |
| 5617 const intptr_t kNumTemps = 1; | 5608 const intptr_t kNumTemps = 1; |
| 5618 LocationSummary* summary = new(zone) LocationSummary( | 5609 LocationSummary* summary = new (zone) |
| 5619 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 5610 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 5620 // Because we always call into the runtime (LocationSummary::kCall) we | 5611 // Because we always call into the runtime (LocationSummary::kCall) we |
| 5621 // must specify each input, temp, and output register explicitly. | 5612 // must specify each input, temp, and output register explicitly. |
| 5622 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); | 5613 summary->set_in(0, Location::FpuRegisterLocation(XMM1)); |
| 5623 // R13 is chosen because it is callee saved so we do not need to back it | 5614 // R13 is chosen because it is callee saved so we do not need to back it |
| 5624 // up before calling into the runtime. | 5615 // up before calling into the runtime. |
| 5625 summary->set_temp(0, Location::RegisterLocation(R13)); | 5616 summary->set_temp(0, Location::RegisterLocation(R13)); |
| 5626 summary->set_out(0, Location::Pair(Location::FpuRegisterLocation(XMM2), | 5617 summary->set_out(0, Location::Pair(Location::FpuRegisterLocation(XMM2), |
| 5627 Location::FpuRegisterLocation(XMM3))); | 5618 Location::FpuRegisterLocation(XMM3))); |
| 5628 return summary; | 5619 return summary; |
| 5629 } | 5620 } |
| 5630 UNIMPLEMENTED(); | 5621 UNIMPLEMENTED(); |
| 5631 return NULL; | 5622 return NULL; |
| 5632 } | 5623 } |
| 5633 | 5624 |
| 5634 | 5625 |
| 5635 | 5626 typedef void (*SinCosCFunction)(double x, double* res_sin, double* res_cos); |
| 5636 typedef void (*SinCosCFunction) (double x, double* res_sin, double* res_cos); | |
| 5637 | 5627 |
| 5638 extern const RuntimeEntry kSinCosRuntimeEntry( | 5628 extern const RuntimeEntry kSinCosRuntimeEntry( |
| 5639 "libc_sincos", reinterpret_cast<RuntimeFunction>( | 5629 "libc_sincos", |
| 5640 static_cast<SinCosCFunction>(&SinCos)), 1, true, true); | 5630 reinterpret_cast<RuntimeFunction>(static_cast<SinCosCFunction>(&SinCos)), |
| 5631 1, |
| 5632 true, |
| 5633 true); |
| 5641 | 5634 |
| 5642 | 5635 |
| 5643 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5636 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5644 Label* deopt = NULL; | 5637 Label* deopt = NULL; |
| 5645 if (CanDeoptimize()) { | 5638 if (CanDeoptimize()) { |
| 5646 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 5639 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
| 5647 } | 5640 } |
| 5648 if (kind() == MergedMathInstr::kTruncDivMod) { | 5641 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 5649 Register left = locs()->in(0).reg(); | 5642 Register left = locs()->in(0).reg(); |
| 5650 Register right = locs()->in(1).reg(); | 5643 Register right = locs()->in(1).reg(); |
| 5651 ASSERT(locs()->out(0).IsPairLocation()); | 5644 ASSERT(locs()->out(0).IsPairLocation()); |
| 5652 PairLocation* pair = locs()->out(0).AsPairLocation(); | 5645 PairLocation* pair = locs()->out(0).AsPairLocation(); |
| 5653 Register result1 = pair->At(0).reg(); | 5646 Register result1 = pair->At(0).reg(); |
| 5654 Register result2 = pair->At(1).reg(); | 5647 Register result2 = pair->At(1).reg(); |
| 5655 Label not_32bit, done; | 5648 Label not_32bit, done; |
| 5656 Register temp = RDX; | 5649 Register temp = RDX; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 5682 __ cdq(); | 5675 __ cdq(); |
| 5683 __ idivl(right); | 5676 __ idivl(right); |
| 5684 __ movsxd(RAX, RAX); | 5677 __ movsxd(RAX, RAX); |
| 5685 __ movsxd(RDX, RDX); | 5678 __ movsxd(RDX, RDX); |
| 5686 __ jmp(&done); | 5679 __ jmp(&done); |
| 5687 | 5680 |
| 5688 // Divide using 64bit idiv. | 5681 // Divide using 64bit idiv. |
| 5689 __ Bind(¬_32bit); | 5682 __ Bind(¬_32bit); |
| 5690 __ SmiUntag(left); | 5683 __ SmiUntag(left); |
| 5691 __ SmiUntag(right); | 5684 __ SmiUntag(right); |
| 5692 __ cqo(); // Sign extend RAX -> RDX:RAX. | 5685 __ cqo(); // Sign extend RAX -> RDX:RAX. |
| 5693 __ idivq(right); // RAX: quotient, RDX: remainder. | 5686 __ idivq(right); // RAX: quotient, RDX: remainder. |
| 5694 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 5687 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 5695 // case we cannot tag the result. | 5688 // case we cannot tag the result. |
| 5696 __ CompareImmediate(RAX, Immediate(0x4000000000000000)); | 5689 __ CompareImmediate(RAX, Immediate(0x4000000000000000)); |
| 5697 __ j(EQUAL, deopt); | 5690 __ j(EQUAL, deopt); |
| 5698 __ Bind(&done); | 5691 __ Bind(&done); |
| 5699 | 5692 |
| 5700 // Modulo correction (RDX). | 5693 // Modulo correction (RDX). |
| 5701 // res = left % right; | 5694 // res = left % right; |
| 5702 // if (res < 0) { | 5695 // if (res < 0) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5755 // .... | 5748 // .... |
| 5756 __ ReserveAlignedFrameSpace(kDoubleSize * 3 + kWordSize * 2); | 5749 __ ReserveAlignedFrameSpace(kDoubleSize * 3 + kWordSize * 2); |
| 5757 __ movsd(Address(RSP, 0), locs()->in(0).fpu_reg()); | 5750 __ movsd(Address(RSP, 0), locs()->in(0).fpu_reg()); |
| 5758 | 5751 |
| 5759 __ leaq(RDI, Address(RSP, 2 * kWordSize + kDoubleSize)); | 5752 __ leaq(RDI, Address(RSP, 2 * kWordSize + kDoubleSize)); |
| 5760 __ leaq(RSI, Address(RSP, 2 * kWordSize + 2 * kDoubleSize)); | 5753 __ leaq(RSI, Address(RSP, 2 * kWordSize + 2 * kDoubleSize)); |
| 5761 __ movaps(XMM0, locs()->in(0).fpu_reg()); | 5754 __ movaps(XMM0, locs()->in(0).fpu_reg()); |
| 5762 | 5755 |
| 5763 __ CallRuntime(kSinCosRuntimeEntry, InputCount()); | 5756 __ CallRuntime(kSinCosRuntimeEntry, InputCount()); |
| 5764 __ movsd(out2, Address(RSP, 2 * kWordSize + kDoubleSize * 2)); // sin. | 5757 __ movsd(out2, Address(RSP, 2 * kWordSize + kDoubleSize * 2)); // sin. |
| 5765 __ movsd(out1, Address(RSP, 2 * kWordSize + kDoubleSize)); // cos. | 5758 __ movsd(out1, Address(RSP, 2 * kWordSize + kDoubleSize)); // cos. |
| 5766 // Restore RSP. | 5759 // Restore RSP. |
| 5767 __ movq(RSP, locs()->temp(0).reg()); | 5760 __ movq(RSP, locs()->temp(0).reg()); |
| 5768 | 5761 |
| 5769 return; | 5762 return; |
| 5770 } | 5763 } |
| 5771 UNIMPLEMENTED(); | 5764 UNIMPLEMENTED(); |
| 5772 } | 5765 } |
| 5773 | 5766 |
| 5774 | 5767 |
| 5775 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( | 5768 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( |
| 5776 Zone* zone, bool opt) const { | 5769 Zone* zone, |
| 5770 bool opt) const { |
| 5777 return MakeCallSummary(zone); | 5771 return MakeCallSummary(zone); |
| 5778 } | 5772 } |
| 5779 | 5773 |
| 5780 | 5774 |
| 5781 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, | 5775 LocationSummary* BranchInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 5782 bool opt) const { | |
| 5783 comparison()->InitializeLocationSummary(zone, opt); | 5776 comparison()->InitializeLocationSummary(zone, opt); |
| 5784 // Branches don't produce a result. | 5777 // Branches don't produce a result. |
| 5785 comparison()->locs()->set_out(0, Location::NoLocation()); | 5778 comparison()->locs()->set_out(0, Location::NoLocation()); |
| 5786 return comparison()->locs(); | 5779 return comparison()->locs(); |
| 5787 } | 5780 } |
| 5788 | 5781 |
| 5789 | 5782 |
| 5790 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5783 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5791 comparison()->EmitBranchCode(compiler, this); | 5784 comparison()->EmitBranchCode(compiler, this); |
| 5792 } | 5785 } |
| 5793 | 5786 |
| 5794 | 5787 |
| 5795 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, | 5788 LocationSummary* CheckClassInstr::MakeLocationSummary(Zone* zone, |
| 5796 bool opt) const { | 5789 bool opt) const { |
| 5797 const intptr_t kNumInputs = 1; | 5790 const intptr_t kNumInputs = 1; |
| 5798 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); | 5791 const bool need_mask_temp = IsDenseSwitch() && !IsDenseMask(ComputeCidMask()); |
| 5799 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; | 5792 const intptr_t kNumTemps = !IsNullCheck() ? (need_mask_temp ? 2 : 1) : 0; |
| 5800 LocationSummary* summary = new(zone) LocationSummary( | 5793 LocationSummary* summary = new (zone) |
| 5801 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5794 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5802 summary->set_in(0, Location::RequiresRegister()); | 5795 summary->set_in(0, Location::RequiresRegister()); |
| 5803 if (!IsNullCheck()) { | 5796 if (!IsNullCheck()) { |
| 5804 summary->set_temp(0, Location::RequiresRegister()); | 5797 summary->set_temp(0, Location::RequiresRegister()); |
| 5805 if (need_mask_temp) { | 5798 if (need_mask_temp) { |
| 5806 summary->set_temp(1, Location::RequiresRegister()); | 5799 summary->set_temp(1, Location::RequiresRegister()); |
| 5807 } | 5800 } |
| 5808 } | 5801 } |
| 5809 return summary; | 5802 return summary; |
| 5810 } | 5803 } |
| 5811 | 5804 |
| 5812 | 5805 |
| 5813 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5806 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5814 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5807 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass, |
| 5815 ICData::kDeoptCheckClass, | |
| 5816 licm_hoisted_ ? ICData::kHoisted : 0); | 5808 licm_hoisted_ ? ICData::kHoisted : 0); |
| 5817 if (IsNullCheck()) { | 5809 if (IsNullCheck()) { |
| 5818 __ CompareObject(locs()->in(0).reg(), | 5810 __ CompareObject(locs()->in(0).reg(), Object::null_object()); |
| 5819 Object::null_object()); | |
| 5820 Condition cond = DeoptIfNull() ? EQUAL : NOT_EQUAL; | 5811 Condition cond = DeoptIfNull() ? EQUAL : NOT_EQUAL; |
| 5821 __ j(cond, deopt); | 5812 __ j(cond, deopt); |
| 5822 return; | 5813 return; |
| 5823 } | 5814 } |
| 5824 | 5815 |
| 5825 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 5816 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
| 5826 (unary_checks().NumberOfChecks() > 1)); | 5817 (unary_checks().NumberOfChecks() > 1)); |
| 5827 Register value = locs()->in(0).reg(); | 5818 Register value = locs()->in(0).reg(); |
| 5828 Register temp = locs()->temp(0).reg(); | 5819 Register temp = locs()->temp(0).reg(); |
| 5829 Label is_ok; | 5820 Label is_ok; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 5846 if (!IsDenseMask(mask)) { | 5837 if (!IsDenseMask(mask)) { |
| 5847 // Only need mask if there are missing numbers in the range. | 5838 // Only need mask if there are missing numbers in the range. |
| 5848 ASSERT(cids_.length() > 2); | 5839 ASSERT(cids_.length() > 2); |
| 5849 Register mask_reg = locs()->temp(1).reg(); | 5840 Register mask_reg = locs()->temp(1).reg(); |
| 5850 __ movq(mask_reg, Immediate(mask)); | 5841 __ movq(mask_reg, Immediate(mask)); |
| 5851 __ btq(mask_reg, temp); | 5842 __ btq(mask_reg, temp); |
| 5852 __ j(NOT_CARRY, deopt); | 5843 __ j(NOT_CARRY, deopt); |
| 5853 } | 5844 } |
| 5854 } else { | 5845 } else { |
| 5855 GrowableArray<CidTarget> sorted_ic_data; | 5846 GrowableArray<CidTarget> sorted_ic_data; |
| 5856 FlowGraphCompiler::SortICDataByCount(unary_checks(), | 5847 FlowGraphCompiler::SortICDataByCount(unary_checks(), &sorted_ic_data, |
| 5857 &sorted_ic_data, | |
| 5858 /* drop_smi = */ true); | 5848 /* drop_smi = */ true); |
| 5859 const intptr_t num_checks = sorted_ic_data.length(); | 5849 const intptr_t num_checks = sorted_ic_data.length(); |
| 5860 const bool use_near_jump = num_checks < 5; | 5850 const bool use_near_jump = num_checks < 5; |
| 5861 for (intptr_t i = 0; i < num_checks; i++) { | 5851 for (intptr_t i = 0; i < num_checks; i++) { |
| 5862 const intptr_t cid = sorted_ic_data[i].cid; | 5852 const intptr_t cid = sorted_ic_data[i].cid; |
| 5863 __ cmpl(temp, Immediate(cid)); | 5853 __ cmpl(temp, Immediate(cid)); |
| 5864 if (i == (num_checks - 1)) { | 5854 if (i == (num_checks - 1)) { |
| 5865 __ j(NOT_EQUAL, deopt); | 5855 __ j(NOT_EQUAL, deopt); |
| 5866 } else { | 5856 } else { |
| 5867 if (use_near_jump) { | 5857 if (use_near_jump) { |
| 5868 __ j(EQUAL, &is_ok, Assembler::kNearJump); | 5858 __ j(EQUAL, &is_ok, Assembler::kNearJump); |
| 5869 } else { | 5859 } else { |
| 5870 __ j(EQUAL, &is_ok); | 5860 __ j(EQUAL, &is_ok); |
| 5871 } | 5861 } |
| 5872 } | 5862 } |
| 5873 } | 5863 } |
| 5874 } | 5864 } |
| 5875 __ Bind(&is_ok); | 5865 __ Bind(&is_ok); |
| 5876 } | 5866 } |
| 5877 | 5867 |
| 5878 | 5868 |
| 5879 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, | 5869 LocationSummary* CheckSmiInstr::MakeLocationSummary(Zone* zone, |
| 5880 bool opt) const { | 5870 bool opt) const { |
| 5881 const intptr_t kNumInputs = 1; | 5871 const intptr_t kNumInputs = 1; |
| 5882 const intptr_t kNumTemps = 0; | 5872 const intptr_t kNumTemps = 0; |
| 5883 LocationSummary* summary = new(zone) LocationSummary( | 5873 LocationSummary* summary = new (zone) |
| 5884 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5874 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5885 summary->set_in(0, Location::RequiresRegister()); | 5875 summary->set_in(0, Location::RequiresRegister()); |
| 5886 return summary; | 5876 return summary; |
| 5887 } | 5877 } |
| 5888 | 5878 |
| 5889 | 5879 |
| 5890 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5880 void CheckSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5891 Register value = locs()->in(0).reg(); | 5881 Register value = locs()->in(0).reg(); |
| 5892 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5882 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckSmi, |
| 5893 ICData::kDeoptCheckSmi, | |
| 5894 licm_hoisted_ ? ICData::kHoisted : 0); | 5883 licm_hoisted_ ? ICData::kHoisted : 0); |
| 5895 __ BranchIfNotSmi(value, deopt); | 5884 __ BranchIfNotSmi(value, deopt); |
| 5896 } | 5885 } |
| 5897 | 5886 |
| 5898 | 5887 |
| 5899 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, | 5888 LocationSummary* CheckClassIdInstr::MakeLocationSummary(Zone* zone, |
| 5900 bool opt) const { | 5889 bool opt) const { |
| 5901 const intptr_t kNumInputs = 1; | 5890 const intptr_t kNumInputs = 1; |
| 5902 const intptr_t kNumTemps = 0; | 5891 const intptr_t kNumTemps = 0; |
| 5903 LocationSummary* summary = new(zone) LocationSummary( | 5892 LocationSummary* summary = new (zone) |
| 5904 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5893 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5905 summary->set_in(0, Location::RequiresRegister()); | 5894 summary->set_in(0, Location::RequiresRegister()); |
| 5906 return summary; | 5895 return summary; |
| 5907 } | 5896 } |
| 5908 | 5897 |
| 5909 | 5898 |
| 5910 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5899 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5911 Register value = locs()->in(0).reg(); | 5900 Register value = locs()->in(0).reg(); |
| 5912 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 5901 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
| 5913 __ CompareImmediate(value, Immediate(Smi::RawValue(cid_))); | 5902 __ CompareImmediate(value, Immediate(Smi::RawValue(cid_))); |
| 5914 __ j(NOT_ZERO, deopt); | 5903 __ j(NOT_ZERO, deopt); |
| 5915 } | 5904 } |
| 5916 | 5905 |
| 5917 | 5906 |
| 5918 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, | 5907 LocationSummary* GenericCheckBoundInstr::MakeLocationSummary(Zone* zone, |
| 5919 bool opt) const { | 5908 bool opt) const { |
| 5920 const intptr_t kNumInputs = 2; | 5909 const intptr_t kNumInputs = 2; |
| 5921 const intptr_t kNumTemps = 0; | 5910 const intptr_t kNumTemps = 0; |
| 5922 LocationSummary* locs = new(zone) LocationSummary( | 5911 LocationSummary* locs = new (zone) LocationSummary( |
| 5923 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); | 5912 zone, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); |
| 5924 locs->set_in(kLengthPos, Location::RequiresRegister()); | 5913 locs->set_in(kLengthPos, Location::RequiresRegister()); |
| 5925 locs->set_in(kIndexPos, Location::RequiresRegister()); | 5914 locs->set_in(kIndexPos, Location::RequiresRegister()); |
| 5926 return locs; | 5915 return locs; |
| 5927 } | 5916 } |
| 5928 | 5917 |
| 5929 | 5918 |
| 5930 class RangeErrorSlowPath : public SlowPathCode { | 5919 class RangeErrorSlowPath : public SlowPathCode { |
| 5931 public: | 5920 public: |
| 5932 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) | 5921 RangeErrorSlowPath(GenericCheckBoundInstr* instruction, intptr_t try_index) |
| 5933 : instruction_(instruction), try_index_(try_index) { } | 5922 : instruction_(instruction), try_index_(try_index) {} |
| 5934 | 5923 |
| 5935 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 5924 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5936 if (Assembler::EmittingComments()) { | 5925 if (Assembler::EmittingComments()) { |
| 5937 __ Comment("slow path check bound operation"); | 5926 __ Comment("slow path check bound operation"); |
| 5938 } | 5927 } |
| 5939 __ Bind(entry_label()); | 5928 __ Bind(entry_label()); |
| 5940 LocationSummary* locs = instruction_->locs(); | 5929 LocationSummary* locs = instruction_->locs(); |
| 5941 __ pushq(locs->in(0).reg()); | 5930 __ pushq(locs->in(0).reg()); |
| 5942 __ pushq(locs->in(1).reg()); | 5931 __ pushq(locs->in(1).reg()); |
| 5943 __ CallRuntime(kRangeErrorRuntimeEntry, 2); | 5932 __ CallRuntime(kRangeErrorRuntimeEntry, 2); |
| 5944 compiler->pc_descriptors_list()->AddDescriptor( | 5933 compiler->pc_descriptors_list()->AddDescriptor( |
| 5945 RawPcDescriptors::kOther, | 5934 RawPcDescriptors::kOther, compiler->assembler()->CodeSize(), |
| 5946 compiler->assembler()->CodeSize(), | 5935 instruction_->deopt_id(), instruction_->token_pos(), try_index_); |
| 5947 instruction_->deopt_id(), | |
| 5948 instruction_->token_pos(), | |
| 5949 try_index_); | |
| 5950 compiler->RecordSafepoint(locs, 2); | 5936 compiler->RecordSafepoint(locs, 2); |
| 5951 __ int3(); | 5937 __ int3(); |
| 5952 } | 5938 } |
| 5953 | 5939 |
| 5954 private: | 5940 private: |
| 5955 GenericCheckBoundInstr* instruction_; | 5941 GenericCheckBoundInstr* instruction_; |
| 5956 intptr_t try_index_; | 5942 intptr_t try_index_; |
| 5957 }; | 5943 }; |
| 5958 | 5944 |
| 5959 | 5945 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5972 } | 5958 } |
| 5973 __ cmpq(index, length); | 5959 __ cmpq(index, length); |
| 5974 __ j(ABOVE_EQUAL, slow_path->entry_label()); | 5960 __ j(ABOVE_EQUAL, slow_path->entry_label()); |
| 5975 } | 5961 } |
| 5976 | 5962 |
| 5977 | 5963 |
| 5978 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 5964 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
| 5979 bool opt) const { | 5965 bool opt) const { |
| 5980 const intptr_t kNumInputs = 2; | 5966 const intptr_t kNumInputs = 2; |
| 5981 const intptr_t kNumTemps = 0; | 5967 const intptr_t kNumTemps = 0; |
| 5982 LocationSummary* locs = new(zone) LocationSummary( | 5968 LocationSummary* locs = new (zone) |
| 5983 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5969 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5984 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); | 5970 locs->set_in(kLengthPos, Location::RegisterOrSmiConstant(length())); |
| 5985 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); | 5971 locs->set_in(kIndexPos, Location::RegisterOrSmiConstant(index())); |
| 5986 return locs; | 5972 return locs; |
| 5987 } | 5973 } |
| 5988 | 5974 |
| 5989 | 5975 |
| 5990 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5976 void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5991 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; | 5977 uint32_t flags = generalized_ ? ICData::kGeneralized : 0; |
| 5992 flags |= licm_hoisted_ ? ICData::kHoisted : 0; | 5978 flags |= licm_hoisted_ ? ICData::kHoisted : 0; |
| 5993 Label* deopt = compiler->AddDeoptStub( | 5979 Label* deopt = |
| 5994 deopt_id(), | 5980 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckArrayBound, flags); |
| 5995 ICData::kDeoptCheckArrayBound, | |
| 5996 flags); | |
| 5997 | 5981 |
| 5998 Location length_loc = locs()->in(kLengthPos); | 5982 Location length_loc = locs()->in(kLengthPos); |
| 5999 Location index_loc = locs()->in(kIndexPos); | 5983 Location index_loc = locs()->in(kIndexPos); |
| 6000 | 5984 |
| 6001 if (length_loc.IsConstant() && index_loc.IsConstant()) { | 5985 if (length_loc.IsConstant() && index_loc.IsConstant()) { |
| 6002 ASSERT((Smi::Cast(length_loc.constant()).Value() <= | 5986 ASSERT((Smi::Cast(length_loc.constant()).Value() <= |
| 6003 Smi::Cast(index_loc.constant()).Value()) || | 5987 Smi::Cast(index_loc.constant()).Value()) || |
| 6004 (Smi::Cast(index_loc.constant()).Value() < 0)); | 5988 (Smi::Cast(index_loc.constant()).Value() < 0)); |
| 6005 // Unconditionally deoptimize for constant bounds checks because they | 5989 // Unconditionally deoptimize for constant bounds checks because they |
| 6006 // only occur only when index is out-of-bounds. | 5990 // only occur only when index is out-of-bounds. |
| 6007 __ jmp(deopt); | 5991 __ jmp(deopt); |
| 6008 return; | 5992 return; |
| 6009 } | 5993 } |
| 6010 | 5994 |
| 6011 const intptr_t index_cid = index()->Type()->ToCid(); | 5995 const intptr_t index_cid = index()->Type()->ToCid(); |
| 6012 if (index_loc.IsConstant()) { | 5996 if (index_loc.IsConstant()) { |
| 6013 Register length = length_loc.reg(); | 5997 Register length = length_loc.reg(); |
| 6014 const Smi& index = Smi::Cast(index_loc.constant()); | 5998 const Smi& index = Smi::Cast(index_loc.constant()); |
| 6015 __ CompareImmediate( | 5999 __ CompareImmediate(length, |
| 6016 length, Immediate(reinterpret_cast<int64_t>(index.raw()))); | 6000 Immediate(reinterpret_cast<int64_t>(index.raw()))); |
| 6017 __ j(BELOW_EQUAL, deopt); | 6001 __ j(BELOW_EQUAL, deopt); |
| 6018 } else if (length_loc.IsConstant()) { | 6002 } else if (length_loc.IsConstant()) { |
| 6019 const Smi& length = Smi::Cast(length_loc.constant()); | 6003 const Smi& length = Smi::Cast(length_loc.constant()); |
| 6020 Register index = index_loc.reg(); | 6004 Register index = index_loc.reg(); |
| 6021 if (index_cid != kSmiCid) { | 6005 if (index_cid != kSmiCid) { |
| 6022 __ BranchIfNotSmi(index, deopt); | 6006 __ BranchIfNotSmi(index, deopt); |
| 6023 } | 6007 } |
| 6024 if (length.Value() == Smi::kMaxValue) { | 6008 if (length.Value() == Smi::kMaxValue) { |
| 6025 __ testq(index, index); | 6009 __ testq(index, index); |
| 6026 __ j(NEGATIVE, deopt); | 6010 __ j(NEGATIVE, deopt); |
| 6027 } else { | 6011 } else { |
| 6028 __ CompareImmediate( | 6012 __ CompareImmediate(index, |
| 6029 index, Immediate(reinterpret_cast<int64_t>(length.raw()))); | 6013 Immediate(reinterpret_cast<int64_t>(length.raw()))); |
| 6030 __ j(ABOVE_EQUAL, deopt); | 6014 __ j(ABOVE_EQUAL, deopt); |
| 6031 } | 6015 } |
| 6032 } else { | 6016 } else { |
| 6033 Register length = length_loc.reg(); | 6017 Register length = length_loc.reg(); |
| 6034 Register index = index_loc.reg(); | 6018 Register index = index_loc.reg(); |
| 6035 if (index_cid != kSmiCid) { | 6019 if (index_cid != kSmiCid) { |
| 6036 __ BranchIfNotSmi(index, deopt); | 6020 __ BranchIfNotSmi(index, deopt); |
| 6037 } | 6021 } |
| 6038 __ cmpq(index, length); | 6022 __ cmpq(index, length); |
| 6039 __ j(ABOVE_EQUAL, deopt); | 6023 __ j(ABOVE_EQUAL, deopt); |
| 6040 } | 6024 } |
| 6041 } | 6025 } |
| 6042 | 6026 |
| 6043 | 6027 |
| 6044 template<typename OperandType> | 6028 template <typename OperandType> |
| 6045 static void EmitInt64Arithmetic(FlowGraphCompiler* compiler, | 6029 static void EmitInt64Arithmetic(FlowGraphCompiler* compiler, |
| 6046 Token::Kind op_kind, | 6030 Token::Kind op_kind, |
| 6047 Register left, | 6031 Register left, |
| 6048 const OperandType& right, | 6032 const OperandType& right, |
| 6049 Label* deopt) { | 6033 Label* deopt) { |
| 6050 switch (op_kind) { | 6034 switch (op_kind) { |
| 6051 case Token::kADD: | 6035 case Token::kADD: |
| 6052 __ addq(left, right); | 6036 __ addq(left, right); |
| 6053 break; | 6037 break; |
| 6054 case Token::kSUB: | 6038 case Token::kSUB: |
| (...skipping 15 matching lines...) Expand all Loading... |
| 6070 UNREACHABLE(); | 6054 UNREACHABLE(); |
| 6071 } | 6055 } |
| 6072 if (deopt != NULL) __ j(OVERFLOW, deopt); | 6056 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 6073 } | 6057 } |
| 6074 | 6058 |
| 6075 | 6059 |
| 6076 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, | 6060 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Zone* zone, |
| 6077 bool opt) const { | 6061 bool opt) const { |
| 6078 const intptr_t kNumInputs = 2; | 6062 const intptr_t kNumInputs = 2; |
| 6079 const intptr_t kNumTemps = 0; | 6063 const intptr_t kNumTemps = 0; |
| 6080 LocationSummary* summary = new(zone) LocationSummary( | 6064 LocationSummary* summary = new (zone) |
| 6081 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6065 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6082 summary->set_in(0, Location::RequiresRegister()); | 6066 summary->set_in(0, Location::RequiresRegister()); |
| 6083 summary->set_in(1, Location::RequiresRegister()); | 6067 summary->set_in(1, Location::RequiresRegister()); |
| 6084 summary->set_out(0, Location::SameAsFirstInput()); | 6068 summary->set_out(0, Location::SameAsFirstInput()); |
| 6085 return summary; | 6069 return summary; |
| 6086 } | 6070 } |
| 6087 | 6071 |
| 6088 | 6072 |
| 6089 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6073 void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6090 const Register left = locs()->in(0).reg(); | 6074 const Register left = locs()->in(0).reg(); |
| 6091 const Register right = locs()->in(1).reg(); | 6075 const Register right = locs()->in(1).reg(); |
| 6092 const Register out = locs()->out(0).reg(); | 6076 const Register out = locs()->out(0).reg(); |
| 6093 | 6077 |
| 6094 ASSERT(out == left); | 6078 ASSERT(out == left); |
| 6095 | 6079 |
| 6096 Label* deopt = NULL; | 6080 Label* deopt = NULL; |
| 6097 if (CanDeoptimize()) { | 6081 if (CanDeoptimize()) { |
| 6098 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 6082 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 6099 } | 6083 } |
| 6100 | 6084 |
| 6101 EmitInt64Arithmetic(compiler, op_kind(), left, right, deopt); | 6085 EmitInt64Arithmetic(compiler, op_kind(), left, right, deopt); |
| 6102 } | 6086 } |
| 6103 | 6087 |
| 6104 | 6088 |
| 6105 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, | 6089 LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Zone* zone, |
| 6106 bool opt) const { | 6090 bool opt) const { |
| 6107 const intptr_t kNumInputs = 1; | 6091 const intptr_t kNumInputs = 1; |
| 6108 const intptr_t kNumTemps = 0; | 6092 const intptr_t kNumTemps = 0; |
| 6109 LocationSummary* summary = new(zone) LocationSummary( | 6093 LocationSummary* summary = new (zone) |
| 6110 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6094 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6111 summary->set_in(0, Location::RequiresRegister()); | 6095 summary->set_in(0, Location::RequiresRegister()); |
| 6112 summary->set_out(0, Location::SameAsFirstInput()); | 6096 summary->set_out(0, Location::SameAsFirstInput()); |
| 6113 return summary; | 6097 return summary; |
| 6114 } | 6098 } |
| 6115 | 6099 |
| 6116 | 6100 |
| 6117 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6101 void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6118 ASSERT(op_kind() == Token::kBIT_NOT); | 6102 ASSERT(op_kind() == Token::kBIT_NOT); |
| 6119 const Register left = locs()->in(0).reg(); | 6103 const Register left = locs()->in(0).reg(); |
| 6120 const Register out = locs()->out(0).reg(); | 6104 const Register out = locs()->out(0).reg(); |
| 6121 ASSERT(out == left); | 6105 ASSERT(out == left); |
| 6122 __ notq(left); | 6106 __ notq(left); |
| 6123 } | 6107 } |
| 6124 | 6108 |
| 6125 | 6109 |
| 6126 static const intptr_t kMintShiftCountLimit = 63; | 6110 static const intptr_t kMintShiftCountLimit = 63; |
| 6127 | 6111 |
| 6128 bool ShiftMintOpInstr::has_shift_count_check() const { | 6112 bool ShiftMintOpInstr::has_shift_count_check() const { |
| 6129 return !RangeUtils::IsWithin( | 6113 return !RangeUtils::IsWithin(right()->definition()->range(), 0, |
| 6130 right()->definition()->range(), 0, kMintShiftCountLimit); | 6114 kMintShiftCountLimit); |
| 6131 } | 6115 } |
| 6132 | 6116 |
| 6133 | 6117 |
| 6134 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, | 6118 LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Zone* zone, |
| 6135 bool opt) const { | 6119 bool opt) const { |
| 6136 const intptr_t kNumInputs = 2; | 6120 const intptr_t kNumInputs = 2; |
| 6137 const intptr_t kNumTemps = can_overflow() ? 1 : 0; | 6121 const intptr_t kNumTemps = can_overflow() ? 1 : 0; |
| 6138 LocationSummary* summary = new(zone) LocationSummary( | 6122 LocationSummary* summary = new (zone) |
| 6139 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6123 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6140 summary->set_in(0, Location::RequiresRegister()); | 6124 summary->set_in(0, Location::RequiresRegister()); |
| 6141 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 6125 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
| 6142 if (kNumTemps > 0) { | 6126 if (kNumTemps > 0) { |
| 6143 summary->set_temp(0, Location::RequiresRegister()); | 6127 summary->set_temp(0, Location::RequiresRegister()); |
| 6144 } | 6128 } |
| 6145 summary->set_out(0, Location::SameAsFirstInput()); | 6129 summary->set_out(0, Location::SameAsFirstInput()); |
| 6146 return summary; | 6130 return summary; |
| 6147 } | 6131 } |
| 6148 | 6132 |
| 6149 | 6133 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6231 | 6215 |
| 6232 CompileType UnaryUint32OpInstr::ComputeType() const { | 6216 CompileType UnaryUint32OpInstr::ComputeType() const { |
| 6233 return CompileType::FromCid(kSmiCid); | 6217 return CompileType::FromCid(kSmiCid); |
| 6234 } | 6218 } |
| 6235 | 6219 |
| 6236 | 6220 |
| 6237 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 6221 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 6238 bool opt) const { | 6222 bool opt) const { |
| 6239 const intptr_t kNumInputs = 2; | 6223 const intptr_t kNumInputs = 2; |
| 6240 const intptr_t kNumTemps = 0; | 6224 const intptr_t kNumTemps = 0; |
| 6241 LocationSummary* summary = new(zone) LocationSummary( | 6225 LocationSummary* summary = new (zone) |
| 6242 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6226 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6243 summary->set_in(0, Location::RequiresRegister()); | 6227 summary->set_in(0, Location::RequiresRegister()); |
| 6244 summary->set_in(1, Location::RequiresRegister()); | 6228 summary->set_in(1, Location::RequiresRegister()); |
| 6245 summary->set_out(0, Location::SameAsFirstInput()); | 6229 summary->set_out(0, Location::SameAsFirstInput()); |
| 6246 return summary; | 6230 return summary; |
| 6247 } | 6231 } |
| 6248 | 6232 |
| 6249 | 6233 |
| 6250 template<typename OperandType> | 6234 template <typename OperandType> |
| 6251 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, | 6235 static void EmitIntegerArithmetic(FlowGraphCompiler* compiler, |
| 6252 Token::Kind op_kind, | 6236 Token::Kind op_kind, |
| 6253 Register left, | 6237 Register left, |
| 6254 const OperandType& right, | 6238 const OperandType& right, |
| 6255 Label* deopt) { | 6239 Label* deopt) { |
| 6256 switch (op_kind) { | 6240 switch (op_kind) { |
| 6257 case Token::kADD: | 6241 case Token::kADD: |
| 6258 __ addl(left, right); | 6242 __ addl(left, right); |
| 6259 break; | 6243 break; |
| 6260 case Token::kSUB: | 6244 case Token::kSUB: |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6296 default: | 6280 default: |
| 6297 UNREACHABLE(); | 6281 UNREACHABLE(); |
| 6298 } | 6282 } |
| 6299 } | 6283 } |
| 6300 | 6284 |
| 6301 | 6285 |
| 6302 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, | 6286 LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 6303 bool opt) const { | 6287 bool opt) const { |
| 6304 const intptr_t kNumInputs = 2; | 6288 const intptr_t kNumInputs = 2; |
| 6305 const intptr_t kNumTemps = 0; | 6289 const intptr_t kNumTemps = 0; |
| 6306 LocationSummary* summary = new(zone) LocationSummary( | 6290 LocationSummary* summary = new (zone) |
| 6307 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6291 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6308 summary->set_in(0, Location::RequiresRegister()); | 6292 summary->set_in(0, Location::RequiresRegister()); |
| 6309 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); | 6293 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX)); |
| 6310 summary->set_out(0, Location::SameAsFirstInput()); | 6294 summary->set_out(0, Location::SameAsFirstInput()); |
| 6311 return summary; | 6295 return summary; |
| 6312 } | 6296 } |
| 6313 | 6297 |
| 6314 | 6298 |
| 6315 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6299 void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6316 const intptr_t kShifterLimit = 31; | 6300 const intptr_t kShifterLimit = 31; |
| 6317 | 6301 |
| 6318 Register left = locs()->in(0).reg(); | 6302 Register left = locs()->in(0).reg(); |
| 6319 Register out = locs()->out(0).reg(); | 6303 Register out = locs()->out(0).reg(); |
| 6320 ASSERT(left == out); | 6304 ASSERT(left == out); |
| 6321 | 6305 |
| 6322 | 6306 |
| 6323 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); | 6307 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp); |
| 6324 | 6308 |
| 6325 if (locs()->in(1).IsConstant()) { | 6309 if (locs()->in(1).IsConstant()) { |
| 6326 // Shifter is constant. | 6310 // Shifter is constant. |
| 6327 | 6311 |
| 6328 const Object& constant = locs()->in(1).constant(); | 6312 const Object& constant = locs()->in(1).constant(); |
| 6329 ASSERT(constant.IsSmi()); | 6313 ASSERT(constant.IsSmi()); |
| 6330 const intptr_t shift_value = Smi::Cast(constant).Value(); | 6314 const intptr_t shift_value = Smi::Cast(constant).Value(); |
| 6331 | 6315 |
| 6332 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). | 6316 // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit). |
| 6333 switch (op_kind()) { | 6317 switch (op_kind()) { |
| 6334 case Token::kSHR: | 6318 case Token::kSHR: |
| 6335 __ shrl(left, Immediate(shift_value)); | 6319 __ shrl(left, Immediate(shift_value)); |
| 6336 break; | 6320 break; |
| 6337 case Token::kSHL: | 6321 case Token::kSHL: |
| 6338 __ shll(left, Immediate(shift_value)); | 6322 __ shll(left, Immediate(shift_value)); |
| 6339 break; | 6323 break; |
| 6340 default: | 6324 default: |
| 6341 UNREACHABLE(); | 6325 UNREACHABLE(); |
| 6342 } | 6326 } |
| 6343 return; | 6327 return; |
| 6344 } | 6328 } |
| 6345 | 6329 |
| 6346 // Non constant shift value. | 6330 // Non constant shift value. |
| 6347 | 6331 |
| 6348 Register shifter = locs()->in(1).reg(); | 6332 Register shifter = locs()->in(1).reg(); |
| 6349 ASSERT(shifter == RCX); | 6333 ASSERT(shifter == RCX); |
| 6350 | 6334 |
| 6351 Label done; | 6335 Label done; |
| 6352 Label zero; | 6336 Label zero; |
| 6353 | 6337 |
| 6354 // TODO(johnmccutchan): Use range information to avoid these checks. | 6338 // TODO(johnmccutchan): Use range information to avoid these checks. |
| 6355 __ SmiUntag(shifter); | 6339 __ SmiUntag(shifter); |
| 6356 __ cmpq(shifter, Immediate(0)); | 6340 __ cmpq(shifter, Immediate(0)); |
| 6357 // If shift value is < 0, deoptimize. | 6341 // If shift value is < 0, deoptimize. |
| 6358 __ j(NEGATIVE, deopt); | 6342 __ j(NEGATIVE, deopt); |
| 6359 __ cmpq(shifter, Immediate(kShifterLimit)); | 6343 __ cmpq(shifter, Immediate(kShifterLimit)); |
| 6360 // If shift value is >= 32, return zero. | 6344 // If shift value is >= 32, return zero. |
| 6361 __ j(ABOVE, &zero); | 6345 __ j(ABOVE, &zero); |
| 6362 | 6346 |
| 6363 // Do the shift. | 6347 // Do the shift. |
| 6364 switch (op_kind()) { | 6348 switch (op_kind()) { |
| 6365 case Token::kSHR: | 6349 case Token::kSHR: |
| 6366 __ shrl(left, shifter); | 6350 __ shrl(left, shifter); |
| 6367 __ jmp(&done); | 6351 __ jmp(&done); |
| 6368 break; | 6352 break; |
| 6369 case Token::kSHL: | 6353 case Token::kSHL: |
| 6370 __ shll(left, shifter); | 6354 __ shll(left, shifter); |
| 6371 __ jmp(&done); | 6355 __ jmp(&done); |
| 6372 break; | 6356 break; |
| 6373 default: | 6357 default: |
| 6374 UNREACHABLE(); | 6358 UNREACHABLE(); |
| 6375 } | 6359 } |
| 6376 | 6360 |
| 6377 __ Bind(&zero); | 6361 __ Bind(&zero); |
| 6378 // Shift was greater than 31 bits, just return zero. | 6362 // Shift was greater than 31 bits, just return zero. |
| 6379 __ xorq(left, left); | 6363 __ xorq(left, left); |
| 6380 | 6364 |
| 6381 // Exit path. | 6365 // Exit path. |
| 6382 __ Bind(&done); | 6366 __ Bind(&done); |
| 6383 } | 6367 } |
| 6384 | 6368 |
| 6385 | 6369 |
| 6386 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, | 6370 LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone, |
| 6387 bool opt) const { | 6371 bool opt) const { |
| 6388 const intptr_t kNumInputs = 1; | 6372 const intptr_t kNumInputs = 1; |
| 6389 const intptr_t kNumTemps = 0; | 6373 const intptr_t kNumTemps = 0; |
| 6390 LocationSummary* summary = new(zone) LocationSummary( | 6374 LocationSummary* summary = new (zone) |
| 6391 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6375 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6392 summary->set_in(0, Location::RequiresRegister()); | 6376 summary->set_in(0, Location::RequiresRegister()); |
| 6393 summary->set_out(0, Location::SameAsFirstInput()); | 6377 summary->set_out(0, Location::SameAsFirstInput()); |
| 6394 return summary; | 6378 return summary; |
| 6395 } | 6379 } |
| 6396 | 6380 |
| 6397 | 6381 |
| 6398 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6382 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6399 Register out = locs()->out(0).reg(); | 6383 Register out = locs()->out(0).reg(); |
| 6400 ASSERT(locs()->in(0).reg() == out); | 6384 ASSERT(locs()->in(0).reg() == out); |
| 6401 | 6385 |
| 6402 ASSERT(op_kind() == Token::kBIT_NOT); | 6386 ASSERT(op_kind() == Token::kBIT_NOT); |
| 6403 | 6387 |
| 6404 __ notl(out); | 6388 __ notl(out); |
| 6405 } | 6389 } |
| 6406 | 6390 |
| 6407 | 6391 |
| 6408 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 6392 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
| 6409 | 6393 |
| 6410 | 6394 |
| 6411 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, | 6395 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone, |
| 6412 bool opt) const { | 6396 bool opt) const { |
| 6413 const intptr_t kNumInputs = 1; | 6397 const intptr_t kNumInputs = 1; |
| 6414 const intptr_t kNumTemps = 0; | 6398 const intptr_t kNumTemps = 0; |
| 6415 LocationSummary* summary = new(zone) LocationSummary( | 6399 LocationSummary* summary = new (zone) |
| 6416 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6400 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6417 if (from() == kUnboxedMint) { | 6401 if (from() == kUnboxedMint) { |
| 6418 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 6402 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 6419 summary->set_in(0, Location::RequiresRegister()); | 6403 summary->set_in(0, Location::RequiresRegister()); |
| 6420 summary->set_out(0, Location::SameAsFirstInput()); | 6404 summary->set_out(0, Location::SameAsFirstInput()); |
| 6421 } else if (to() == kUnboxedMint) { | 6405 } else if (to() == kUnboxedMint) { |
| 6422 ASSERT((from() == kUnboxedInt32) || (from() == kUnboxedUint32)); | 6406 ASSERT((from() == kUnboxedInt32) || (from() == kUnboxedUint32)); |
| 6423 summary->set_in(0, Location::RequiresRegister()); | 6407 summary->set_in(0, Location::RequiresRegister()); |
| 6424 summary->set_out(0, Location::SameAsFirstInput()); | 6408 summary->set_out(0, Location::SameAsFirstInput()); |
| 6425 } else { | 6409 } else { |
| 6426 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | 6410 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6480 // Sign extend. | 6464 // Sign extend. |
| 6481 ASSERT(from() == kUnboxedInt32); | 6465 ASSERT(from() == kUnboxedInt32); |
| 6482 __ movsxd(out, value); | 6466 __ movsxd(out, value); |
| 6483 } | 6467 } |
| 6484 } else { | 6468 } else { |
| 6485 UNREACHABLE(); | 6469 UNREACHABLE(); |
| 6486 } | 6470 } |
| 6487 } | 6471 } |
| 6488 | 6472 |
| 6489 | 6473 |
| 6490 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, | 6474 LocationSummary* ThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6491 bool opt) const { | 6475 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 6492 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
| 6493 } | 6476 } |
| 6494 | 6477 |
| 6495 | 6478 |
| 6496 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6479 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6497 compiler->GenerateRuntimeCall(token_pos(), | 6480 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kThrowRuntimeEntry, 1, |
| 6498 deopt_id(), | |
| 6499 kThrowRuntimeEntry, | |
| 6500 1, | |
| 6501 locs()); | 6481 locs()); |
| 6502 __ int3(); | 6482 __ int3(); |
| 6503 } | 6483 } |
| 6504 | 6484 |
| 6505 | 6485 |
| 6506 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, | 6486 LocationSummary* ReThrowInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6507 bool opt) const { | 6487 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); |
| 6508 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kCall); | |
| 6509 } | 6488 } |
| 6510 | 6489 |
| 6511 | 6490 |
| 6512 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6491 void ReThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6513 compiler->SetNeedsStacktrace(catch_try_index()); | 6492 compiler->SetNeedsStacktrace(catch_try_index()); |
| 6514 compiler->GenerateRuntimeCall(token_pos(), | 6493 compiler->GenerateRuntimeCall(token_pos(), deopt_id(), kReThrowRuntimeEntry, |
| 6515 deopt_id(), | 6494 2, locs()); |
| 6516 kReThrowRuntimeEntry, | |
| 6517 2, | |
| 6518 locs()); | |
| 6519 __ int3(); | 6495 __ int3(); |
| 6520 } | 6496 } |
| 6521 | 6497 |
| 6522 | 6498 |
| 6523 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, | 6499 LocationSummary* StopInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6524 bool opt) const { | 6500 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 6525 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
| 6526 } | 6501 } |
| 6527 | 6502 |
| 6528 | 6503 |
| 6529 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6504 void StopInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6530 __ Stop(message()); | 6505 __ Stop(message()); |
| 6531 } | 6506 } |
| 6532 | 6507 |
| 6533 | 6508 |
| 6534 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6509 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6535 if (!compiler->CanFallThroughTo(normal_entry())) { | 6510 if (!compiler->CanFallThroughTo(normal_entry())) { |
| 6536 __ jmp(compiler->GetJumpLabel(normal_entry())); | 6511 __ jmp(compiler->GetJumpLabel(normal_entry())); |
| 6537 } | 6512 } |
| 6538 } | 6513 } |
| 6539 | 6514 |
| 6540 | 6515 |
| 6541 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, | 6516 LocationSummary* GotoInstr::MakeLocationSummary(Zone* zone, bool opt) const { |
| 6542 bool opt) const { | 6517 return new (zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); |
| 6543 return new(zone) LocationSummary(zone, 0, 0, LocationSummary::kNoCall); | |
| 6544 } | 6518 } |
| 6545 | 6519 |
| 6546 | 6520 |
| 6547 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6521 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6548 if (!compiler->is_optimizing()) { | 6522 if (!compiler->is_optimizing()) { |
| 6549 if (FLAG_reorder_basic_blocks) { | 6523 if (FLAG_reorder_basic_blocks) { |
| 6550 compiler->EmitEdgeCounter(block()->preorder_number()); | 6524 compiler->EmitEdgeCounter(block()->preorder_number()); |
| 6551 } | 6525 } |
| 6552 // Add a deoptimization descriptor for deoptimizing instructions that | 6526 // Add a deoptimization descriptor for deoptimizing instructions that |
| 6553 // may be inserted before this instruction. | 6527 // may be inserted before this instruction. |
| 6554 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 6528 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(), |
| 6555 GetDeoptId(), | |
| 6556 TokenPosition::kNoSource); | 6529 TokenPosition::kNoSource); |
| 6557 } | 6530 } |
| 6558 if (HasParallelMove()) { | 6531 if (HasParallelMove()) { |
| 6559 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 6532 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 6560 } | 6533 } |
| 6561 | 6534 |
| 6562 // We can fall through if the successor is the next block in the list. | 6535 // We can fall through if the successor is the next block in the list. |
| 6563 // Otherwise, we need a jump. | 6536 // Otherwise, we need a jump. |
| 6564 if (!compiler->CanFallThroughTo(successor())) { | 6537 if (!compiler->CanFallThroughTo(successor())) { |
| 6565 __ jmp(compiler->GetJumpLabel(successor())); | 6538 __ jmp(compiler->GetJumpLabel(successor())); |
| 6566 } | 6539 } |
| 6567 } | 6540 } |
| 6568 | 6541 |
| 6569 | 6542 |
| 6570 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, | 6543 LocationSummary* IndirectGotoInstr::MakeLocationSummary(Zone* zone, |
| 6571 bool opt) const { | 6544 bool opt) const { |
| 6572 const intptr_t kNumInputs = 1; | 6545 const intptr_t kNumInputs = 1; |
| 6573 const intptr_t kNumTemps = 1; | 6546 const intptr_t kNumTemps = 1; |
| 6574 | 6547 |
| 6575 LocationSummary* summary = new(zone) LocationSummary( | 6548 LocationSummary* summary = new (zone) |
| 6576 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6549 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6577 | 6550 |
| 6578 summary->set_in(0, Location::RequiresRegister()); | 6551 summary->set_in(0, Location::RequiresRegister()); |
| 6579 summary->set_temp(0, Location::RequiresRegister()); | 6552 summary->set_temp(0, Location::RequiresRegister()); |
| 6580 | 6553 |
| 6581 return summary; | 6554 return summary; |
| 6582 } | 6555 } |
| 6583 | 6556 |
| 6584 | 6557 |
| 6585 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6558 void IndirectGotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6586 Register offset_reg = locs()->in(0).reg(); | 6559 Register offset_reg = locs()->in(0).reg(); |
| 6587 Register target_address_reg = locs()->temp(0).reg(); | 6560 Register target_address_reg = locs()->temp(0).reg(); |
| 6588 | 6561 |
| 6589 { | 6562 { |
| 6590 const intptr_t kRIPRelativeLeaqSize = 7; | 6563 const intptr_t kRIPRelativeLeaqSize = 7; |
| 6591 const intptr_t entry_to_rip_offset = | 6564 const intptr_t entry_to_rip_offset = __ CodeSize() + kRIPRelativeLeaqSize; |
| 6592 __ CodeSize() + kRIPRelativeLeaqSize; | |
| 6593 __ leaq(target_address_reg, | 6565 __ leaq(target_address_reg, |
| 6594 Address::AddressRIPRelative(-entry_to_rip_offset)); | 6566 Address::AddressRIPRelative(-entry_to_rip_offset)); |
| 6595 ASSERT(__ CodeSize() == entry_to_rip_offset); | 6567 ASSERT(__ CodeSize() == entry_to_rip_offset); |
| 6596 } | 6568 } |
| 6597 | 6569 |
| 6598 // Load from [current frame pointer] + kPcMarkerSlotFromFp. | 6570 // Load from [current frame pointer] + kPcMarkerSlotFromFp. |
| 6599 | 6571 |
| 6600 // Calculate the final absolute address. | 6572 // Calculate the final absolute address. |
| 6601 if (offset()->definition()->representation() == kTagged) { | 6573 if (offset()->definition()->representation() == kTagged) { |
| 6602 __ SmiUntag(offset_reg); | 6574 __ SmiUntag(offset_reg); |
| 6603 } | 6575 } |
| 6604 __ addq(target_address_reg, offset_reg); | 6576 __ addq(target_address_reg, offset_reg); |
| 6605 | 6577 |
| 6606 // Jump to the absolute address. | 6578 // Jump to the absolute address. |
| 6607 __ jmp(target_address_reg); | 6579 __ jmp(target_address_reg); |
| 6608 } | 6580 } |
| 6609 | 6581 |
| 6610 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, | 6582 LocationSummary* StrictCompareInstr::MakeLocationSummary(Zone* zone, |
| 6611 bool opt) const { | 6583 bool opt) const { |
| 6612 const intptr_t kNumInputs = 2; | 6584 const intptr_t kNumInputs = 2; |
| 6613 const intptr_t kNumTemps = 0; | 6585 const intptr_t kNumTemps = 0; |
| 6614 if (needs_number_check()) { | 6586 if (needs_number_check()) { |
| 6615 LocationSummary* locs = new(zone) LocationSummary( | 6587 LocationSummary* locs = new (zone) |
| 6616 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6588 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 6617 locs->set_in(0, Location::RegisterLocation(RAX)); | 6589 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 6618 locs->set_in(1, Location::RegisterLocation(RCX)); | 6590 locs->set_in(1, Location::RegisterLocation(RCX)); |
| 6619 locs->set_out(0, Location::RegisterLocation(RAX)); | 6591 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 6620 return locs; | 6592 return locs; |
| 6621 } | 6593 } |
| 6622 LocationSummary* locs = new(zone) LocationSummary( | 6594 LocationSummary* locs = new (zone) |
| 6623 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6595 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 6624 locs->set_in(0, Location::RegisterOrConstant(left())); | 6596 locs->set_in(0, Location::RegisterOrConstant(left())); |
| 6625 // Only one of the inputs can be a constant. Choose register if the first one | 6597 // Only one of the inputs can be a constant. Choose register if the first one |
| 6626 // is a constant. | 6598 // is a constant. |
| 6627 locs->set_in(1, locs->in(0).IsConstant() | 6599 locs->set_in(1, locs->in(0).IsConstant() |
| 6628 ? Location::RequiresRegister() | 6600 ? Location::RequiresRegister() |
| 6629 : Location::RegisterOrConstant(right())); | 6601 : Location::RegisterOrConstant(right())); |
| 6630 locs->set_out(0, Location::RequiresRegister()); | 6602 locs->set_out(0, Location::RequiresRegister()); |
| 6631 return locs; | 6603 return locs; |
| 6632 } | 6604 } |
| 6633 | 6605 |
| 6634 | 6606 |
| 6635 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 6607 Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 6636 BranchLabels labels) { | 6608 BranchLabels labels) { |
| 6637 Location left = locs()->in(0); | 6609 Location left = locs()->in(0); |
| 6638 Location right = locs()->in(1); | 6610 Location right = locs()->in(1); |
| 6639 ASSERT(!left.IsConstant() || !right.IsConstant()); | 6611 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 6640 Condition true_condition; | 6612 Condition true_condition; |
| 6641 if (left.IsConstant()) { | 6613 if (left.IsConstant()) { |
| 6642 true_condition = compiler->EmitEqualityRegConstCompare(right.reg(), | 6614 true_condition = compiler->EmitEqualityRegConstCompare( |
| 6643 left.constant(), | 6615 right.reg(), left.constant(), needs_number_check(), token_pos()); |
| 6644 needs_number_check(), | |
| 6645 token_pos()); | |
| 6646 } else if (right.IsConstant()) { | 6616 } else if (right.IsConstant()) { |
| 6647 true_condition = compiler->EmitEqualityRegConstCompare(left.reg(), | 6617 true_condition = compiler->EmitEqualityRegConstCompare( |
| 6648 right.constant(), | 6618 left.reg(), right.constant(), needs_number_check(), token_pos()); |
| 6649 needs_number_check(), | |
| 6650 token_pos()); | |
| 6651 } else { | 6619 } else { |
| 6652 true_condition = compiler->EmitEqualityRegRegCompare(left.reg(), | 6620 true_condition = compiler->EmitEqualityRegRegCompare( |
| 6653 right.reg(), | 6621 left.reg(), right.reg(), needs_number_check(), token_pos()); |
| 6654 needs_number_check(), | |
| 6655 token_pos()); | |
| 6656 } | 6622 } |
| 6657 if (kind() != Token::kEQ_STRICT) { | 6623 if (kind() != Token::kEQ_STRICT) { |
| 6658 ASSERT(kind() == Token::kNE_STRICT); | 6624 ASSERT(kind() == Token::kNE_STRICT); |
| 6659 true_condition = NegateCondition(true_condition); | 6625 true_condition = NegateCondition(true_condition); |
| 6660 } | 6626 } |
| 6661 return true_condition; | 6627 return true_condition; |
| 6662 } | 6628 } |
| 6663 | 6629 |
| 6664 | 6630 |
| 6665 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6631 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6666 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 6632 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 6667 | 6633 |
| 6668 Label is_true, is_false; | 6634 Label is_true, is_false; |
| 6669 BranchLabels labels = { &is_true, &is_false, &is_false }; | 6635 BranchLabels labels = {&is_true, &is_false, &is_false}; |
| 6670 | 6636 |
| 6671 Condition true_condition = EmitComparisonCode(compiler, labels); | 6637 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 6672 EmitBranchOnCondition(compiler, true_condition, labels); | 6638 EmitBranchOnCondition(compiler, true_condition, labels); |
| 6673 | 6639 |
| 6674 Register result = locs()->out(0).reg(); | 6640 Register result = locs()->out(0).reg(); |
| 6675 Label done; | 6641 Label done; |
| 6676 __ Bind(&is_false); | 6642 __ Bind(&is_false); |
| 6677 __ LoadObject(result, Bool::False()); | 6643 __ LoadObject(result, Bool::False()); |
| 6678 __ jmp(&done); | 6644 __ jmp(&done); |
| 6679 __ Bind(&is_true); | 6645 __ Bind(&is_true); |
| 6680 __ LoadObject(result, Bool::True()); | 6646 __ LoadObject(result, Bool::True()); |
| 6681 __ Bind(&done); | 6647 __ Bind(&done); |
| 6682 } | 6648 } |
| 6683 | 6649 |
| 6684 | 6650 |
| 6685 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 6651 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 6686 BranchInstr* branch) { | 6652 BranchInstr* branch) { |
| 6687 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 6653 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 6688 | 6654 |
| 6689 BranchLabels labels = compiler->CreateBranchLabels(branch); | 6655 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 6690 Condition true_condition = EmitComparisonCode(compiler, labels); | 6656 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 6691 EmitBranchOnCondition(compiler, true_condition, labels); | 6657 EmitBranchOnCondition(compiler, true_condition, labels); |
| 6692 } | 6658 } |
| 6693 | 6659 |
| 6694 | 6660 |
| 6695 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, | 6661 LocationSummary* ClosureCallInstr::MakeLocationSummary(Zone* zone, |
| 6696 bool opt) const { | 6662 bool opt) const { |
| 6697 const intptr_t kNumInputs = 1; | 6663 const intptr_t kNumInputs = 1; |
| 6698 const intptr_t kNumTemps = 0; | 6664 const intptr_t kNumTemps = 0; |
| 6699 LocationSummary* summary = new(zone) LocationSummary( | 6665 LocationSummary* summary = new (zone) |
| 6700 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6666 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 6701 summary->set_in(0, Location::RegisterLocation(RAX)); // Function. | 6667 summary->set_in(0, Location::RegisterLocation(RAX)); // Function. |
| 6702 summary->set_out(0, Location::RegisterLocation(RAX)); | 6668 summary->set_out(0, Location::RegisterLocation(RAX)); |
| 6703 return summary; | 6669 return summary; |
| 6704 } | 6670 } |
| 6705 | 6671 |
| 6706 | 6672 |
| 6707 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6673 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6708 // Arguments descriptor is expected in R10. | 6674 // Arguments descriptor is expected in R10. |
| 6709 intptr_t argument_count = ArgumentCount(); | 6675 intptr_t argument_count = ArgumentCount(); |
| 6710 const Array& arguments_descriptor = | 6676 const Array& arguments_descriptor = Array::ZoneHandle( |
| 6711 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 6677 ArgumentsDescriptor::New(argument_count, argument_names())); |
| 6712 argument_names())); | |
| 6713 __ LoadObject(R10, arguments_descriptor); | 6678 __ LoadObject(R10, arguments_descriptor); |
| 6714 | 6679 |
| 6715 // Function in RAX. | 6680 // Function in RAX. |
| 6716 ASSERT(locs()->in(0).reg() == RAX); | 6681 ASSERT(locs()->in(0).reg() == RAX); |
| 6717 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); | 6682 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); |
| 6718 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); | 6683 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); |
| 6719 | 6684 |
| 6720 // RAX: Function. | 6685 // RAX: Function. |
| 6721 // R10: Arguments descriptor array. | 6686 // R10: Arguments descriptor array. |
| 6722 // RBX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). | 6687 // RBX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). |
| 6723 __ xorq(RBX, RBX); | 6688 __ xorq(RBX, RBX); |
| 6724 __ call(RCX); | 6689 __ call(RCX); |
| 6725 compiler->RecordSafepoint(locs()); | 6690 compiler->RecordSafepoint(locs()); |
| 6726 // Marks either the continuation point in unoptimized code or the | 6691 // Marks either the continuation point in unoptimized code or the |
| 6727 // deoptimization point in optimized code, after call. | 6692 // deoptimization point in optimized code, after call. |
| 6728 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); | 6693 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id()); |
| 6729 if (compiler->is_optimizing()) { | 6694 if (compiler->is_optimizing()) { |
| 6730 compiler->AddDeoptIndexAtCall(deopt_id_after); | 6695 compiler->AddDeoptIndexAtCall(deopt_id_after); |
| 6731 } | 6696 } |
| 6732 // Add deoptimization continuation point after the call and before the | 6697 // Add deoptimization continuation point after the call and before the |
| 6733 // arguments are removed. | 6698 // arguments are removed. |
| 6734 // In optimized code this descriptor is needed for exception handling. | 6699 // In optimized code this descriptor is needed for exception handling. |
| 6735 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 6700 compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, |
| 6736 deopt_id_after, | |
| 6737 token_pos()); | 6701 token_pos()); |
| 6738 __ Drop(argument_count); | 6702 __ Drop(argument_count); |
| 6739 } | 6703 } |
| 6740 | 6704 |
| 6741 | 6705 |
| 6742 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, | 6706 LocationSummary* BooleanNegateInstr::MakeLocationSummary(Zone* zone, |
| 6743 bool opt) const { | 6707 bool opt) const { |
| 6744 return LocationSummary::Make(zone, | 6708 return LocationSummary::Make(zone, 1, Location::RequiresRegister(), |
| 6745 1, | |
| 6746 Location::RequiresRegister(), | |
| 6747 LocationSummary::kNoCall); | 6709 LocationSummary::kNoCall); |
| 6748 } | 6710 } |
| 6749 | 6711 |
| 6750 | 6712 |
| 6751 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6713 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6752 Register value = locs()->in(0).reg(); | 6714 Register value = locs()->in(0).reg(); |
| 6753 Register result = locs()->out(0).reg(); | 6715 Register result = locs()->out(0).reg(); |
| 6754 | 6716 |
| 6755 Label done; | 6717 Label done; |
| 6756 __ LoadObject(result, Bool::True()); | 6718 __ LoadObject(result, Bool::True()); |
| 6757 __ CompareRegisters(result, value); | 6719 __ CompareRegisters(result, value); |
| 6758 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 6720 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 6759 __ LoadObject(result, Bool::False()); | 6721 __ LoadObject(result, Bool::False()); |
| 6760 __ Bind(&done); | 6722 __ Bind(&done); |
| 6761 } | 6723 } |
| 6762 | 6724 |
| 6763 | 6725 |
| 6764 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 6726 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
| 6765 bool opt) const { | 6727 bool opt) const { |
| 6766 return MakeCallSummary(zone); | 6728 return MakeCallSummary(zone); |
| 6767 } | 6729 } |
| 6768 | 6730 |
| 6769 | 6731 |
| 6770 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6732 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6771 const Code& stub = Code::ZoneHandle( | 6733 const Code& stub = Code::ZoneHandle( |
| 6772 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); | 6734 compiler->zone(), StubCode::GetAllocationStubForClass(cls())); |
| 6773 const StubEntry stub_entry(stub); | 6735 const StubEntry stub_entry(stub); |
| 6774 compiler->GenerateCall(token_pos(), | 6736 compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther, |
| 6775 stub_entry, | |
| 6776 RawPcDescriptors::kOther, | |
| 6777 locs()); | 6737 locs()); |
| 6778 compiler->AddStubCallTarget(stub); | 6738 compiler->AddStubCallTarget(stub); |
| 6779 __ Drop(ArgumentCount()); // Discard arguments. | 6739 __ Drop(ArgumentCount()); // Discard arguments. |
| 6780 } | 6740 } |
| 6781 | 6741 |
| 6782 | 6742 |
| 6783 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6743 void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6784 ASSERT(!compiler->is_optimizing()); | 6744 ASSERT(!compiler->is_optimizing()); |
| 6785 __ CallPatchable(*StubCode::DebugStepCheck_entry()); | 6745 __ CallPatchable(*StubCode::DebugStepCheck_entry()); |
| 6786 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); | 6746 compiler->AddCurrentDescriptor(stub_kind_, Thread::kNoDeoptId, token_pos()); |
| 6787 compiler->RecordSafepoint(locs()); | 6747 compiler->RecordSafepoint(locs()); |
| 6788 } | 6748 } |
| 6789 | 6749 |
| 6790 | 6750 |
| 6791 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary( | 6751 LocationSummary* GrowRegExpStackInstr::MakeLocationSummary(Zone* zone, |
| 6792 Zone* zone, bool opt) const { | 6752 bool opt) const { |
| 6793 const intptr_t kNumInputs = 1; | 6753 const intptr_t kNumInputs = 1; |
| 6794 const intptr_t kNumTemps = 0; | 6754 const intptr_t kNumTemps = 0; |
| 6795 LocationSummary* locs = new(zone) LocationSummary( | 6755 LocationSummary* locs = new (zone) |
| 6796 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6756 LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 6797 locs->set_in(0, Location::RegisterLocation(RAX)); | 6757 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 6798 locs->set_out(0, Location::RegisterLocation(RAX)); | 6758 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 6799 return locs; | 6759 return locs; |
| 6800 } | 6760 } |
| 6801 | 6761 |
| 6802 | 6762 |
| 6803 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6763 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6804 const Register typed_data = locs()->in(0).reg(); | 6764 const Register typed_data = locs()->in(0).reg(); |
| 6805 const Register result = locs()->out(0).reg(); | 6765 const Register result = locs()->out(0).reg(); |
| 6806 __ PushObject(Object::null_object()); | 6766 __ PushObject(Object::null_object()); |
| 6807 __ pushq(typed_data); | 6767 __ pushq(typed_data); |
| 6808 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, | 6768 compiler->GenerateRuntimeCall(TokenPosition::kNoSource, deopt_id(), |
| 6809 deopt_id(), | 6769 kGrowRegExpStackRuntimeEntry, 1, locs()); |
| 6810 kGrowRegExpStackRuntimeEntry, | |
| 6811 1, | |
| 6812 locs()); | |
| 6813 __ Drop(1); | 6770 __ Drop(1); |
| 6814 __ popq(result); | 6771 __ popq(result); |
| 6815 } | 6772 } |
| 6816 | 6773 |
| 6817 | 6774 |
| 6818 } // namespace dart | 6775 } // namespace dart |
| 6819 | 6776 |
| 6820 #undef __ | 6777 #undef __ |
| 6821 | 6778 |
| 6822 #endif // defined TARGET_ARCH_X64 | 6779 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |